Vue 整体框架全面解析

一、Vue 框架概述

Vue.js 是一套用于构建用户界面的渐进式 JavaScript 框架 ,于 2014 年正式发布。它的核心思想是 "渐进式",意味着开发者可以根据项目需求,逐步引入 Vue 的功能模块,而无需一次性接纳整个框架。无论是小型单页应用,还是大型复杂项目,Vue 都能灵活适配。具有轻量、高效、易上手的特点,其核心库只关注视图层,与其他库或现有项目整合时兼容性良好。同时,Vue 拥有完善的官方文档和活跃的社区,为开发者提供了丰富的学习资源和问题解决方案。

二、Vue 的核心特性

2.1 响应式数据绑定

Vue 的响应式系统是其核心亮点之一。当数据发生变化时,视图会自动更新,无需开发者手动操作 DOM。这一特性基于 JavaScript 的 Object.defineProperty() 方法(Vue 2.x)或 Proxy 对象(Vue 3.x)实现。

Vue 2.x 实现原理

通过递归遍历数据对象的属性,使用 Object.defineProperty() 为每个属性添加 getter 和 setter。具体实现过程如下:

  1. 初始化阶段:遍历 data 对象的所有属性
  2. 依赖收集:当属性被访问时,触发 getter 将当前 Watcher 实例添加到依赖列表中
  3. 变更通知:当属性值被修改时,触发 setter 通知所有依赖进行更新
  4. 视图更新:触发组件的重新渲染

示例

javascript 复制代码
// 简化的响应式实现
function defineReactive(obj, key, val) {
  Object.defineProperty(obj, key, {
    get() {
      console.log(`读取 ${key}: ${val}`);
      return val;
    },
    set(newVal) {
      console.log(`设置 ${key}: ${newVal}`);
      val = newVal;
      // 通知依赖更新
      dep.notify();
    }
  });
}

局限性

  • 无法检测到对象属性的添加或删除
  • 对数组的索引修改和长度变化无法检测
  • 需要递归遍历整个对象,性能开销较大

Vue 3.x 优化

采用 Proxy 对象替代 Object.defineProperty(),主要改进包括:

  1. 全面响应式:可以监听到对象属性的添加、删除和数组索引变化
  2. 性能提升:不需要递归遍历整个对象,按需响应
  3. 简化实现:统一处理对象和数组的响应式逻辑
  4. 惰性监听:只有当属性被访问时才会创建响应式

示例

javascript 复制代码
const reactive = (target) => {
  return new Proxy(target, {
    get(target, key, receiver) {
      track(target, key); // 依赖收集
      return Reflect.get(target, key, receiver);
    },
    set(target, key, value, receiver) {
      Reflect.set(target, key, value, receiver);
      trigger(target, key); // 触发更新
      return true;
    }
  });
};

实际应用场景

  • 表单输入实时反馈
  • 数据可视化图表自动更新
  • 列表数据变更时的UI同步

2.2 组件化开发

组件化是 Vue 的另一个核心特性,它允许开发者将页面拆分为多个独立、可复用的组件,每个组件包含自己的模板、脚本和样式。这种开发方式具有以下优势:

组件化优势

  1. 代码复用

    • 通用组件(如按钮、表单控件)可以在不同项目或页面中重复使用
    • 业务组件(如商品卡片、评论模块)可以在同一项目的多个位置复用
    • 减少重复代码量,提高开发效率
  2. 维护便捷

    • 每个组件独立维护,职责单一
    • 修改功能时只需关注对应组件,不影响其他部分
    • 通过props和events明确定义组件接口,降低耦合度
  3. 团队协作

    • 不同开发者可以并行开发不同组件
    • 组件文档化后便于团队共享使用
    • 适合大型项目开发和管理

组件类型

全局组件

通过 Vue.component() 方法注册,在整个 Vue 应用中都可以使用。

注册示例

javascript 复制代码
Vue.component('my-button', {
  template: '<button class="btn"><slot></slot></button>',
  props: ['type']
});

使用场景

  • 应用级通用组件(如布局组件、导航栏)
  • 频繁使用的UI组件(如按钮、图标)
局部组件

在组件的 components 选项中注册,只能在当前组件内部使用。

注册示例

javascript 复制代码
const UserProfile = {
  template: '<div class="profile">{{ username }}</div>',
  props: ['username']
};

new Vue({
  el: '#app',
  components: {
    'user-profile': UserProfile
  }
});

使用场景

  • 特定业务场景的专用组件
  • 组件只在有限范围内使用
  • 需要保持组件封装性的情况

