文章列表


Vuex 是 Vue.js 应用程序的状态管理模式和库。在 Vuex 中,`mutations`、`actions` 和 `getters` 是核心概念,它们各自扮演着不同的角色,并在状态管理中发挥着关键作用。以下是它们之间的主要区别: ### 1. Mutations * **定义**:Mutations 是 Vuex 中同步更改状态的唯一方法。每个 mutation 都有一个字符串的事件类型(type)和一个回调函数(handler),该回调函数就是实际进行状态更新的地方。 * **特性**: * **同步性**:Mutations 必须是同步的,这意味着它们会立即执行并修改状态。 * **原子性**:每个 Mutation 应该是原子的,即它应该只修改一个状态值,或者相关的一组状态值。 * **确定性**:Mutations 的执行结果应该是确定的,相同的输入应该产生相同的输出。 * **触发方式**:在组件中,可以使用 `store.commit` 方法来触发特定的 Mutation。 ### 2. Actions * **定义**:Actions 类似于 mutations,不同之处在于 Actions 提交的是 mutations,而不是直接变更状态;Actions 可以包含任意异步操作。 * **特性**: * **异步性**:Actions 是处理异步操作和触发状态变更的地方,如网络请求、定时器等。 * **业务逻辑**:Actions 可以包含业务逻辑,并在触发 mutation 之前进行数据的预处理或后处理。 * **组合性**:Actions 可以组合多个 mutations,以实现更复杂的状态更改逻辑。 * **触发方式**:在组件中,可以通过 `store.dispatch` 方法来触发 actions。 ### 3. Getters * **定义**:Getters 类似于 Vue 组件中的计算属性,用于对 store 中的 state 进行计算或过滤,并返回一个新的值供组件使用。 * **特性**: * **缓存性**:Getters 的返回值会根据它的依赖被缓存起来,且只有当它的依赖值发生了改变才会被重新计算。 * **组合性**:Getters 可以接收其他 getters 作为参数,实现对多个状态的联合计算。 * **易用性**:在组件中,可以通过 `this.$store.getters.getterName` 来访问 getters。 ### 总结 | | Mutations | Actions | Getters | | --- | --- | --- | --- | | **定义** | 同步更改状态的唯一方法 | 提交 mutations,可包含异步操作 | 类似于计算属性,对 state 进行计算或过滤 | | **特性** | 同步性、原子性、确定性 | 异步性、业务逻辑、组合性 | 缓存性、组合性、易用性 | | **触发方式** | `store.commit('mutationName', payload)` | `store.dispatch('actionName', payload)` | 在组件中通过 `this.$store.getters.getterName` 访问 | 这些概念共同构成了 Vuex 的状态管理体系,使得 Vue.js 应用程序的状态管理变得更加集中、高效和可维护。

