一、Vue2 项目环境搭建

1. 环境准备
  • 安装 Node.js:推荐使用 nvm 管理多版本 Node

    # 安装Node 16.20.2
    nvm install 16.20.2
    # 切换至指定版本
    nvm use 16.20.2
    # 验证安装
    node -v && npm -v
    
  • 安装 Vue CLI 脚手架

    # 国内镜像源安装
    npm install --registry=https://registry.npmmirror.com @vue/cli -g
    # 验证安装
    vue -V
    
2. 创建项目
  • 命令行方式

    vue create my-vue2-project
    # 选择"Default (Vue 2)"模板或手动配置
    
  • UI 界面方式

    vue ui
    

    在浏览器打开的 UI 界面中,点击 "创建项目",选择路径并配置选项。
3. 项目基本配置

在项目根目录创建vue.config.js

const { defineConfig } = require('@vue/cli-service')
module.exports = defineConfig({
  // 关闭代码格式校验
  lintOnSave: false,
  // 配置跨域代理
  devServer: {
    proxy: {
      '/api': {
        target: 'http://localhost:3000',
        changeOrigin: true,
        pathRewrite: {
          '^/api': ''
        }
      }
    }
  },
  // 打包配置
  configureWebpack: {
    optimization: {
      splitChunks: {
        chunks: 'all'
      }
    }
  }
})
二、项目目录结构解析

典型的 Vue2 项目结构如下:

my-vue2-project/
├── public/                  # 静态资源(HTML模板、图标等)
├── src/
│   ├── assets/              # 样式、图片等资源
│   ├── components/          # 组件文件夹
│   ├── router/              # 路由配置
│   ├── store/               # Vuex状态管理
│   ├── utils/               # 工具函数
│   ├── views/               # 页面级组件
│   ├── App.vue              # 根组件
│   └── main.js              # 入口文件
├── .gitignore              # Git忽略文件
├── babel.config.js          # Babel配置
├── package.json             # 依赖管理
└── README.md                # 项目说明
三、组件化开发核心
1. 组件基本结构

一个 Vue 组件由三部分组成:

<template>
  <div class="component-container">
    <!-- 模板层,只能有一个根元素 -->
    <h3>{{ title }}</h3>
    <p>内容:{{ content }}</p>
  </div>
</template>

<script>
export default {
  name: 'ComponentName', // 组件名(首字母大写)
  props: {
    title: {
      type: String,
      default: '默认标题'
    },
    content: {
      type: String,
      required: true
    }
  },
  data() {
    return {
      internalData: '组件内部数据'
    }
  },
  methods: {
    handleClick() {
      console.log('组件方法被调用')
    }
  },
  mounted() {
    console.log('组件挂载完成')
  }
}
</script>

<style scoped>
/* 样式层,scoped确保样式仅作用于当前组件 */
.component-container {
  padding: 16px;
  border: 1px solid #eee;
}
</style>
2. 组件注册方式
  • 局部注册:在父组件中引入并注册

    <!-- 父组件 -->
    <template>
      <div>
        <HeaderComponent />
        <MainContent />
      </div>
    </template>
    
    <script>
    // 1. 引入组件
    import HeaderComponent from './components/Header.vue'
    import MainContent from './components/MainContent.vue'
    
    export default {
      components: {
        // 2. 注册组件(可自定义标签名)
        HeaderComponent, // 等价于 HeaderComponent: HeaderComponent
        MainContent
      }
    }
    </script>
    
  • 全局注册:在 main.js 中注册

    // main.js
    import Vue from 'vue'
    import App from './App.vue'
    import FooterComponent from './components/Footer.vue'
    
    // 全局注册组件
    Vue.component('FooterComponent', FooterComponent)
    
    new Vue({
      render: h => h(App)
    }).$mount('#app')
    

    在任意组件中可直接使用:

    <FooterComponent />
    
3. 组件样式隔离

通过scoped属性实现组件样式私有化:

<style scoped>
/* 该样式仅作用于当前组件 */
.button {
  background-color: #42b983;
}
</style>

若需使用 CSS Modules:

<style module>
/* 生成类名如 .button_1d823ab */
.button {
  color: white;
}
</style>

在模板中使用:

<button :class="$style.button">按钮</button>
四、组件间通信机制
1. 父传子(Props)
  • 父组件传递数据:

    <ChildComponent :title="pageTitle" :is-active="true" />
    
  • 子组件接收 Props:

    export default {
      props: {
        title: String,
        isActive: {
          type: Boolean,
          default: false
        },
        // 数组/对象类型的默认值需返回函数
        initialData: {
          type: Object,
          default() {
            return { count: 0 }
          }
        }
      }
    }
    
2. 子传父(自定义事件)
  • 子组件触发事件:

    methods: {
      sendDataToParent() {
        const data = { message: '子组件数据' }
        this.$emit('child-event', data)
      }
    }
    
  • 父组件监听事件:

    <ChildComponent @child-event="handleChildData" />
    
    methods: {
      handleChildData(data) {
        console.log('接收到子组件数据:', data)
      }
    }
    
3. 非父子组件通信(事件总线)
  • 创建事件总线(EventBus.js):

    import Vue from 'vue'
    export default new Vue()
    
  • 发送数据组件:

    import EventBus from '@/utils/EventBus'
    
    methods: {
      sendToOtherComponent() {
        EventBus.$emit('custom-event', { data: '跨组件数据' })
      }
    }
    
  • 接收数据组件:

    import EventBus from '@/utils/EventBus'
    
    created() {
      this.eventHandler = (data) => {
        console.log('接收到跨组件数据:', data)
      }
      EventBus.$on('custom-event', this.eventHandler)
    },
    beforeDestroy() {
      // 销毁时移除监听,避免内存泄漏
      EventBus.$off('custom-event', this.eventHandler)
    }
    
五、组件引用与 Ref

通过ref获取 DOM 元素或子组件实例:

<template>
  <div>
    <!-- 引用DOM元素 -->
    <input ref="inputElement" type="text">
    <!-- 引用子组件 -->
    <ChildComponent ref="childComponent" />
    <button @click="focusInput">聚焦输入框</button>
  </div>
</template>

<script>
export default {
  methods: {
    focusInput() {
      // 获取DOM元素并调用方法
      this.$refs.inputElement.focus()
      // 调用子组件方法
      this.$refs.childComponent.doSomething()
    }
  }
}
</script>

注意$refs在组件挂载后(mounted 钩子)才能正确获取,动态生成的 ref(如 v-for)会返回数组。

Logo

Agent 垂直技术社区,欢迎活跃、内容共建。

更多推荐