组件通信方式

  1. Props向下传递:父组件向子组件传递数据
  2. Events向上通知:子组件向父组件发送事件
  3. Provide/Inject:跨层级组件通信
  4. Event Bus:非父子组件间通信
  5. Vuex:全局状态管理

2.3 模板语法

Vue 使用基于 HTML 的模板语法,允许开发者将 DOM 与 Vue 实例中的数据进行绑定。模板语法主要包括以下几种形式:

文本插值

使用双大括号 {``{ }} 将数据插入到 DOM 中。

示例

html 复制代码
<p>消息:{{ message }}</p>
<p>计算值:{{ count * 2 }}</p>
<p>格式化日期:{{ formatDate(date) }}</p>

特点

  • 支持简单的JavaScript表达式
  • 自动更新数据变化
  • 可以使用过滤器(Vue 2.x)或方法处理数据

指令系统

带有 v- 前缀的特殊属性,用于实现DOM操作和数据绑定。

常用指令
  1. 条件渲染

    • v-if / v-else / v-else-if:根据条件渲染DOM元素
    html 复制代码
    <div v-if="score >= 90">优秀</div>
    <div v-else-if="score >= 60">及格</div>
    <div v-else>不及格</div>
  2. 列表渲染

    • v-for:遍历数组或对象
    html 复制代码
    <ul>
      <li v-for="(item, index) in items" :key="item.id">
        {{ index }} - {{ item.name }}
      </li>
    </ul>
  3. 属性绑定

    • v-bind(缩写 :):动态绑定HTML属性
    html 复制代码
    <img :src="imagePath" :alt="imageAlt">
    <button :disabled="isDisabled">提交</button>
  4. 事件绑定

    • v-on(缩写 @):绑定事件监听器
    html 复制代码
    <button @click="handleClick">点击</button>
    <input @keyup.enter="submitForm">
  5. 双向绑定

    • v-model:表单元素与数据的双向绑定
    html 复制代码
    <input v-model="username">
    <select v-model="selectedOption">
      <option value="A">选项A</option>
      <option value="B">选项B</option>
    </select>

计算属性与侦听器

计算属性

通过 computed 选项定义,基于现有数据计算出新的数据。

特点

  • 具有缓存特性,只有当依赖的数据变化时才会重新计算
  • 适合处理复杂逻辑和数据转换
  • 声明式编程,模板中使用更简洁

示例

javascript 复制代码
computed: {
  fullName() {
    return this.firstName + ' ' + this.lastName;
  },
  filteredList() {
    return this.list.filter(item => item.active);
  }
}
侦听器

通过 watch 选项定义,用于监听数据的变化。

特点

  • 适合执行异步操作或复杂逻辑
  • 可以监听特定数据的变化
  • 命令式编程,更灵活

示例

javascript 复制代码
watch: {
  searchQuery(newVal, oldVal) {
    this.fetchResults(newVal);
  },
  'user.id': {
    handler: 'loadUserData',
    immediate: true
  }
}

应用场景对比

  • 计算属性:需要基于现有数据派生新值(如格式化显示、过滤列表)
  • 侦听器:需要在数据变化时执行特定操作(如API调用、验证逻辑)

三、Vue 实例与生命周期

3.1 Vue 实例

每个 Vue 应用都是从创建 Vue 实例开始的,这是构建 Vue 应用的起点。Vue 实例是 Vue 应用的根组件,通过 new Vue({ 选项 }) 的方式创建。这个实例包含了应用的所有核心功能:

javascript 复制代码
const vm = new Vue({
  // 挂载目标,指定Vue实例管理的DOM元素
  // 可以是CSS选择器字符串或直接传入DOM元素
  el: '#app', 
  
  // 应用的数据对象,Vue会递归将其转换为getter/setter
  data: { 
    message: 'Hello Vue!',
    counter: 0,
    user: {
      name: 'John',
      age: 25
    }
  },

  // 应用的方法集合
  methods: { 
    showMessage() {
      alert(this.message);
    },
    incrementCounter() {
      this.counter++;
    }
  },

  // 计算属性
  computed: {
    reversedMessage() {
      return this.message.split('').reverse().join('');
    }
  },

  // 监听属性
  watch: {
    counter(newVal, oldVal) {
      console.log(`计数器从${oldVal}变为${newVal}`);
    }
  }
});

在 Vue 实例中,this 指向当前的 Vue 实例,开发者可以通过 this 访问实例中的数据和方法。例如,在方法中可以通过 this.message 访问数据,在模板中则可以直接使用 message