在 Vuex 中管理状态主要涉及到几个核心概念:State、Getters、Mutations、Actions 和 Modules。以下是如何在 Vuex 中管理状态的基本步骤和概念解释: ### 1. 安装和设置 Vuex 首先,确保你的项目中已经安装了 Vuex。如果还没有安装,可以通过 npm 或 yarn 来安装它: ```bash npm install vuex --save # 或者 yarn add vuex ``` 然后,在你的 Vue 应用中创建 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 }, mutations: { // 更改状态的同步方法 increment(state) { state.count++; } }, actions: { // 异步操作 incrementIfOddOnRootSum({ state, commit, rootState }) { if ((state.count + rootState.otherCount) % 2 === 1) { commit('increment'); } } }, getters: { // 派生的状态,如基于 state 的计算属性 evenOrOdd: state => state.count % 2 === 0 ? 'even' : 'odd' }, modules: { // 分割 store 为模块 a: moduleA, b: moduleB } }); ``` ### 2. 使用 State 在组件中,你可以通过 `this.$store.state.count` 来访问状态。但更好的方式是使用 Vuex 提供的辅助函数 `mapState` 来将 store 中的状态映射到局部计算属性中: ```javascript import { mapState } from 'vuex'; export default { computed: mapState([ 'count' // 映射 this.count 为 store.state.count ]) } ``` ### 3. 提交 Mutations 更改 Vuex 的 state 的唯一途径是提交 mutation。Mutation 必须是同步函数。你可以通过 `this.$store.commit('increment')` 来提交一个 mutation。同样,也可以使用 `mapMutations` 辅助函数来映射: ```javascript import { mapMutations } from 'vuex'; export default { methods: { ...mapMutations([ 'increment' // 映射 this.increment() 为 this.$store.commit('increment') ]) } } ``` ### 4. 分发 Actions Action 类似于 mutation,不同在于 action 可以包含任意异步操作。你可以通过 `this.$store.dispatch('incrementIfOddOnRootSum')` 来分发一个 action。Action 通过提交 mutation 来改变状态: ```javascript actions: { incrementIfOddOnRootSum({ commit, state, rootState }) { if ((state.count + rootState.otherCount) % 2 === 1) { commit('increment'); } } } ``` ### 5. 使用 Getters Getters 允许组件从 Store 中派生一些状态。你可以通过 `this.$store.getters.evenOrOdd` 来访问 getter。同样,`mapGetters` 辅助函数可以帮助你将 getter 映射到计算属性中: ```javascript import { mapGetters } from 'vuex'; export default { computed: { ...mapGetters([ 'evenOrOdd' ]) } } ``` ### 6. 使用 Modules 当 Vuex 的 store 变得复杂时,可以通过将 store 分割成模块(module)来管理。每个模块拥有自己的 state、mutation、action、getter、甚至是嵌套子模块——从上至下进行同样方式的分割。 Vuex 提供了一个集中管理所有组件共享状态的模式,并以相应的规则和方式保证状态以一种可预测的方式发生变化。通过合理使用这些核心概念,你可以高效地管理 Vue 应用中的状态。

Vuex 是 Vue.js 应用程序的状态管理模式和库。它专门为 Vue.js 应用程序开发,用于集中式存储管理应用的所有组件的状态,并以相应的规则保证状态以一种可预测的方式发生变化。简单来说,Vuex 充当了一个应用级别的状态容器,它管理着所有组件的公共状态,并以相应的规则保证状态以一种可预测的方式发生变化。 ### Vuex 的主要作用: 1. **集中式状态管理**:Vuex 提供了一个中心化的存储来管理所有组件的共享状态,这样,不同组件之间可以很容易地共享和访问这些状态。 2. **预测性的状态变更**:由于 Vuex 强制使用特定的方式来更新状态(通过 mutations),这使得状态的变更更加易于追踪和调试。每个 mutation 都有一个字符串的事件类型 (type) 和一个回调函数 (handler)。这个回调函数就是我们实际进行状态更新的地方,并且它会接受 state 作为第一个参数。 3. **更细粒度的状态控制**:通过 Vuex 的 actions,我们可以对状态变更进行更细粒度的控制,比如异步操作。actions 可以包含任意异步操作,并通过提交 mutations 来变更状态。 4. **模块化的组织结构**:随着应用变得复杂,Vuex 允许我们将 store 分割成模块(module)。每个模块拥有自己的 state、mutation、action、getter、甚至是嵌套子模块——从上至下进行同样方式的分割。 ### Vuex 的核心概念: - **State**:单一状态树,即应用的所有状态都包含在一个对象里面,并且这个对象也包含你的应用中大部分重要的数据。 - **Getters**:从 state 中派生出一些状态,类似于 Vue 的计算属性。 - **Mutations**:更改 Vuex 的 store 中的状态的唯一方法是提交 mutation。 - **Actions**:类似于 mutation,不同在于:Action 提交的是 mutation,而不是直接变更状态;Action 可以包含任意异步操作。 - **Modules**:允许将单一的 Store 拆分为多个 store 并同时保存在单一的状态树中。 ### 使用场景: Vuex 特别适用于大型单页应用(SPA),当应用中的多个组件需要共享状态时,使用 Vuex 可以有效地管理这些状态,并使得应用的状态更加清晰和易于维护。然而,对于小型应用来说,直接使用 Vue 的组件内部状态可能就足够了,无需引入 Vuex。

