• VUE必知必会


    一、简介


    Vue.js是一个流行的JavaScript框架,用于构建用户界面和单页应用程序(SPA)。自2014年由前Google工程师尤雨溪发布以来,Vue迅速获得了广泛的关注和使用,特别是在前端开发领域。

    核心特性

    1.  响应式数据绑定:Vue最显著的特点之一是其响应式系统。当Vue实例的数据对象发生变化时,视图会自动更新。这使得状态管理变得简单直观。 
    2.  组件系统:Vue的另一个关键特性是组件系统。组件是可重用的Vue实例,完全具备与新实例相同的选项,如数据、计算属性、方法等。这种组件化使得构建大型应用变得更加高效和模块化。 
    3.  虚拟DOM:Vue使用虚拟DOM(Document Object Model)来提升性能和效率。这意味着当视图发生变化时,Vue会先在虚拟DOM上进行变更,然后高效地将这些变更应用到实际的DOM上。 
    4.  指令系统:Vue提供了一套丰富的指令(如v-bind, v-model, v-on等),使得HTML模板的编写变得更加直观和方便。 

    设计哲学

    Vue的设计哲学是渐进式的。你可以只在一个小项目中引入Vue来处理交互式部分,而不必重构整个项目。随着项目的发展,你可以逐渐探索Vue的更多特性,如组件系统、Vuex(状态管理)、Vue Router(路由管理)等。这种渐进式的特性使得Vue既适合小型项目,也适合大型、复杂的单页应用。

    社区和生态系统

    Vue享有一个活跃且快速增长的社区。Vue的生态系统包括但不限于:

    • Vuex:官方状态管理库。
    • Vue Router:官方路由库。
    • Nuxt.js:用于服务器端渲染的框架。
    • Vuetify、Quasar等:提供现成UI组件的库。

    学习曲线

    Vue被广泛认为是最易于学习的前端框架之一。其简洁的API设计、清晰的文档以及渐进式的特性使得初学者可以轻松上手。

    应用场景

    Vue可以用于构建各种Web应用,从小型项目(如动态表单、小型网站)到大型企业级应用(如电子商务网站、后台系统)。它的灵活性和模块化使其适应各种不同的开发需求。

    总的来说,Vue以其易用性、灵活性和强大的功能,成为了现代Web开发中最受欢迎的框架之一。无论是对于初学者还是有经验的开发者,Vue都是一个值得考虑的优秀选择。

    二、模型架构


    Vue.js 的架构可以从几个关键部分来理解:其响应式系统、组件结构、以及与此相关的模块(如Vuex和Vue Router)。下面详细介绍这些构成部分:

    1. 响应式系统

    Vue 的核心是一个响应式系统,它基于 MVVM(Model-View-ViewModel)模式:

    • Model:代表应用数据,通常是纯JavaScript对象。
    • View:是由Vue模板构成的DOM表现。
    • ViewModel:是Vue实例,它是一个连接视图和数据的中介。在ViewModel中,Vue实例通过一些特殊的属性和函数来观察数据的变化,并自动更新DOM。

    当数据变化时,Vue会自动更新视图,这是通过依赖跟踪和一个发布者-订阅者模式实现的。每个组件实例都对应一个watcher实例,它会在组件渲染过程中把属性记录为依赖,当依赖项的setter被调用时,通知watcher重新计算,从而使其关联的组件重新渲染。

    2. 组件系统

    Vue的另一个关键特点是组件系统。Vue应用由嵌套的、可复用的组件树组成:

    • 组件(Component):是Vue最强大的功能之一。每个组件都是一个拥有预定义选项的Vue实例。组件可以包含自己的模板、数据、方法、生命周期钩子等。
    • Props:组件可以接受外部传递的数据,这些数据称为props。
    • 事件(Events):组件之间可以通过事件进行通信,子组件可以发射事件让父组件监听和响应。
    • 插槽(Slots):用于父子组件内容的分发。

    3. Vue Router

    对于单页应用(SPA),Vue Router 提供了前端路由的功能。它允许你构建一个单页应用的导航系统,而无需页面重新加载。Vue Router 与 Vue.js 核心深度集成,使得构建单页应用变得更加容易。

    4. Vuex

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

    5. 服务端渲染(SSR)

    Vue.js 也支持服务端渲染,这对于SEO和首次加载性能特别重要。通过SSR,可以在服务器端执行Vue组件的渲染,生成并发送静态HTML到客户端,实现更快的首次内容绘制。

    总结

    Vue的架构提供了一个简单但强大的模式,用于构建用户界面。通过响应式数据绑定和组件系统,开发者可以轻松创建高效的、维护性好的应用程序。同时,Vue的生态系统(包括Vue Router和Vuex)提供了构建复杂应用程序所需的所有工具和功能。这些特性,加上其渐进式的本质,使Vue成为了现代Web应用开发的一个非常受欢迎的选择。

    三、 响应式系统


    核心概念

    1.  响应式数据: Vue 中的数据(例如,在 data 对象中定义的数据)是响应式的。这意味着当这些数据改变时,视图将自动更新。 
    2.  依赖跟踪: 当组件渲染时,系统会记录哪些数据被读取。之后,当这些数据改变时,系统知道需要重新渲染哪些组件。 
    3.  虚拟DOM (VDOM): Vue 使用虚拟DOM来提高渲染效率。当状态改变时,Vue 会先在虚拟DOM上进行改变,然后比较新旧虚拟DOM的差异,并将差异应用于实际的DOM上。 

    实现细节

    1.  响应式属性: 在 Vue 2.x 中,这是通过 Object.defineProperty 实现的。Vue 3.x 则使用了 ES6 的 Proxy 特性来提供更好的性能和更多的语言特性支持。 
    2.  依赖收集: 当组件进行渲染时,它会读取所需的数据属性,这些属性会收集当前组件作为依赖。如果这些属性的值发生变化,依赖的组件会被重新渲染。 
    3.  异步更新队列: Vue 在数据变化后并不会立即更新DOM,而是把这个更新任务放入到一个异步队列中。在下一个事件循环中,Vue 会清空队列并执行必要的DOM更新。这种方式可以有效地批量处理数据变化,避免不必要的重复渲染。 

    ES6的 Proxy 特性

    这是一个非常强大和灵活的功能,它允许你创建一个对象的代理(proxy),从而可以拦截和自定义对象的基本操作,例如属性查找、赋值、枚举、函数调用等。

    基本概念

    Proxy 对象用于定义基本操作的自定义行为(如属性查找、赋值、枚举、函数调用等)。它包含两个参数:

    1. 目标对象 (target): 被 Proxy 包裹的原始对象。
    2. 处理器对象 (handler): 一个定义了多种“陷阱”(trap)的对象,这些陷阱对应于基本操作。

    代码示例
    1. let target = {
    2. name: "target"
    3. };
    4. let handler = {
    5. get: function(obj, prop) {
    6. if (prop in obj) {
    7. return obj[prop];
    8. } else {
    9. return `Property ${prop} not found`;
    10. }
    11. },
    12. set: function(obj, prop, value) {
    13. if (prop === 'age' && !Number.isInteger(value)) {
    14. throw new TypeError('Age must be an integer');
    15. }
    16. obj[prop] = value;
    17. return true;
    18. }
    19. };
    20. let proxy = new Proxy(target, handler);
    21. console.log(proxy.name); // 输出: target
    22. console.log(proxy.age); // 输出: Property age not found
    23. proxy.age = 30; // 正常赋值
    24. console.log(proxy.age); // 输出: 30
    25. proxy.age = 'thirty'; // 抛出错误: TypeError: Age must be an integer

    在这个例子中,proxy 是 target 对象的一个代理。通过 handler 对象,我们定义了对 target 对象的 get 和 set 操作的自定义行为。

    主要特性
    1.  拦截和定制行为: Proxy 可以拦截对象上的几乎所有操作,包括属性访问、赋值、函数调用、原型链操作等。 
    2.  验证: 可以用于验证属性值。 
    3.  观察对象: 用于观察对象属性的读写。 
    4.  虚拟对象: 可以创建完全虚拟的对象,这些对象的属性和行为可以完全自定义。 
    5.  反射 (Reflect): ES6 同时引入了 Reflect 对象,它提供了一系列与 Proxy 陷阱函数相对应的方法。这使得在处理器对象内部可以方便地执行默认行为。 

    使用场景
    • 调试: 在属性访问或函数调用时添加日志记录。
    • 数据绑定和观察者模式: 自动观察数据变化。
    • 数据验证和格式化
    • API 包装和适配
    • 性能优化: 惰性求值或条件加载。

    Proxy 特性为 JavaScript 带来了前所未有的操作对象的灵活性和控制力,使得可以在底层操作上实现高级、定制的行为。

    VUE和JS的事件循环

    Vue.js 和 JavaScript 的事件循环是两个相互关联但又有所不同的概念。我将首先解释 JavaScript 的事件循环,然后讨论 Vue.js 是如何在这个框架内工作的。

    JavaScript 事件循环

    JavaScript 事件循环是 JavaScript 引擎处理异步操作的机制。它允许 JavaScript 代码执行时,同时处理异步事件(如点击、定时器、HTTP 请求等)。其工作原理如下:

    1.  调用栈(Call Stack): 
      • 当一个函数被调用时,它被添加到调用栈中。
      • 当函数执行完成,它会从调用栈中弹出。
    1.  事件队列(Event Queue): 
      • 当一个异步事件发生并准备好被处理时,它的回调函数被添加到事件队列中。
    1.  事件循环(Event Loop): 
      • 事件循环的工作是检查调用栈并确定是否为空。
      • 如果调用栈为空,事件循环会从事件队列中取出第一个事件,并将其对应的回调放入调用栈,开始执行。
      • 这个过程是循环进行的,因此称为“事件循环”。

    Vue.js 和事件循环

    Vue.js 是一个构建用户界面的渐进式框架,它在 JavaScript 的事件循环之上提供了响应式数据绑定和组件系统。Vue.js 如何与事件循环交互:

    1.  响应式系统: 
      • Vue.js 使用响应式系统自动追踪依赖并在数据变化时更新视图。
      • 当数据变化时,视图的更新并不是立即执行的,而是被放入一个异步队列中。这就是 Vue.js 的异步更新机制。
    1.  异步更新队列: 
      • Vue.js 有自己的内部队列来管理异步更新。
      • 当数据变化时,组件不会立即重新渲染。相反,Vue 将需要更新的组件标记为“脏的”并放入异步队列。
      • 在下一个事件循环中,Vue 清空队列,并只执行必要的组件更新。这种机制可以避免不必要的重复渲染,并提高性能。
    1.  与 JavaScript 事件循环的集成: 
      • Vue.js 的异步更新队列利用 JavaScript 的事件循环。
      • 它通常使用 Promise.thenMutationObserver 或 setTimeout 来延迟队列的处理到下一个事件循环中。

    总结

    Vue.js 在 JavaScript 的事件循环基础上构建了自己的响应式系统和异步更新机制。通过将组件的更新推迟到下一个事件循环,Vue 可以优化性能并避免不必要的渲染,同时保持界面的响应性和数据的一致性。这种机制允许 Vue.js 高效地管理数据变化和界面更新,同时充分利用 JavaScript 异步处理的能力。

    四、 组件系统


    4.1 组件定义

    Vue 组件定义是 Vue.js 中一个重要的概念,它允许你创建可重用的代码块,具有自己的模板、逻辑和样式。Vue 组件可以被视为自定义元素,它们扩展了 HTML 的能力。下面详细介绍 Vue 组件的定义方式:

    单文件组件(.vue 文件)

    在 Vue.js 中,最常见的组件定义方式是使用单文件组件(SFC)。这种方式将模板、脚本和样式封装在一个 .vue 文件中。

    •  模板部分(Template)
      • 使用 HTML 编写。
      • 可以包含其他组件、数据绑定和指令。
    •  脚本部分(Script)
      • 用于定义组件的逻辑,如数据、方法、生命周期钩子等。
      • 通过 export default 导出一个 Vue 组件对象。
    •  样式部分(Style)
      • 可以包含 CSS 用于样式化组件。
      • 支持预处理器如 SCSS。
    1. <template>
    2. <div>{{ message }}</div>
    3. </template>
    4. <script>
    5. export default {
    6. data() {
    7. return {
    8. message: 'Hello, Vue!'
    9. }
    10. }
    11. }
    12. </script>
    13. <style>
    14. div {
    15. color: red;
    16. }
    17. </style>

    JavaScript 对象

    在 Vue.js 中,除了使用单文件组件(.vue 文件)定义组件外,还可以直接在 JavaScript 文件中定义组件。这种方式不依赖于 .vue 文件,而是利用纯 JavaScript 来创建组件。有两种主要的方法:使用 Vue.extend 方法或者直接定义一个对象。

    1. 使用 Vue.extend 方法

    Vue.extend 是一种构造器,它创建一个“扩展实例构造器”,允许你定义一个预设选项的 Vue 组件。这个方法返回一个“扩展实例构造器”,也就是一个“子类”,这个子类继承自 Vue。

    1. var MyComponent = Vue.extend({
    2. // 选项对象
    3. template: '
      {{ message }}
      '
      ,
    4. data() {
    5. return {
    6. message: 'Hello, Vue!'
    7. };
    8. }
    9. });
    10. // 创建 MyComponent 实例
    11. new MyComponent().$mount('#app');

    在这个例子中,Vue.extend 创建了一个新的组件构造器 MyComponent。然后,你可以像使用普通 Vue 实例一样使用这个构造器来创建组件实例。

    2. 直接定义一个对象

    另一种方式是直接定义一个对象,然后通过 Vue.component 方法全局注册这个组件。这种方式简洁直观,适用于较小的应用或是功能。

    1. Vue.component('my-component', {
    2. // 选项对象
    3. template: '
      {{ message }}
      '
      ,
    4. data() {
    5. return {
    6. message: 'Hello, Vue!'
    7. };
    8. }
    9. });

    在这个例子中,Vue.component 方法用于全局注册组件。它接受两个参数:组件的名字(在这里是 'my-component')和一个选项对象,这个对象定义了组件的行为和模板。

    4.2 组件属性

    1、data

    Vue 组件的 data 属性是其中一个核心概念,用于声明组件的响应式状态。这个属性在组件内部定义了可以被模板和组件的逻辑所使用的数据。

    基本概念
    • 类型:在组件中,data 必须是一个函数,这样每个实例都可以维护一份数据的独立拷贝,避免数据在组件间共享。
    • 作用:定义组件的状态。任何在 data 中声明的属性都是响应式的,意味着当这些属性的值改变时,Vue 将自动更新 DOM。
    • 访问方式:在组件的模板、计算属性、方法、生命周期钩子和监视器中,可以通过 this 关键字访问 data 属性中的数据。

    定义方式

    在定义组件时,data 属性必须被声明为一个返回对象的函数。这个对象包含了组件的状态。

    1. Vue.component('my-component', {
    2. data() {
    3. return {
    4. counter: 0,
    5. message: 'Hello Vue!'
    6. };
    7. }
    8. });

    在这个例子中,data 函数返回一个对象,该对象包含 counter 和 message 两个属性。

    使用场景
    • 局部状态管理:当你需要存储组件特有的状态时,例如用户输入、计时器状态或任何其他只与该组件相关的数据。
    • 响应式数据:Vue 的响应式系统会自动追踪 data 属性中数据的变化,并在数据变化时更新视图。
    • 组件实例间独立:由于 data 是一个函数,每个组件实例可以维持一份独立的数据副本,这样同一组件的不同实例之间的数据不会相互影响。

    注意事项
    • 初始化时声明:为了确保数据是响应式的,需要在组件的 data 中初始化所有需要的属性。
    • 直接修改数组和对象:Vue 不能检测到对象属性的添加或删除。当需要修改对象或数组时,应使用 Vue.set 或以新对象替换旧对象。
    • 数据的非响应性:如果在 data 定义后添加新的属性到对象上,这些新属性不会是响应式的。应该在初始的 data 函数中预先声明它们。

    data 属性是 Vue 组件中管理和维护状态的基础,合理利用它可以让组件的状态管理更加清晰和高效。

    2、父子组件通信方式

    props

    在 Vue.js 中,props 是用于接收来自父组件数据的自定义属性。在单文件组件(.vue 文件)中,props 的使用是组件间通信的关键部分。以下是如何在单文件组件中使用 props 的详细步骤和方法。

    步骤 1: 定义 Props

    在子组件中,首先需要定义 props。这可以通过数组语法或对象语法来完成。

    数组语法
    1. <template>
    2. <div>{{ title }}div>
    3. template>
    4. <script>
    5. export default {
    6. props: ['title']
    7. }
    8. script>

    对象语法(推荐)

    对象语法允许提供详细的配置,如类型检查、默认值和必需性。

    1. <template>
    2. <div>{{ title }}</div>
    3. </template>
    4. <script>
    5. export default {
    6. props: {
    7. title: {
    8. type: String,
    9. required: true,
    10. default: 'Default Title'
    11. }
    12. }
    13. }
    14. </script>

    步骤 2: 在父组件中传递 Props

    在父组件中,你需要将数据作为属性传递给子组件。

    1. <template>
    2. <my-component title="Hello Vue!"></my-component>
    3. </template>
    4. <script>
    5. import MyComponent from './MyComponent.vue';
    6. export default {
    7. components: {
    8. MyComponent
    9. }
    10. }
    11. </script>

    步骤 3: 在子组件中使用 Props

    在子组件中,你可以像使用普通数据一样使用 props

    1. <template>
    2. <div>{{ title }}</div>
    3. </template>
    4. <script>
    5. export default {
    6. props: ['title']
    7. }
    8. </script>

    高级使用
    Props 验证

    可以对 props 进行详细的验证,以确保传入的数据类型正确,并且符合预期。

    1. <script>
    2. export default {
    3. props: {
    4. age: {
    5. type: Number,
    6. required: true,
    7. validator: value => {
    8. return value > 0;
    9. }
    10. }
    11. }
    12. }
    13. </script>

    使用 Props 初始化数据

    有时,你可能需要基于 props 的值来初始化组件的局部状态。

    1. <script>
    2. export default {
    3. props: ['initialCounter'],
    4. data() {
    5. return {
    6. counter: this.initialCounter
    7. };
    8. }
    9. }
    10. script>

    注意事项
    • 不要直接修改 Props:Vue 强烈建议不要直接修改 props 的值。如果需要,可以将 props 的值赋给 data 属性或计算属性进行处理。
    • Props 的单向数据流props 的更新只能从父组件流向子组件。这有助于预防子组件无意间改变父组件的状态,从而导致应用的数据流难以理解和维护。

    props 的正确使用是创建可维护和高效 Vue 应用的关键之一,它确保了组件间清晰和灵活的数据流动。

    自定义事件

    在 Vue.js 中,自定义事件是组件间通信的重要机制,尤其是从子组件向父组件传递信息。在单文件组件中使用自定义事件包括在子组件中触发事件和在父组件中监听这些事件。以下是使用自定义事件的详细步骤和方法。

    步骤 1: 子组件中触发事件

    在子组件中,你可以使用 this.$emit 方法来触发一个事件。这个方法接受事件名作为第一个参数,随后的参数是传递给监听器的数据。

    子组件(ChildComponent.vue)

    1. <template>
    2. <button @click="handleClick">Click me</button>
    3. </template>
    4. <script>
    5. export default {
    6. methods: {
    7. handleClick() {
    8. // 触发自定义事件,发送信息给父组件
    9. this.$emit('custom-event', 'some data');
    10. }
    11. }
    12. }
    13. </script>

    步骤 2: 父组件中监听事件

    在父组件中,你可以使用 v-on 或简写 @ 来监听子组件触发的事件。

    父组件(ParentComponent.vue)

    1. <template>
    2. <child-component @custom-event="handleCustomEvent"></child-component>
    3. </template>
    4. <script>
    5. import ChildComponent from './ChildComponent.vue';
    6. export default {
    7. components: {
    8. ChildComponent
    9. },
    10. methods: {
    11. handleCustomEvent(data) {
    12. console.log('Event received:', data);
    13. // 处理事件和数据
    14. }
    15. }
    16. }
    17. </script>

    进阶使用
    使用 .native 监听原生事件

    如果你需要在父组件中监听子组件根元素的原生事件,可以使用 .native 修饰符。

    <child-component @click.native="handleClick"></child-component>

    使用 v-model 实现双向绑定

    Vue 允许使用 v-model 在自定义组件上实现双向绑定。这实际上是 value 属性和 input 事件的语法糖。

    1. <template>
    2. <input :value="value" @input="updateValue">
    3. template>
    4. <script>
    5. export default {
    6. props: ['value'],
    7. methods: {
    8. updateValue(event) {
    9. this.$emit('input', event.target.value);
    10. }
    11. }
    12. }
    13. script>
    14. <template>
    15. <child-component v-model="inputValue">child-component>
    16. template>
    17. <script>
    18. import ChildComponent from './ChildComponent.vue';
    19. export default {
    20. components: {
    21. ChildComponent
    22. },
    23. data() {
    24. return {
    25. inputValue: 'initial value'
    26. };
    27. }
    28. }
    29. script>

    注意事项
    • 避免与原生 DOM 事件冲突:自定义事件名不应与原生 DOM 事件(如 clickmouseover 等)冲突,以防止混淆。
    • 命名约定:建议使用 kebab-case(短横线分隔命名)来命名自定义事件。

    自定义事件是 Vue 组件间沟通的强大工具,它允许子组件以一种松耦合的方式向父组件发送消息,有助于保持组件的封装性和可重用性。

    插槽

    Vue 的插槽(Slots)是一种用于组件模板的内容分发机制,允许开发者将内容从父组件插入到子组件的指定位置。这在单文件组件(.vue 文件)中特别有用,因为它提供了一种灵活的方式来创建可复用和可配置的组件。以下是在单文件组件中使用插槽的方法和步骤。

    默认插槽

    默认插槽是最简单的插槽类型,用于分发父组件中未指定插槽的内容。

    子组件 (ChildComponent.vue)
    1. <template>
    2. <div>
    3. <h2>Title</h2>
    4. <slot></slot> <!-- 默认插槽 -->
    5. </div>
    6. </template>
    7. <script>
    8. export default {
    9. // 组件逻辑
    10. }
    11. </script>

    在这里, 标签定义了一个默认插槽。

    父组件 (ParentComponent.vue)
    1. <template>
    2. <child-component>
    3. <p>This will go into the default slot.</p>
    4. </child-component>
    5. </template>
    6. <script>
    7. import ChildComponent from './ChildComponent.vue';
    8. export default {
    9. components: {
    10. ChildComponent
    11. }
    12. }
    13. </script>

    具名插槽

    具名插槽允许你为不同的插槽指定不同的内容。

    子组件 (ChildComponent.vue)
    1. <template>
    2. <div>
    3. <header>
    4. <slot name="header"></slot>
    5. </header>
    6. <main>
    7. <slot></slot> <!-- 默认插槽 -->
    8. </main>
    9. <footer>
    10. <slot name="footer"></slot>
    11. </footer>
    12. </div>
    13. </template>

    父组件 (ParentComponent.vue)
    1. <template>
    2. <child-component>
    3. <template v-slot:header>
    4. <h1>Header Content</h1>
    5. </template>
    6. <p>Main Content</p> <!-- 默认插槽内容 -->
    7. <template v-slot:footer>
    8. <p>Footer Content</p>
    9. </template>
    10. </child-component>
    11. </template>

    作用域插槽

    Vue 的作用域插槽是一种强大的功能,允许子组件传递数据到它的插槽内容中,这些内容定义在父组件里。作用域插槽特别适用于创建可复用的组件模板,它们需要根据父组件的数据来定制内容。以下是在单文件组件中使用作用域插槽的方法和步骤。

    子组件:定义作用域插槽

    在子组件中,你定义一个插槽,并决定哪些数据要传递给这个插槽。这是通过在  标签中使用 v-bind 或简写 : 来实现的。

    子组件 (ChildComponent.vue)
    1. <template>
    2. <ul>
    3. <li v-for="item in items" :key="item.id">
    4. <!-- 定义作用域插槽,并传递 item 数据 -->
    5. <slot name="item" :item="item">
    6. {{ item.defaultText }} <!-- 默认内容 -->
    7. </slot>
    8. </li>
    9. </ul>
    10. </template>
    11. <script>
    12. export default {
    13. data() {
    14. return {
    15. items: [
    16. { id: 1, text: 'Item 1', defaultText: 'Default 1' },
    17. { id: 2, text: 'Item 2', defaultText: 'Default 2' }
    18. // 更多 items...
    19. ]
    20. };
    21. }
    22. }
    23. </script>

    这里,子组件为每个 item 定义了一个作用域插槽,将 item 对象作为属性传递给插槽。

    父组件:使用作用域插槽

    父组件接收子组件传递的数据,并决定如何显示这些数据。

    父组件 (ParentComponent.vue)
    1. <template>
    2. <child-component>
    3. <!-- 使用作用域插槽 -->
    4. <template v-slot:item="slotProps">
    5. <span>{{ slotProps.item.text }}</span>
    6. </template>
    7. </child-component>
    8. </template>
    9. <script>
    10. import ChildComponent from './ChildComponent.vue';
    11. export default {
    12. components: {
    13. ChildComponent
    14. }
    15. }
    16. </script>

    在这个例子中,父组件使用 v-slot:item="slotProps" 来接收从子组件传递过来的 item 数据。slotProps 是一个对象,它包含了所有传递给该插槽的属性。在这里,它包含了子组件中的 item 对象。

    使用场景

    作用域插槽非常适合以下场景:

    • 创建可复用的列表组件,其中列表项的内容需要根据父组件的数据定制。
    • 构建一个组件,其部分 UI 结构和行为由父组件控制,但数据来自子组件。
    • 实现高度可定制的组件接口。

    注意事项
    • 在作用域插槽中,插槽内容仍然在父组件的作用域内编译,因此可以访问父组件中的数据和方法。
    • 默认插槽内容是可选的。如果父组件没有提供对应插槽的内容,将显示子组件中定义的默认内容。
    • 作用域插槽增强了组件间的合作能力,同时保持了组件的封装性和可重用性。

    作用域插槽是 Vue.js 中一项强大的功能,提供了一种灵活的方式来创建具有动态内容的组件,同时保持了组件的清晰界限和可维护性。

    插槽使用的注意事项
    • 插槽内容是在父组件作用域内编译的,因此父组件的数据和方法可以在插槽内容中使用。
    • 插槽可以是可选的;如果父组件没有提供内容,子组件的插槽会被显示默认内容。
    • 作用域插槽允许子组件将数据作为插槽的“范围”提供给父组件,这对于创建高度动态的组件特别有用。

    Vue 的插槽系统提供了一种强大的机制,用于构建灵活且可重用的组件,它允许开发者更好地控制内容的布局和组合。

    3、methods

    Vue.js 中的 methods 属性是用于在 Vue 实例中定义方法的地方。这些方法可以用于响应事件、计算数据或任何其他逻辑。在单文件组件(.vue 文件)中使用 methods 属性是非常直接和常见的做法。以下是在单文件组件中使用 methods 属性的方法和步骤。

    定义 Methods

    在单文件组件中,methods 属性是一个对象,其中的每个属性都是一个方法。这些方法可以在组件的模板中被调用,或者在其他方法、计算属性和生命周期钩子中被使用。

    示例:子组件 (MyComponent.vue)
    1. <template>
    2. <div>
    3. <button @click="incrementCount">Increment</button>
    4. <p>Count: {{ count }}</p>
    5. </div>
    6. </template>
    7. <script>
    8. export default {
    9. data() {
    10. return {
    11. count: 0
    12. };
    13. },
    14. methods: {
    15. incrementCount() {
    16. this.count += 1;
    17. }
    18. }
    19. }
    20. </script>

    在这个示例中:

    • incrementCount 方法被定义在 methods 对象内。
    • 当按钮被点击时,@click 指令调用 incrementCount 方法。
    • incrementCount 方法更新 count 数据属性的值。

    调用 Methods

    在 Vue 组件中,你可以通过 this 关键字调用 methods 中定义的方法。

    在模板中调用

    可以在 Vue 模板的指令中直接调用方法,如上面示例中的 @click="incrementCount"

    在 JavaScript 代码中调用

    你也可以在组件的其他方法、计算属性或生命周期钩子中调用这些方法。

    1. export default {
    2. methods: {
    3. methodOne() {
    4. // 逻辑...
    5. },
    6. methodTwo() {
    7. this.methodOne();
    8. }
    9. }
    10. }

    Methods 使用场景
    • 事件处理:响应用户输入,如点击按钮、提交表单等。
    • 复杂计算:执行比计算属性更复杂的逻辑操作。
    • 重用逻辑:封装可在多处调用的代码块。

    注意事项
    • 避免过度使用:对于依赖组件数据并用于渲染结果的逻辑,优先考虑使用计算属性。
    • 访问组件数据和方法:在 methods 中,可以通过 this 访问组件的数据和其他方法。
    • 响应性methods 中的方法不是响应式的,它们不会像计算属性那样自动重新计算。它们仅在被调用时执行。

    methods 属性在 Vue 组件中提供了一个强大的工具,可以用于处理用户交互、执行计算或其他逻辑操作,从而增加了组件的交互性和功能性。

    4、computed

    Vue.js 中的 computed 属性是用来声明计算属性的地方。计算属性是基于响应式依赖进行缓存的数据属性。与方法相比,计算属性只在相关响应式依赖发生改变时才会重新求值,这使得它们非常适合执行更复杂的逻辑,同时保持高效性。在单文件组件(.vue 文件)中使用 computed 属性是常见且有益的做法。以下是在单文件组件中使用 computed 属性的方法和步骤。

    定义计算属性

    在单文件组件中,computed 属性是一个对象,其中的每个属性都是一个计算属性。这些属性看起来像常规的数据属性,但实际上它们的值是由一个函数计算得来的。

    示例:子组件 (MyComponent.vue)
    1. <template>
    2. <div>
    3. <p>Original message: "{{ message }}"</p>
    4. <p>Reversed message: "{{ reversedMessage }}"</p>
    5. </div>
    6. </template>
    7. <script>
    8. export default {
    9. data() {
    10. return {
    11. message: 'Hello Vue!'
    12. };
    13. },
    14. computed: {
    15. reversedMessage() {
    16. return this.message.split('').reverse().join('');
    17. }
    18. }
    19. }
    20. </script>

    在这个示例中:

    • reversedMessage 是一个计算属性,它依赖于 data 中的 message 属性。
    • 每当 message 的值发生变化时,reversedMessage 会自动更新。

    使用计算属性

    计算属性可以像常规的数据属性一样在模板中被使用。它们通常用于模板表达式和数据绑定。

    在模板中使用

    在 Vue 模板中,直接引用计算属性名即可。

    <p>{{ reversedMessage }}p>

    在 JavaScript 代码中使用

    在组件的其他方法或计算属性中,你可以通过 this 关键字来引用计算属性。

    1. computed: {
    2. anotherComputedProp() {
    3. return this.reversedMessage + ' some other data';
    4. }
    5. }

    计算属性的使用场景
    • 复杂逻辑:当模板中的表达式过于复杂时,可以使用计算属性来简化模板。
    • 性能优化:计算属性会缓存结果,只有当依赖的响应式数据发生变化时,它们才会重新计算。
    • 数据格式化:在显示之前格式化或计算数据。

    注意事项
    • 依赖的响应性:计算属性的响应性完全取决于它们所依赖的数据属性。如果依赖的数据不是响应式的,计算属性也不会更新。
    • 不要改变响应式数据:避免在计算属性中改变其依赖的响应式数据,这可能导致不可预测的结果。
    • 计算属性默认只有 getter:如果需要,你也可以提供一个 setter。

    computed 属性提供了一种声明式的方法来描述数据的依赖关系和计算逻辑,是 Vue 组件设计中的一个重要工具。

    5、watch

    Vue.js 中的 watch 属性是一个非常有用的功能,用于观察和响应 Vue 实例上数据对象的变化。当你需要在数据变化时执行异步或开销较大的操作时,watch 是最合适的选择。在单文件组件(.vue 文件)中使用 watch 属性可以让你轻松地追踪数据的变化并作出相应的反应。以下是在单文件组件中使用 watch 属性的方法和步骤。

    定义 Watchers

    在单文件组件中,watch 属性是一个对象,其中的每个属性对应一个要观察的数据属性。你可以为每个属性指定一个函数,当被观察的属性变化时,该函数将被调用。

    示例:子组件 (MyComponent.vue)
    1. <template>
    2. <div>
    3. <input v-model="message" placeholder="Edit me">
    4. <p>The message is: {{ message }}</p>
    5. </div>
    6. </template>
    7. <script>
    8. export default {
    9. data() {
    10. return {
    11. message: ''
    12. };
    13. },
    14. watch: {
    15. message(newVal, oldVal) {
    16. console.log(`The new message is: ${newVal}`);
    17. }
    18. }
    19. }
    20. </script>

    在这个示例中:

    • message 是一个数据属性,通过 v-model 在输入框中被绑定。
    • watch 对象包含一个 message 函数,每当 message 数据变化时,这个函数就会被调用。

    Watcher 函数参数

    Watcher 函数默认接收两个参数:

    • newVal:变化后的值。
    • oldVal:变化前的值。

    使用场景
    • 异步操作:如在数据变化时从服务器获取数据。
    • 复杂逻辑:当需要执行比计算属性更复杂的响应逻辑时。
    • 监听路由变化:如在 Vue Router 中监听 $route 的变化。

    高级特性
    深度观察

    使用 deep 选项可以观察对象内部值的变化。

    1. watch: {
    2. someObject: {
    3. handler(newVal, oldVal) {
    4. // 处理逻辑
    5. },
    6. deep: true
    7. }
    8. }

    立即触发

    使用 immediate 选项可以在监听开始后立即触发回调。

    1. watch: {
    2. someData: {
    3. handler(newVal, oldVal) {
    4. // 处理逻辑
    5. },
    6. immediate: true
    7. }
    8. }

    注意事项
    • 避免过度使用watch 可能会引起性能问题,特别是在观察复杂数据结构时。只在必要时使用。
    • 清理工作:如果你在 watcher 中设置了定时器或执行了其他副作用操作,请确保在组件销毁时清理它们。

    watch 属性提供了一种强大的方式来响应数据的变化,它在处理异步操作、复杂逻辑或依赖于外部数据源的情况下尤其有用。

    6、template

      • 类型:字符串。
      • 作用:定义组件的 HTML 模板。
      • 使用:在单文件组件(.vue 文件)中通常用