3.2 生命周期钩子函数

Vue 实例从创建到销毁的过程称为生命周期,在这个过程中,Vue 会自动调用一系列的钩子函数,开发者可以在这些钩子函数中执行相应的操作。

详细的生命周期钩子函数说明:

  1. beforeCreate

    • 实例创建前调用
    • 此时数据观测 (data observer) 和事件/监视器配置尚未初始化
    • 示例场景:可以在此时添加一些全局事件总线的事件监听
  2. created

    • 实例创建后调用
    • 已经完成了数据观测、属性和方法的运算,但挂载阶段还未开始
    • 常用于异步获取数据、初始化非DOM相关的操作
    • 此时可以访问 this.datathis.methods
  3. beforeMount

    • DOM 挂载前调用
    • 模板编译已完成,但尚未将模板渲染到页面中
    • 很少在此阶段进行操作,因为此时DOM还未生成
  4. mounted

    • DOM 挂载后调用
    • 此时可以访问DOM元素,常用于:
      • 初始化需要DOM的第三方插件
      • 添加事件监听器
      • 执行依赖于DOM的操作
    • 注意:不保证所有子组件也都一起被挂载
  5. beforeUpdate

    • 数据更新前调用
    • 发生在虚拟DOM重新渲染和打补丁之前
    • 可以在此钩子中进一步更改状态,不会触发附加的重渲染过程
  6. updated

    • 数据更新后调用
    • 虚拟DOM已重新渲染和打补丁
    • 避免在该钩子函数中修改数据,否则可能导致无限循环
    • 适合执行依赖于DOM更新的操作
  7. beforeDestroy

    • 实例销毁前调用
    • 此时实例仍然完全可用
    • 常用于:
      • 清除定时器
      • 取消事件监听
      • 清理第三方插件实例
  8. destroyed

    • 实例销毁后调用
    • 所有指令都已解绑,所有事件监听器都已移除
    • 所有子实例也都被销毁

生命周期使用示例

javascript 复制代码
new Vue({
  el: '#app',
  data: {
    message: 'Hello Vue!'
  },
  beforeCreate() {
    console.log('beforeCreate: 实例刚刚创建');
  },
  created() {
    console.log('created: 实例创建完成');
    // 可以在这里发起AJAX请求获取初始数据
    this.fetchData();
  },
  beforeMount() {
    console.log('beforeMount: 模板编译完成,即将挂载');
  },
  mounted() {
    console.log('mounted: 实例已挂载到DOM');
    // 可以在这里初始化需要DOM的插件
    this.initThirdPartyPlugin();
  },
  beforeUpdate() {
    console.log('beforeUpdate: 数据即将更新');
  },
  updated() {
    console.log('updated: 数据已更新完成');
  },
  beforeDestroy() {
    console.log('beforeDestroy: 实例即将销毁');
    // 清除定时器
    clearInterval(this.timer);
  },
  destroyed() {
    console.log('destroyed: 实例已销毁');
  },
  methods: {
    fetchData() {
      // 模拟异步数据获取
      setTimeout(() => {
        this.message = 'Data loaded!';
      }, 1000);
    },
    initThirdPartyPlugin() {
      // 初始化第三方插件
      console.log('初始化第三方插件');
    }
  }
});

四、Vue 生态系统

4.1 Vue Router

Vue Router 是 Vue 官方提供的路由管理库,专门用于构建单页应用程序(SPA)。它通过将 URL 映射到对应的组件,实现了页面的无刷新切换,提供了流畅的用户体验。Vue Router 支持多种高级功能,如动态路由匹配、嵌套路由视图、路由参数传递等,是现代前端开发中不可或缺的工具。

4.1.1 基本使用

安装 Vue Router

在项目中使用 npm 或 yarn 安装 Vue Router:

bash 复制代码
npm install vue-router --save
# 或
yarn add vue-router
创建路由实例

创建一个 router.js 文件来配置路由:

javascript 复制代码
import Vue from 'vue';
import VueRouter from 'vue-router';
import Home from './components/Home.vue';
import About from './components/About.vue';
import NotFound from './components/NotFound.vue';

// 使用 VueRouter 插件
Vue.use(VueRouter);

// 定义路由配置
const routes = [
  { 
    path: '/', 
    component: Home,
    name: 'Home'  // 命名路由,便于编程式导航
  },
  { 
    path: '/about', 
    component: About,
    name: 'About'
  },
  {
    path: '*',  // 404 页面匹配
    component: NotFound
  }
];