Vue.js 是一个用于构建用户界面的渐进式JavaScript框架,而Axios 是一个基于 Promise 的 HTTP 客户端,用于浏览器和 node.js。在Vue.js项目中集成Axios可以方便地发起HTTP请求,获取或发送数据到服务器。以下是如何在Vue.js项目中集成Axios进行HTTP请求的基本步骤: ### 1. 安装Axios 首先,你需要在你的Vue项目中安装Axios。如果你正在使用npm作为包管理工具,你可以通过以下命令来安装Axios: ```bash npm install axios ``` 或者,如果你使用yarn: ```bash yarn add axios ``` ### 2. 在Vue组件中使用Axios 你可以直接在Vue组件的methods中导入并使用Axios来发起HTTP请求。但是,为了更好的管理和复用,通常我们会创建一个Axios实例并在整个应用中共享它。 #### 示例:直接在组件中使用 ```javascript <template> <div> <button @click="fetchData">获取数据</button> </div> </template> <script> // 导入axios import axios from 'axios'; export default { methods: { fetchData() { axios.get('https://api.example.com/data') .then(response => { // 处理成功情况 console.log(response.data); }) .catch(error => { // 处理错误情况 console.error(error); }); } } } </script> ``` #### 示例:创建Axios实例并在Vue中全局使用 在Vue项目的`main.js`或`main.ts`(如果你使用TypeScript)文件中,你可以创建一个Axios实例,并通过Vue的原型(prototype)来全局注册它,这样你就可以在所有的组件中通过`this.$axios`来访问它了。 ```javascript // main.js import Vue from 'vue' import axios from 'axios' // 创建axios实例 const http = axios.create({ baseURL: 'https://api.example.com', timeout: 1000, headers: {'X-Custom-Header': 'foobar'} }); // 将axios实例挂载到Vue的原型上 Vue.prototype.$http = http; // 现在你可以在所有的组件中通过`this.$http`来使用axios了 new Vue({ // ... }) ``` ### 3. 发送请求 创建并注册了Axios实例之后,你就可以在Vue组件中通过`this.$http`(或`this.$axios`,取决于你的命名)来发送HTTP请求了。 ```javascript export default { methods: { fetchData() { this.$http.get('/data') .then(response => { console.log(response.data); }) .catch(error => { console.error(error); }); } } } ``` ### 结论 以上就是在Vue.js项目中集成Axios进行HTTP请求的基本方法。你可以根据项目的需求来创建和管理Axios实例,以便在Vue组件中方便地发起HTTP请求。

在 Vue.js 项目中,Vue Router 提供了非常方便的页面懒加载(也称为代码分割)机制,这有助于减少应用的初始加载时间,因为它允许用户仅加载当前路由所需的组件代码。这主要通过动态导入(`import()`)语法来实现。 ### 使用 Vue CLI 创建的项目 如果你使用 Vue CLI 创建的项目,Vue Router 通常已经配置好了。你可以很容易地通过修改路由配置来实现懒加载。 假设你有一个名为 `Home.vue` 和 `About.vue` 的组件,并且你想要在路由中懒加载它们,你可以这样配置你的路由: ```javascript // router/index.js import Vue from 'vue' import Router from 'vue-router' Vue.use(Router) export default new Router({ routes: [ { path: '/', name: 'Home', // 使用箭头函数简化代码,并返回 Promise component: () => import(/* webpackChunkName: "home" */ '../views/Home.vue') }, { path: '/about', name: 'About', // 也可以这样写,不使用箭头函数 component: () => require.ensure([], () => require('../views/About.vue'), 'about') // 注意:require.ensure 是 Webpack 特有的语法,它在 Vue CLI 3+ 中被 import() 替代 } ] }) ``` ### 关于 `import()` 和 `webpackChunkName` - `import()` 语法允许你定义一个代码块,这个代码块会被 Webpack 自动进行代码分割。 - `webpackChunkName` 是一个特殊的注释语法,它允许你指定分割后的 chunk 名称。这对于控制最终生成的 bundle 名称和缓存非常有用。 ### 注意事项 - 懒加载通常用于较大的 Vue 组件或库,以优化加载时间。 - 在开发模式下,Webpack 会自动处理代码分割,并在构建时生成相应的 chunk 文件。 - 在生产模式下,你需要确保服务器配置正确,以便能够正确地为这些 chunk 文件提供服务。 - Vue CLI 3+ 默认支持 Webpack 4+,并已经内置了对代码分割的支持。 ### 总结 Vue Router 提供了简单而强大的机制来实现页面懒加载,通过动态导入(`import()`)语法,你可以轻松地优化你的 Vue 应用的加载时间和性能。记得利用 `webpackChunkName` 注释来更好地控制你的代码分割和缓存策略。

配置Vue Router通常涉及几个关键步骤,这些步骤在Vue 2和Vue 3中略有不同,但大体上相似。以下是一个通用的配置流程,适用于Vue 2和Vue 3(根据版本调整细节): ### 一、安装Vue Router 首先,你需要安装Vue Router。如果你使用的是npm或yarn,可以通过命令行来安装。 * 对于Vue 2项目,通常安装`vue-router`的3.x版本(请根据你的Vue版本选择合适的`vue-router`版本)。 ```bash npm install vue-router@3 --save # 或者 yarn add vue-router@3 ``` * 对于Vue 3项目,安装`vue-router`的4.x版本。 ```bash npm install vue-router@4 --save # 或者 yarn add vue-router@4 ``` ### 二、创建路由配置 在项目中创建一个路由文件夹(通常命名为`router`),并在其中创建一个`index.js`文件(或其他命名,但`index.js`是默认的入口文件)。 #### Vue 2示例 ```javascript import Vue from 'vue'; import Router from 'vue-router'; import Home from '../views/Home.vue'; import About from '../views/About.vue'; Vue.use(Router); const routes = [ { path: '/', name: 'home', component: Home }, { path: '/about', name: 'about', component: About } ]; const router = new Router({ mode: 'history', // 使用HTML5 History模式,避免URL中的# base: process.env.BASE_URL, routes }); export default router; ``` #### Vue 3示例 ```javascript import { createRouter, createWebHistory } from 'vue-router'; import Home from '../views/Home.vue'; import About from '../views/About.vue'; const routes = [ { path: '/', name: 'home', component: Home }, { path: '/about', name: 'about', component: About } ]; const router = createRouter({ history: createWebHistory(process.env.BASE_URL), routes }); export default router; ``` ### 三、将路由注入Vue实例 在你的主入口文件(通常是`main.js`或`main.ts`)中,引入并注册路由实例。 #### Vue 2示例 ```javascript import Vue from 'vue'; import App from './App.vue'; import router from './router'; Vue.config.productionTip = false; new Vue({ router, render: h => h(App), }).$mount('#app'); ``` #### Vue 3示例 ```javascript import { createApp } from 'vue'; import App from './App.vue'; import router from './router'; const app = createApp(App); app.use(router); app.mount('#app'); ``` ### 四、在组件中使用路由 在Vue组件中,你可以使用`<router-link>`来声明导航链接,使用`<router-view>`来显示当前路由对应的组件。 ```vue <template> <div id="app"> <router-link to="/">Home</router-link> <router-link to="/about">About</router-link> <router-view></router-view> </div> </template> ``` ### 五、路由编程式导航 你也可以在Vue组件的JavaScript代码中通过编程方式来实现路由的跳转。 ```javascript this.$router.push('/about'); // 使用路径字符串 this.$router.push({ name: 'home' }); // 使用路由名称 ``` ### 总结 以上就是在Vue项目中配置Vue Router的基本步骤。请根据你的项目版本(Vue 2或Vue 3)和具体需求进行调整。如果你遇到任何问题,建议查阅Vue Router的官方文档,那里提供了更详细的信息和示例。