// 创建路由实例
const router = new VueRouter({
  mode: 'history',  // 使用 HTML5 history 模式,去除 URL 中的 #
  routes,
  scrollBehavior(to, from, savedPosition) {
    // 路由切换时的滚动行为控制
    if (savedPosition) {
      return savedPosition;
    } else {
      return { x: 0, y: 0 };
    }
  }
});

export default router;
在 Vue 实例中集成路由

在 main.js 中引入并使用路由:

javascript 复制代码
import Vue from 'vue';
import App from './App.vue';
import router from './router';  // 导入路由配置

new Vue({
  router,  // 注入路由实例
  render: h => h(App)
}).$mount('#app');
模板中使用路由

在 App.vue 或任何组件模板中使用路由相关组件:

html 复制代码
<template>
  <div id="app">
    <nav>
      <!-- 使用 router-link 进行导航 -->
      <router-link to="/" exact>首页</router-link> |
      <router-link :to="{ name: 'About' }">关于我们</router-link>
    </nav>
    
    <!-- 路由匹配的组件将渲染在这里 -->
    <router-view></router-view>
  </div>
</template>

4.1.2 高级特性

动态路由

动态路由允许我们根据参数动态匹配路由:

javascript 复制代码
// 路由配置
{
  path: '/user/:userId',
  component: User,
  props: true  // 将路由参数作为 props 传递给组件
}

// 在组件中获取参数
// 通过 $route.params.userId
// 或通过 props: ['userId']
嵌套路由

嵌套路由允许我们在组件内部再嵌套路由视图:

javascript 复制代码
const routes = [
  {
    path: '/user/:id',
    component: User,
    children: [
      {
        path: 'profile',
        component: UserProfile
      },
      {
        path: 'posts',
        component: UserPosts
      }
    ]
  }
]
编程式导航

除了使用 <router-link>,还可以通过 JavaScript 进行导航:

javascript 复制代码
// 基本导航
this.$router.push('/about')
this.$router.push({ name: 'About' })
this.$router.replace('/login')  // 替换当前历史记录

// 带参数的导航
this.$router.push({ 
  name: 'User', 
  params: { userId: 123 } 
})

// 导航守卫
router.beforeEach((to, from, next) => {
  // 全局前置守卫
  if (to.meta.requiresAuth && !isAuthenticated) {
    next('/login')
  } else {
    next()
  }
})

4.2 Vuex

Vuex 是 Vue 的官方状态管理库,用于集中管理应用中多个组件共享的状态。它采用集中式存储管理应用的所有组件的状态,并以相应的规则保证状态以一种可预测的方式发生变化。

4.2.1 核心概念

State

State 是 Vuex 存储应用状态的地方,类似于组件的 data 选项:

javascript 复制代码
state: {
  user: null,
  isLoading: false,
  todos: []
}
Getters

Getters 用于从 state 中派生出新的状态,类似于计算属性:

javascript 复制代码
getters: {
  completedTodos: state => {
    return state.todos.filter(todo => todo.completed)
  },
  activeTodosCount: (state, getters) => {
    return state.todos.length - getters.completedTodos.length
  }
}
Mutations

Mutations 是修改 state 的唯一方式,必须是同步函数:

javascript 复制代码
mutations: {
  ADD_TODO(state, todo) {
    state.todos.push(todo)
  },
  TOGGLE_TODO(state, id) {
    const todo = state.todos.find(t => t.id === id)
    if (todo) {
      todo.completed = !todo.completed
    }
  }
}
Actions

Actions 用于处理异步操作,可以包含任意异步操作:

javascript 复制代码
actions: {
  fetchTodos({ commit }) {
    return api.fetchTodos().then(response => {
      commit('SET_TODOS', response.data)
    })
  },
  addTodoAsync({ commit }, todo) {
    setTimeout(() => {
      commit('ADD_TODO', todo)
    }, 1000)
  }
}
Modules

Modules 允许我们将 store 分割成模块:

javascript 复制代码
const userModule = {
  state: { user: null },
  mutations: { SET_USER(state, user) { state.user = user } },
  actions: { login({ commit }, credentials) { /* ... */ } }
}

const store = new Vuex.Store({
  modules: {
    user: userModule,
    products: productsModule
  }
})

4.2.2 基本使用

安装 Vuex
bash 复制代码
npm install vuex --save
# 或
yarn add vuex
创建 Vuex Store

store/index.js:

javascript 复制代码
import Vue from 'vue'
import Vuex from 'vuex'

Vue.use(Vuex)

export default new Vuex.Store({
  state: {
    count: 0,
    user: null
  },
  getters: {
    doubleCount: state => state.count * 2,
    isAuthenticated: state => !!state.user
  },
  mutations: {
    INCREMENT(state) {
      state.count++
    },
    SET_USER(state, user) {
      state.user = user
    }
  },
  actions: {
    incrementAsync({ commit }) {
      setTimeout(() => {
        commit('INCREMENT')
      }, 1000)
    },
    login({ commit }, credentials) {
      return authService.login(credentials)
        .then(user => commit('SET_USER', user))
    }
  }
})
在 Vue 实例中使用

main.js:

javascript 复制代码
import Vue from 'vue'
import App from './App.vue'
import store from './store'

new Vue({
  store,
  render: h => h(App)
}).$mount('#app')
在组件中使用
javascript 复制代码
// 访问 state
computed: {
  count() {
    return this.$store.state.count
  },
  // 使用 mapState 辅助函数
  ...mapState(['count', 'user'])
}

// 调用 mutations
methods: {
  increment() {
    this.$store.commit('INCREMENT')
  },
  // 使用 mapMutations 辅助函数
  ...mapMutations(['INCREMENT'])
}

// 调用 actions
methods: {
  incrementAsync() {
    this.$store.dispatch('incrementAsync')
  },
  // 使用 mapActions 辅助函数
  ...mapActions(['incrementAsync'])
}

4.3 Vue CLI

Vue CLI 是一个基于 Vue.js 进行快速开发的完整系统,提供了项目脚手架、开发服务器、构建工具和各种插件支持。

4.3.1 安装与使用

安装 Vue CLI
bash 复制代码
npm install -g @vue/cli
# 或
yarn global add @vue/cli
创建新项目
bash 复制代码
vue create my-project

交互式项目创建过程:

  1. 选择预设配置(默认或手动)
  2. 选择需要的特性(Babel, Router, Vuex, CSS 预处理器等)
  3. 选择 Vue 版本(2.x 或 3.x)
  4. 选择路由的 history 模式
  5. 选择 CSS 预处理器(Sass, Less, Stylus)
  6. 选择代码风格配置(ESLint + Standard/Prettier)
  7. 选择何时进行代码检查(保存时或提交时)
  8. 选择测试解决方案(Jest, Mocha 等)
  9. 选择配置文件位置(单独文件或 package.json)
项目命令
bash 复制代码
# 启动开发服务器
npm run serve

# 构建生产版本
npm run build

# 运行测试
npm run test

# 检查并修复代码
npm run lint

4.3.2 项目结构

典型 Vue CLI 项目结构:

复制代码
my-project/
├── public/                   # 静态资源目录
│   ├── index.html            # 主 HTML 文件
│   └── favicon.ico           # 网站图标
├── src/                      # 源代码目录
│   ├── assets/               # 静态资源(图片、字体等)
│   ├── components/           # 公共组件
│   ├── views/                # 页面级组件
│   ├── router/               # 路由配置
│   │   └── index.js
│   ├── store/                # Vuex 状态管理
│   │   └── index.js
│   ├── styles/               # 全局样式
│   ├── utils/                # 工具函数
│   ├── App.vue               # 根组件
│   └── main.js               # 应用入口文件
├── .env                      # 环境变量
├── .env.development          # 开发环境变量
├── .env.production           # 生产环境变量
├── vue.config.js             # Vue CLI 配置
└── package.json              # 项目配置和依赖
自定义配置

vue.config.js:

javascript 复制代码
module.exports = {
  publicPath: process.env.NODE_ENV === 'production' 
    ? '/production-sub-path/' 
    : '/',
  outputDir: 'dist',
  assetsDir: 'static',
  lintOnSave: process.env.NODE_ENV === 'development',
  productionSourceMap: false,
  devServer: {
    port: 8080,
    proxy: {
      '/api': {
        target: 'http://localhost:3000',
        changeOrigin: true,
        pathRewrite: {
          '^/api': ''
        }
      }
    }
  },
  chainWebpack: config => {
    // 添加自定义 webpack 配置
  }
}

五、Vue 3.x 新特性

5.1 组合式 API(Composition API)

组合式 API 是 Vue 3.x 的核心新特性之一,它改变了传统选项式 API 的组织方式,允许开发者按照逻辑功能而非选项(如 data、methods、computed)来组织代码。这种架构方式特别适合大型项目,能够显著提高代码的可维护性和可复用性。