Vue.js 的路由管理主要使用 **Vue Router** 库。Vue Router 是 Vue.js 的官方路由管理器,它允许开发者在不重新加载整个页面的情况下,通过 URL 的变化来切换不同的视图组件,从而实现单页面应用(SPA)中的页面导航和组件渲染。 ### Vue Router 的主要功能特点包括: 1. **声明式路由映射**:Vue Router 允许你通过简单的配置来定义路由和组件之间的关系,使得路由管理更加直观和易于维护。 2. **嵌套路由**:对于需要多层布局的应用,Vue Router 提供了嵌套路由的功能,允许你在一个主视图内嵌套多个子视图。 3. **模块化、组件化的路由配置**:路由配置是模块化和组件化的,这有助于管理大型应用中的路由,使得代码更加清晰和易于管理。 4. **细粒度导航控制**:Vue Router 提供了一系列的导航钩子函数,如 `beforeEach` 和 `afterEach`,这些函数可以在路由改变前后执行,允许你进行更细粒度的导航控制,如权限检查、数据预加载等。 5. **链接活动类**:当用户导航到一个路由时,Vue Router 可以自动为对应的链接元素添加 "active" CSS 类,从而方便地高亮当前活动的路由链接。 6. **支持历史模式和哈希模式**:Vue Router 支持两种模式来管理浏览器的历史记录。HTML5 历史模式使用 `pushState` API 来管理浏览器历史,而哈希模式则使用 URL 的哈希部分来模拟页面跳转。 ### 安装和使用 Vue Router 1. **安装**:你可以通过 npm 或 yarn 来安装 Vue Router。 ```bash npm install vue-router # 或者 yarn add vue-router ``` 2. **配置**:在 Vue 项目中,你需要在入口文件(如 `main.js` 或 `app.js`)中引入并使用 Vue Router。然后,你需要创建一个路由实例,并定义路由规则,最后将这个路由实例传递给 Vue 实例。 3. **使用**:在 Vue 组件中,你可以使用 `<router-link>` 组件来创建导航链接,使用 `<router-view>` 组件来显示当前路由对应的组件。 ### 示例 下面是一个简单的 Vue Router 配置示例: ```javascript // 引入 Vue 和 VueRouter import Vue from 'vue'; import VueRouter from 'vue-router'; // 引入组件 import Home from './views/Home.vue'; import About from './views/About.vue'; // 告诉 Vue 使用 VueRouter Vue.use(VueRouter); // 定义路由 // 每个路由应该映射一个组件。 const routes = [ { path: '/', component: Home }, { path: '/about', component: About } ]; // 创建 router 实例,然后传 `routes` 配置 // 你还可以传别的配置参数, 不过先这么简单着吧。 const router = new VueRouter({ routes // (缩写)相当于 routes: routes }); // 创建和挂载根实例 new Vue({ router, render: h => h(App), }).$mount('#app'); ``` 在 Vue 组件的模板中,你可以这样使用 `<router-link>` 和 `<router-view>`: ```html <template> <div id="app"> <router-link to="/">Home</router-link> <router-link to="/about">About</router-link> <router-view/> </div> </template> ``` 这样,当用户点击 "Home" 或 "About" 链接时,`<router-view>` 组件就会渲染对应的组件内容。

Vue.js 中的计算属性(computed)和侦听器(watch)是两种用于处理数据变化的响应式机制,它们在功能、使用方式以及性能优化方面存在显著差异。以下是它们之间的主要区别: ### 一、功能差异 1. **计算属性(computed)**: - **目的**:主要用于根据组件的响应式数据派生出一些状态,这些状态是只读的,并会根据依赖的数据变化而自动更新。 - **应用场景**:适用于需要基于其他响应式数据进行复杂计算或转换的场景,如根据用户输入的过滤条件动态计算筛选结果。 - **特点**:具有缓存性,只有当其依赖的响应式数据发生变化时,才会重新计算。 2. **侦听器(watch)**: - **目的**:主要用于监听Vue实例上数据的变化,并在数据变化时执行一些异步操作或开销较大的操作。 - **应用场景**:适用于需要在数据变化时执行复杂逻辑、发送请求、执行动画等场景。 - **特点**:不具备缓存性,每次数据变化时都会执行相应的逻辑。 ### 二、使用方式 1. **计算属性(computed)**: - 在Vue组件的`computed`选项中定义,通过getter函数返回计算结果。 - 可选地,还可以定义setter函数来处理计算属性被赋值的情况(虽然计算属性默认是只读的)。 - 在模板中直接像访问普通属性一样使用计算属性。 2. **侦听器(watch)**: - 在Vue组件的`watch`选项中定义,监听特定的数据变化。 - 可以监听单个数据的变化,也可以监听多个数据源(通过数组形式)。 - 侦听器函数接收两个参数:新值和旧值,可以在函数中执行相应的逻辑。 ### 三、性能优化 1. **计算属性(computed)**: - 由于具有缓存性,当依赖的响应式数据没有变化时,不会重新计算,从而提高了性能。 - 适用于频繁访问的计算结果,如列表的过滤和排序。 2. **侦听器(watch)**: - 由于不具备缓存性,每次数据变化时都会执行相应的逻辑,如果逻辑复杂或开销较大,可能会影响性能。 - 适用于不频繁变化但需要执行复杂逻辑的场景。 ### 四、其他注意事项 - **计算属性不支持异步操作**:因为计算属性需要立即返回计算结果,所以不支持异步操作。如果需要进行异步计算,应该使用侦听器或Vue的生命周期钩子。 - **侦听器支持异步操作**:侦听器函数中可以执行异步操作,如发送Ajax请求或调用其他异步API。 综上所述,Vue.js中的计算属性和侦听器在功能、使用方式和性能优化方面存在显著差异。开发者应根据具体场景和需求选择合适的数据处理方式。