实现方式

组合式 API 主要通过setup()函数实现,该函数在组件创建前调用,其返回的对象中的属性和方法可以在模板中直接使用。这种设计使得相关逻辑可以更好地聚合在一起,而不是分散在不同的选项块中。

示例代码

javascript 复制代码
import { ref, computed } from 'vue';

export default {
  setup() {
    // 定义响应式数据
    const count = ref(0);
    
    // 定义计算属性
    const doubleCount = computed(() => count.value * 2);
    
    // 定义方法
    const increment = () => {
      count.value++;
    };
    
    // 定义一个重置功能
    const reset = () => {
      count.value = 0;
    };
    
    // 返回模板可用的属性和方法
    return {
      count,
      doubleCount,
      increment,
      reset
    };
  }
};

实际应用场景

  1. 表单处理:可以将表单验证、提交逻辑封装在一个组合函数中
  2. 数据获取:将API调用、加载状态管理、错误处理逻辑集中管理
  3. 复杂业务逻辑:将相关操作聚合在一起,提高代码可读性

5.2 更高效的虚拟 DOM

Vue 3.x 对虚拟 DOM 实现进行了全面重写,带来了显著的性能提升:

优化措施

  1. 静态节点提升:识别并提升静态节点,避免不必要的重渲染
  2. 补丁标记:为动态节点添加标记,减少diff时需要比较的范围
  3. 缓存事件处理函数:避免不必要的重新绑定
  4. 更高效的渲染函数生成:通过编译时优化生成更精简的代码

性能对比

在典型的中型应用测试中,Vue 3.x 的虚拟DOM操作速度比Vue 2.x快约2倍,内存占用减少约50%。

实际影响

  • 列表渲染性能提升30-50%
  • 组件初始化和更新速度大幅提高
  • 内存占用更少,适合大型单页应用

5.3 更好的 TypeScript 支持

Vue 3.x 从架构层面优化了对TypeScript的支持:

改进点

  1. 代码库完全使用TypeScript重写
  2. 提供了完整的类型定义
  3. 组合式API天然支持类型推断
  4. 模板中的表达式也支持类型检查

类型支持示例

typescript 复制代码
import { defineComponent, ref } from 'vue';

interface User {
  id: number;
  name: string;
  email: string;
}

export default defineComponent({
  setup() {
    // 具有完整类型推断的响应式数据
    const user = ref<User>({
      id: 1,
      name: 'John Doe',
      email: 'john@example.com'
    });
    
    // 类型安全的更新方法
    const updateName = (newName: string) => {
      user.value.name = newName;
    };
    
    return {
      user,
      updateName
    };
  }
});

5.4 其他重要新特性

Teleport

解决组件在DOM结构中位置受限的问题,典型应用场景包括:

  • 模态对话框
  • 通知提示
  • 全局加载指示器

示例:

html 复制代码
<teleport to="body">
  <div class="modal">
    <!-- 模态框内容 -->
  </div>
</teleport>

Suspense

处理异步组件加载状态,提供更好的用户体验:

html 复制代码
<Suspense>
  <template #default>
    <AsyncComponent />
  </template>
  <template #fallback>
    <div>Loading...</div>
  </template>
</Suspense>

Emits 选项

明确声明组件事件,提高代码可维护性:

javascript 复制代码
export default {
  emits: ['submit', 'cancel'],
  methods: {
    handleSubmit() {
      this.$emit('submit', formData);
    }
  }
}
相关推荐
洛小豆2 小时前
Git 打标签完全指南:从本地创建到远端推送
前端·git·github
世间小小鱼2 小时前
【爬坑指南】亚马逊文件中心 AWS S3 预签名URL 前端直传
前端·云计算·aws
华仔啊3 小时前
前端登录token到底应该存在哪?LocalStorage、SessionStorage还是Cookie?一篇说透!
前端·javascript
BeefyBytes3 小时前
动态组件库建设
前端
懒大王95273 小时前
uni-app + Vue3 + EZUIKit.js 播放视频流
开发语言·javascript·uni-app
懒大王95273 小时前
uni-app + Vue3 开发展示 echarts 图表
前端·uni-app·echarts
yinuo3 小时前
Uni-App跨端实战:微信小程序WebView与H5通信全流程解析(01)
前端
xkroy3 小时前
ajax
前端·javascript·ajax
Yvonne爱编码4 小时前
AJAX入门-URL、参数查询、案例查询
前端·javascript·ajax