在 Vue.js 中,插槽(slot)是一种非常强大的功能,它允许我们定义组件模板的某些部分,而这些部分的内容将由父组件来决定。这对于创建可复用的组件非常有用,因为你可以定义组件的结构,但将具体的内容留给使用它的父组件来填充。 ### 基本插槽 Vue.js 提供了默认插槽和具名插槽两种类型。 #### 默认插槽 默认插槽是最简单的插槽形式,它不需要命名。当组件中只有一个插槽时,默认插槽就会被使用。 **子组件(ChildComponent.vue)**: ```vue <template> <div> <h2>我是子组件的标题</h2> <!-- 默认插槽 --> <slot></slot> </div> </template> <script> export default { name: 'ChildComponent' } </script> ``` **父组件**: ```vue <template> <div> <ChildComponent> <!-- 这里的内容会被渲染到子组件的<slot>位置 --> <p>这是父组件传递给子组件的内容</p> </ChildComponent> </div> </template> <script> import ChildComponent from './ChildComponent.vue' export default { components: { ChildComponent } } </script> ``` #### 具名插槽 当组件中有多个插槽时,我们需要给插槽命名(即具名插槽),以便区分它们。 **子组件(ChildComponent.vue)**: ```vue <template> <div> <header> <slot name="header"></slot> </header> <main> <slot></slot> <!-- 默认插槽 --> </main> <footer> <slot name="footer"></slot> </footer> </div> </template> <script> export default { name: 'ChildComponent' } </script> ``` **父组件**: ```vue <template> <div> <ChildComponent> <template v-slot:header> <h1>这是头部内容</h1> </template> <p>这是默认插槽的内容</p> <template v-slot:footer> <p>这是底部内容</p> </template> </ChildComponent> </div> </template> <script> import ChildComponent from './ChildComponent.vue' export default { components: { ChildComponent } } </script> ``` ### 作用域插槽 作用域插槽是一种特殊类型的插槽,它允许子组件将数据“回传”给插槽的内容。这意呀着父组件可以访问到子组件的数据。 **子组件(ChildComponent.vue)**: ```vue <template> <ul> <li v-for="item in items" :key="item.id"> <slot name="item" :item="item"></slot> </li> </ul> </template> <script> export default { data() { return { items: [ { id: 1, text: 'Item 1' }, { id: 2, text: 'Item 2' } ] } } } </script> ``` **父组件**: ```vue <template> <ChildComponent> <template v-slot:item="slotProps"> <span>{{ slotProps.item.text }}</span> </template> </ChildComponent> </template> <script> import ChildComponent from './ChildComponent.vue' export default { components: { ChildComponent } } </script> ``` 在作用域插槽中,`slotProps` 是一个对象,包含了传递给插槽的所有属性(在这个例子中是 `item`)。通过这种方式,父组件可以访问到子组件的 `items` 数组中的每个元素,并在插槽的内容中使用它们。

`v-model` 是 Vue.js 中的一个非常强大的指令,它主要用于在表单输入和应用状态之间创建双向数据绑定。这意味着,当用户在表单输入中修改数据时,绑定的数据会自动更新;反之,当绑定的数据变化时,输入也会相应地更新。 ### 基本原理 `v-model` 实际上是一个语法糖,它背后做了几件事情来实现双向绑定: 1. **监听 input 事件**:`v-model` 会根据控件类型自动选取正确的方法来更新元素。对于 `<input>`, `<select>`, 和 `<textarea>`,它默认使用 `value` 属性作为 prop,并监听 `input` 事件来更新数据。 2. **更新数据**:当在表单控件上触发 `input`(或其他类似事件,如 `change` 对于 `<select>`)时,`v-model` 会将新的值赋给绑定的数据属性。 3. **渲染视图**:由于 Vue 的响应式系统,当绑定的数据发生变化时,视图会自动更新以反映最新的数据。 ### 自定义组件中的 v-model 在自定义组件中,`v-model` 同样可以工作,但需要组件显式地定义如何接收 prop 和触发事件。默认情况下,`v-model` 使用 `value` 作为 prop 和 `input` 作为事件,但你可以通过 `model` 选项来自定义它们: ```javascript Vue.component('custom-input', { props: ['value'], model: { prop: 'customValue', event: 'customInput' }, methods: { updateValue(e) { this.$emit('customInput', e.target.value); } }, template: ` <input :value="customValue" @input="updateValue" type="text" > ` }); ``` 在这个例子中,虽然模板中使用了 `:value="customValue"` 和 `@input="updateValue"`,但由于 `model` 选项的指定,使用 `<custom-input v-model="something">` 时,实际上绑定的是 `customValue` prop,并在内部 `updateValue` 方法中通过 `$emit('customInput', ...)` 触发更新。 ### 注意事项 - 并非所有表单输入都触发 `input` 事件。例如,对于 `<select multiple>`,你可能需要监听 `change` 事件。 - 在自定义组件中,确保你正确处理了 prop 和事件的传递,以便 `v-model` 能够正常工作。 - Vue 3 引入了 Composition API,其中可以使用 `ref` 或 `reactive` 来创建响应式数据,并通过 `watch` 或 `computed` 来实现更复杂的逻辑,但 `v-model` 的基本工作原理保持不变。