了解Vue2全局API这一篇就够了

前段时间,小哆啦在工作之余,总感觉vue会用还是不是很了解,于是小哆啦决定总结一波,来深度复习一下。复习完之后小哆啦也会跟着大佬去学习vue的源码分析,在总结的时候小哆啦也尽量去理解大佬的设计思想。

参考资料:

[API — Vue.js (vuejs.org)

序号Vue.js 特性描述注意事项
1Vue.extend(options)通过选项扩展基础构造函数,创建一个新的组件构造函数。
2Vue.nextTick([callback, context])在下一次 DOM 更新周期之后执行回调函数。用于在重新渲染后执行一些操作。需要注意回调中的上下文和异步执行的特性。
3Vue.set(target, propertyName/index, value)将响应式属性添加到对象或更新现有属性。用于确保将属性添加到对象以保持响应性。避免直接添加新属性,使用Vue.set来确保响应性。
4Vue.delete(target, propertyName/index)从对象中删除属性,确保更改是响应式的。在删除响应式对象的属性时使用。使用Vue.delete确保属性的删除是响应式的。
5Vue.directive(id, [definition])注册或检索全局自定义指令。指令用于将特殊行为附加到DOM中的元素。注意指令的使用方式和生命周期函数的调用时机。
6Vue.filter(id, [definition])注册或检索全局自定义过滤器。过滤器用于在模板中格式化文本或执行转换。注意过滤器的使用方式和参数传递。
7Vue.component(id, [definition])注册或检索全局自定义组件。组件是具有自己选项的可重用Vue实例。注意组件的使用方式、Props和自定义事件。
8Vue.use(plugin)全局安装Vue.js插件,将其功能添加到Vue中。通常用于添加第三方Vue插件。需要注意插件的安装方式和相关配置。
9Vue.compile(template)将模板字符串编译成渲染函数。用于在运行时动态渲染模板。注意编译模板的性能和使用场景。
10Vue.observable(object)从普通的JavaScript对象创建一个响应式对象,使其属性具有响应性。避免在对象上直接添加新属性,使用Vue.set来确保响应性。
11Vue.mixin(mixin)全局混入选项或方法到所有Vue组件中。用于共享公共逻辑或功能。慎用全局混入,注意混入和组件选项的合并规则。

1、Vue.extend()

  • 参数

    • {Object} options
  • 用法

    使用基础 Vue 构造器,创建一个“子类”。参数是一个包含组件选项的对象。

    data 选项是特例,需要注意 - 在 Vue.extend() 中它必须是函数

    <div id="mount-point"></div>
    
    // 创建构造器
    var Profile = Vue.extend({
      template: '<p>{{firstName}} {{lastName}} aka {{alias}}</p>',
      data: function () {
        return {
          firstName: 'Walter',
          lastName: 'White',
          alias: 'Heisenberg'
        }
      }
    })
    // 创建 Profile 实例,并挂载到一个元素上。
    new Profile().$mount('#mount-point')
    

    结果如下:

    <p>Walter White aka Heisenberg</p>
    
  • 原理

    Vue.extend 的原理是基于 Vue 构造函数创建一个新的子类构造函数,这个子类构造函数继承了父类构造函数的所有属性,并可以进一步添加或覆盖一些选项。这样,通过这个子类构造函数创建的组件实例具有与父组件相似的特性。

  • 使用场景

    可复用组件构造函数: 主要用于创建可复用的组件构造函数,使得可以在应用中动态创建多个实例。

2、Vue.nextTick()

Vue.nextTick 是 Vue.js 提供的一个工具方法,用于在 DOM 更新之后执行回调函数。它的主要作用是在下次 DOM 更新循环结束之后执行回调函数,这样可以确保在 Vue 组件更新完成后执行特定的操作。

语法

Vue.nextTick([callback, context])

参数

  • callback (可选): 要执行的回调函数。
  • context (可选): 回调函数中 this 的上下文。

用途和原理

  1. 用途: Vue.nextTick 的典型用途是在数据变化后立即对 DOM 进行操作,而在下次 DOM 更新循环结束之后执行回调。这在一些场景中是非常有用的,例如在修改数据后立即获取更新后的 DOM 尺寸或位置。

  2. 原理: Vue.js 使用异步更新队列来处理 DOM 更新。当组件的数据发生变化时,Vue 将更新推送到异步队列,然后等待下一个事件循环周期执行更新。Vue.nextTick 利用了这个机制,它的回调函数会在异步队列中的 DOM 更新完成后执行,确保我们能够在 DOM 更新后执行特定的操作。

示例

<template>
  <div>
    <p>{{ message }}</p>
    <button @click="changeMessage">Change Message</button>
  </div>
</template>

<script>
export default {
  data() {
    return {
      message: 'Hello, Vue!',
    };
  },
  methods: {
    changeMessage() {
      // 修改数据
      this.message = 'Updated Message';

      // 在下次 DOM 更新循环结束后执行回调
      this.$nextTick(() => {
        // 在这里操作更新后的 DOM
        console.log('DOM updated:', this.$el.textContent);
      });
    },
  },
};
</script>

在上述示例中,当点击按钮触发 changeMessage 方法时,会修改 message 数据,并通过 this.$nextTick 在下次 DOM 更新循环结束后执行回调。在回调函数中,我们输出更新后的 DOM 内容,这样可以确保我们在 DOM 更新后进行相应的操作。

nextTick在页面更新数据后,DOM更新,可以通俗理解为,nextTick就是用来支持操作DOM的代码及时更新渲染页面。也就是在数据变化后要执行的某个操作,而这个操作需要使用随数据改变而改变的DOM结构的时候,这个操作都应该放进Vue.nextTick()的回调函数中。

在Vue生命周期的created()钩子函数进行的DOM操作一定要放在Vue.nextTick()的回调函数中。

3、Vue.set()

Vue.set 是 Vue.js 提供的一个全局方法,用于在响应式对象上添加响应式属性。它的主要作用是确保在添加新属性时触发视图更新。

参数

Vue.set 接受三个参数:

  1. target(目标对象): {Object | Array} - 目标对象,可以是一个响应式对象或数组。

  2. propertyName/index(属性名或索引): {String | Number} - 要添加的属性名或数组的索引。

  3. value(属性值): {Any} - 要设置的属性值。

使用场景

主要用于在运行时向响应式对象或数组中添加新的属性或元素。在使用 Vue.js 进行开发时,通常会在处理异步数据或动态生成属性时使用。

原理

Vue.set 的原理是通过 Vue.js 的响应式系统,使用 Object.defineProperty 或数组变异方法(如 pushsplice)来确保新添加的属性是响应式的,并触发视图更新。

源码

以下是简化版的 Vue.set 源码:

// src/core/observer/index.js

/**
 * Set a property on an object. Adds the new property and
 * triggers change detection.
 */
export function set(target: Array<any> | Object, key: any, val: any): any {
  if (Array.isArray(target) && isValidArrayIndex(key)) {
    // 处理数组的情况
    target.length = Math.max(target.length, key);
    target.splice(key, 1, val);
    return val;
  }
  // 处理对象的情况
  if (key in target && !(key in Object.prototype)) {
    target[key] = val;
    return val;
  }
  // 如果 target 不是响应式对象,则直接赋值
  const ob = (target: any).__ob__;
  if (!ob) {
    target[key] = val;
    return val;
  }
  // 将新属性设置为响应式
  defineReactive(ob.value, key, val);
  ob.dep.notify();
  return val;
}

使用示例

<template>
  <div>
    <p>{{ user.name }}</p>
    <button @click="updateUserName">Update Name</button>
  </div>
</template>

<script>
export default {
  data() {
    return {
      user: {
        name: 'John',
        age: 25,
      },
    };
  },
  methods: {
    updateUserName() {
      // 使用 Vue.set 添加新属性,并确保触发视图更新
      this.$set(this.user, 'gender', 'male');
    },
  },
};
</script>

在这个示例中,当点击按钮时,调用 updateUserName 方法,通过 Vue.setuser 对象中添加了一个名为 gender 的新属性,并确保这个属性是响应式的,以便触发视图更新。这样,在模板中使用 {{ user.gender }} 就能正确地显示新添加的属性值。

1、看来使用示例之后是不是有人会问为什么不直接修改属性,而是使用vue的原型中的$set()方法?

解答:这是因为在 JavaScript 中,对对象属性的直接修改(例如 vm.someProp = 'new value')可能不会触发 getter 和 setter,从而导致视图不会更新。以及数组修改长度和修改具体一个值也不会触发响应式。

官方文档图片

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

在 Vue.js 中,为了实现响应式,对象的属性必须在 data 选项中声明,这样在初始化时可以进行属性的转换。这也是为了确保在属性被定义前就能够转化为 getter 和 setter。

在这里插入图片描述

深入响应式原理 — Vue.js (vuejs.org)

2、时候就有人会问为什么会出现不会更新?

解答:Vue.js实现响应式的关键是通过Object.defineProperty来劫持对象的访问和修改。当使用Object.defineProperty定义一个属性时,可以为该属性设置getter和setter方法,这样当获取或修改属性值时,可以执行相关的逻辑。但是,对对象属性的直接赋值并不会不会触发setter方法。当你直接使用 vm.someProp = 'new value' 修改属性值时,这实际上是在给对象添加一个新的属性,并不是修改已存在的属性。这样做是因为JavaScript允许动态地为对象添加新属性,而Object.defineProperty只会拦截已存在的属性的访问和修改,而不会拦截动态添加的属性。

其实可以看一段代码

function defineReactive(obj, key, value) {
  let internalValue = value;

  Object.defineProperty(obj, key, {
    get() {
      console.log('Getting prop:', key);
      return internalValue;
    },
    set(newValue) {
      console.log('Setting prop:', key, 'to', newValue);
      internalValue = newValue;
    },
  });
}

const vm = {};

defineReactive(vm, 'someProp', 'original value');

// 直接赋值并不会触发 setter
vm.someProp = 'new value'; // 这行代码不会触发 setter,因为 'someProp' 是动态添加的新属性

console.log(vm.someProp); // 通过 getter 获取属性值

//Setting prop: someProp to new value
//Getting prop: someProp
//new value

在上面的例子中,尽管我们使用了Object.defineProperty定义了prop属性的getter和setter,但是直接赋值并没有触发setter,因此没有执行相应的逻辑。

Vue不允许动态添加根级响应式属性

4、Vue.delete()

Vue.delete 是 Vue 提供的一个方法,用于删除对象的属性或数组的元素,同时触发视图的更新。它主要用于在响应式对象或数组中删除属性或元素,并确保这个操作能被 Vue 的响应式系统正确地追踪和处理。

语法

Vue.delete(target, propertyName/index)
  • target: 目标对象,可以是数组或对象。
  • propertyName/index: 要删除的属性的名称(对象)或索引(数组)。

示例

删除对象属性

// 在对象上使用 Vue.delete 删除属性
Vue.delete(vm.someObject, 'propertyName');

删除数组元素

// 在数组上使用 Vue.delete 删除元素
Vue.delete(vm.someArray, 1);

注意事项

  • Vue.delete 只能用于删除对象的属性或数组的元素,不能用于删除整个对象或数组。
  • 当你通过 Vue.delete 删除对象的属性或数组的元素时,Vue 的响应式系统会触发视图的更新。

示例

<template>
  <div>
    <p v-for="(value, key) in myObject" :key="key">{{ key }}: {{ value }}</p>
    <button @click="removeProperty">Remove Property</button>
  </div>
</template>

<script>
export default {
  data() {
    return {
      myObject: {
        prop1: 'value1',
        prop2: 'value2',
        prop3: 'value3',
      },
    };
  },
  methods: {
    removeProperty() {
      // 删除对象的属性并触发视图更新
      Vue.delete(this.myObject, 'prop2');
    },
  },
};
</script>

在上述例子中,点击按钮会触发 removeProperty 方法,该方法使用 Vue.delete 删除了 myObject 对象的属性 prop2,并且由于 Vue 的响应式系统,这个操作会触发视图的更新。

这个和set原理类似

5、Vue.directive()

Vue.directive 是用于注册全局自定义指令的方法,允许你注册一个全局自定义指令,以便在 Vue 应用的任何地方使用。自定义指令可以用于添加 DOM 元素的特殊行为,例如改变元素的样式、绑定事件等。

语法

Vue.directive(id, [definition])
  • id: 指令的名称,即自定义指令的标识符。
  • definition (可选): 一个对象,包含指令的钩子函数和一些配置选项。

钩子函数

  • bind(el, binding, vnode, oldVnode): 只调用一次,在指令绑定到元素时调用。
  • inserted(el, binding, vnode, oldVnode): 被绑定元素插入父节点时调用(父节点存在即可调用,不必存在于 document 中)。
  • update(el, binding, vnode, oldVnode): 所在组件的 VNode 更新时调用,但是可能发生在其子 VNode 更新之前。
  • componentUpdated(el, binding, vnode, oldVnode): 所在组件的 VNode 及其子组件的 VNode 全部更新后调用。
  • unbind(el, binding, vnode, oldVnode): 只调用一次,在指令与元素解绑时调用。

示例

// 注册一个全局自定义指令 'v-color'
Vue.directive('color', {
  bind(el, binding) {
    // 在元素绑定时设置元素的颜色为指令的值
    el.style.color = binding.value;
  },
  update(el, binding) {
    // 在元素更新时重新设置颜色
    el.style.color = binding.value;
  },
});

// 使用自定义指令
<template>
  <div>
    <p v-color="'red'">This text is red</p>
    <p v-color="'blue'">This text is blue</p>
  </div>
</template>

在上述例子中,我们注册了一个全局的自定义指令 'v-color',该指令在绑定和更新时设置元素的颜色为指令的值。在使用该指令时,可以通过绑定的值来动态设置颜色。

使用场景

  1. 操作 DOM 元素: 当你需要直接操作 DOM 元素,例如改变样式、绑定事件、添加动画等,就可以考虑使用自定义指令。这允许你将操作抽象成一个指令,然后在模板中进行使用。

    Vue.directive('highlight', {
      bind(el, binding) {
        // 在绑定时设置背景色
        el.style.backgroundColor = binding.value;
      },
    });
    
    <p v-highlight="'yellow'">This text has a yellow background</p>
    
  2. 对输入框进行限制或格式化: 你可以使用自定义指令对用户的输入进行限制、格式化或其他操作。例如,限制只能输入数字、限制长度等。

    Vue.directive('numeric', {
      bind(el) {
        // 在绑定时添加事件监听,限制只能输入数字
        el.addEventListener('input', (event) => {
          const input = event.target;
          input.value = input.value.replace(/[^0-9]/g, '');
        });
      },
    });
    
    <input v-numeric />
    
  3. 集成第三方库: 当你需要集成第三方库或插件时,可能需要使用自定义指令。例如,集成日期选择器、滚动库等。

    // 使用第三方滚动库
    import Scrollbar from 'perfect-scrollbar';
    
    Vue.directive('scroll', {
      bind(el) {
        // 在绑定时初始化滚动库
        new Scrollbar(el);
      },
    });
    
    <div v-scroll>This content is scrollable</div>
    

自定义指令提供了一种扩展 Vue 行为的强大机制。使用自定义指令能够将特定行为封装成可复用的组件,使代码更加模块化和可维护。

总的来说,Vue.directive 允许你创建全局自定义指令,以在整个 Vue 应用中复用特定的行为。

6、Vue.filter()

Vue.filter 是用于注册全局过滤器的方法。过滤器可以用于在模板中对数据进行一些常见的处理,例如格式化日期、截取字符串等。通过使用过滤器,你可以在模板中轻松地对数据进行处理,而无需在数据源中修改原始数据。

语法

Vue.filter(id, [definition])
  • id: 过滤器的名称,即过滤器的标识符。
  • definition (可选): 一个函数,定义了过滤器的转换逻辑。

过滤器的定义

过滤器是一个函数,接受输入参数并返回处理后的结果。过滤器函数的第一个参数是要处理的值,后面可以跟上其他参数。

// 注册一个全局过滤器 'capitalize'
Vue.filter('capitalize', function (value) {
  if (!value) return '';
  value = value.toString();
  return value.charAt(0).toUpperCase() + value.slice(1);
});

使用过滤器

在模板中,你可以使用过滤器对数据进行处理:

<template>
  <div>
    <p>{{ message | capitalize }}</p>
  </div>
</template>

<script>
export default {
  data() {
    return {
      message: 'hello, vue!',
    };
  },
};
</script>

在上述例子中,message 的值会经过 capitalize 过滤器的处理,使首字母大写。模板中使用过滤器的语法是 {{ value | filterName }}

注意事项

  • 过滤器是一次性的,即它们在数据从模型到视图的过程中生效,但不会影响模型中的原始数据。
  • 过滤器可以串联使用,将多个过滤器以管道方式进行连接。

过滤器的串联使用

Vue.filter('uppercase', function (value) {
  if (!value) return '';
  return value.toUpperCase();
});

Vue.filter('exclamation', function (value) {
  if (!value) return '';
  return value + '!';
});
<template>
  <div>
    <p>{{ message | uppercase | exclamation }}</p>
  </div>
</template>

<script>
export default {
  data() {
    return {
      message: 'hello, vue!',
    };
  },
};
</script>

在上述例子中,message 的值首先会经过 uppercase 过滤器,然后再经过 exclamation 过滤器的处理。最终在模板中输出的是大写字母的消息并且末尾带有感叹号。

7、Vue.component()

Vue.component 是用于注册全局或局部的 Vue 组件的方法。通过 Vue.component,你可以将组件注册为可复用的构建块,使其可以在整个应用中使用。以下是该方法的详细介绍:

**语法 **

Vue.component(id, [definition])
  • id: 组件的名称,即组件的标识符。
  • definition: 组件的定义,可以是一个对象或一个函数。

组件的定义

definition 参数可以是一个对象,也可以是一个函数。如果是一个对象,它就是组件的配置对象,如果是一个函数,该函数会被作为组件的构造函数。

对象定义

// 对象定义的组件
Vue.component('my-component', {
  // 组件的数据
  data() {
    return {
      message: 'Hello, Vue!',
    };
  },
  // 组件的模板
  template: '<p>{{ message }}</p>',
});

函数定义

// 函数定义的组件
Vue.component('my-component', function (resolve, reject) {
  // 异步加载组件
  setTimeout(() => {
    resolve({
      // 组件的数据
      data() {
        return {
          message: 'Hello, Vue!',
        };
      },
      // 组件的模板
      template: '<p>{{ message }}</p>',
    });
  }, 1000);
});

使用组件

注册完组件后,你就可以在模板中使用该组件:

<template>
  <div>
    <my-component></my-component>
  </div>
</template>

注册全局组件

如果你在多个组件中都要使用该组件,可以通过 Vue.component 全局注册:

Vue.component('my-component', {
  // 组件的数据
  data() {
    return {
      message: 'Hello, Vue!',
    };
  },
  // 组件的模板
  template: '<p>{{ message }}</p>',
});

注册局部组件

如果你只在某个组件中使用该组件,可以在组件的 components 选项中进行局部注册:

// 父组件
export default {
  components: {
    'my-component': {
      // 组件的数据
      data() {
        return {
          message: 'Hello, Vue!',
        };
      },
      // 组件的模板
      template: '<p>{{ message }}</p>',
    },
  },
};

异步组件

可以使用函数定义异步组件,实现组件的懒加载:

Vue.component('async-component', function (resolve, reject) {
  // 异步加载组件
  import('./AsyncComponent.vue')
    .then((component) => {
      resolve(component);
    })
    .catch((error) => {
      reject(error);
    });
});

这样的组件会在被渲染时动态加载,优化应用性能。

生命周期钩子

在组件的定义中,你可以使用各种生命周期钩子来执行一些操作。例如,created 钩子会在组件被创建之后调用。

Vue.component('my-component', {
  // 组件创建后调用
  created() {
    console.log('Component created!');
  },
  // 组件的数据
  data() {
    return {
      message: 'Hello, Vue!',
    };
  },
  // 组件的模板
  template: '<p>{{ message }}</p>',
});

总的来说,Vue.component 允许你注册和使用全局或局部的 Vue 组件,扩展了 Vue 应用的组件化能力。

8、Vue.use()

Vue.use 是 Vue 提供的用于安装 Vue 插件的方法。插件通常是一个包含 install 方法的对象或函数。通过 Vue.use,你可以在 Vue 实例中全局注册插件,使其提供一些额外的功能或添加全局级别的功能。

语法

Vue.use(plugin)
  • plugin: 要安装的插件,可以是一个对象或一个函数。

插件的定义

插件是一个包含 install 方法的对象或函数。当使用 Vue.use 安装插件时,该 install 方法会被调用,接收 Vue 构造函数作为参数。

对象定义

const myPlugin = {
  install(Vue, options) {
    // 在这里可以添加全局方法或属性
    Vue.myGlobalMethod = function () {
      // 全局方法的逻辑
    };
    // 在这里可以添加全局资源指令
    Vue.directive('my-directive', {
      bind(el, binding, vnode, oldVnode) {
        // 全局指令的逻辑
      },
    });
  },
};

函数定义

const myPlugin = function (Vue, options) {
  // 在这里可以添加全局方法或属性
  Vue.myGlobalMethod = function () {
    // 全局方法的逻辑
  };
  // 在这里可以添加全局资源指令
  Vue.directive('my-directive', {
    bind(el, binding, vnode, oldVnode) {
      // 全局指令的逻辑
    },
  });
};

使用插件

使用 Vue.use 安装插件后,插件中的 install 方法会被调用,你就可以在 Vue 实例中使用插件提供的功能。

// 安装插件
Vue.use(myPlugin, { someOption: true });

// 在 Vue 实例中使用插件提供的功能
new Vue({
  // ...
  created() {
    // 调用全局方法
    this.$myGlobalMethod();

    // 使用全局指令
    // <div v-my-directive></div>
  },
  // ...
});

插件的扩展

插件可以用于添加全局方法、全局资源、指令等,以及在组件中注入混入。通过插件,你可以将一些通用的功能封装起来,使其在应用中易于复用。

// 插件定义
const myPlugin = {
  install(Vue, options) {
    // 添加全局方法
    Vue.myGlobalMethod = function () {
      // 全局方法的逻辑
    };

    // 添加全局资源指令
    Vue.directive('my-directive', {
      bind(el, binding, vnode, oldVnode) {
        // 全局指令的逻辑
      },
    });

    // 注入混入
    Vue.mixin({
      created() {
        // 注入混入的逻辑
      },
    });
  },
};

// 使用插件
Vue.use(myPlugin, { someOption: true });

// 在 Vue 实例中可以直接使用插件提供的功能
new Vue({
  // ...
  created() {
    // 调用全局方法
    this.$myGlobalMethod();

    // 使用全局指令
    // <div v-my-directive></div>
  },
  // ...
});

总的来说,Vue.use 是用于安装 Vue 插件的方法,通过该方法,你可以在 Vue 实例中全局注册插件,以扩展应用的功能。插件的定义包括 install 方法,它可以用于添加全局方法、全局资源、指令等,以及在组件中注入混入。

9、Vue.compile()

Vue.compile 是 Vue 提供的一个用于将字符串模板编译成渲染函数的方法。该方法返回一个渲染函数,可以被用于渲染 Vue 实例。

语法

const { render, staticRenderFns } = Vue.compile(template);
  • template: 字符串模板,将被编译成渲染函数。

返回值

Vue.compile 的返回值是一个对象,包含两个属性:

  • render: 渲染函数,用于生成虚拟 DOM。
  • staticRenderFns: 静态渲染函数,用于生成静态虚拟 DOM。

使用渲染函数

一旦使用 Vue.compile 编译模板,你可以将返回的渲染函数用于创建 Vue 实例:

const { render, staticRenderFns } = Vue.compile('<div>{{ message }}</div>');

new Vue({
  render,
  staticRenderFns,
  data() {
    return {
      message: 'Hello, Vue!',
    };
  },
}).$mount('#app');

预编译模板

在某些情况下,你可能希望在构建时(例如使用 Webpack)预编译模板,以减小应用的体积。Vue.compile 可以在构建时使用。

import Vue from 'vue';

const { render, staticRenderFns } = Vue.compile('<div>{{ message }}</div>');

export default {
  render,
  staticRenderFns,
  data() {
    return {
      message: 'Hello, Vue!',
    };
  },
};

在上述例子中,Vue.compile 被用于在构建时预编译模板,然后将渲染函数和静态渲染函数导出,以便在其他文件中使用。

总的来说,Vue.compile 提供了一个在运行时将字符串模板编译成渲染函数的方法,使得你可以更灵活地处理模板的编译和渲染。在大多数情况下,直接在模板中使用即可,而不必手动调用 Vue.compile。****

10、Vue.observable()

Vue.observable() 是 Vue 提供的一个方法,用于将普通 JavaScript 对象转换为可响应对象,使其具有 Vue 的响应式特性。

语法

Vue.observable(object)
  • object: 要转换成可响应对象的普通 JavaScript 对象。

返回值

返回一个包装后的可响应对象。

使用场景

  1. 在组件中使用非响应式对象: 当你需要在组件中使用一个普通 JavaScript 对象,但希望该对象具有响应式能力时,可以使用 Vue.observable

    import Vue from 'vue';
    
    const plainObject = {
      message: 'Hello, Vue!',
      count: 0,
    };
    
    const reactiveObject = Vue.observable(plainObject);
    
  2. Vuex 中使用:Vuex 中的状态对象通常需要是可响应的,可以使用 Vue.observable 将普通对象转为可响应对象。

    import Vue from 'vue';
    import Vuex from 'vuex';
    
    Vue.use(Vuex);
    
    const store = new Vuex.Store({
      state: Vue.observable({
        message: 'Hello from Vuex!',
        count: 0,
      }),
      // ...
    });
    

原理

Vue.observable 的原理基于 Vue 的响应式系统。它会对传入的普通 JavaScript 对象进行代理,通过 Object.defineProperty 在对象的属性上设置 getter 和 setter,使得当属性被访问或修改时,能够触发依赖追踪和更新视图。

注意事项

  1. 不要在对象上添加新的属性: 一旦对象被转换成可响应对象,应该避免在对象上添加新的属性。因为新添加的属性不会自动变成响应式的,需要使用 Vue.set 方法来使其变成响应式。

    // 避免这样做
    reactiveObject.newProperty = 'new value';
    
    // 正确的方式
    Vue.set(reactiveObject, 'newProperty', 'new value');
    
  2. 不要在对象上直接修改数组: 当对象的属性是数组时,应该避免直接修改数组,因为这样不会触发视图更新。需要使用数组的变异方法,或者使用 Vue.set

    // 避免这样做
    reactiveObject.arrayProperty.push('new item');
    
    // 正确的方式
    reactiveObject.arrayProperty = [...reactiveObject.arrayProperty, 'new item'];
    // 或者
    reactiveObject.arrayProperty.splice(index, 0, 'new item');
    

总体来说,Vue.observable() 是一个在 Vue 生态中用于创建可响应对象的重要工具,它使得我们能够更方便地管理和使用响应式的状态。

11、Vue.mixin(mixin)

Vue.mixin 是 Vue 提供的一个全局混入方法,用于将混入对象的选项合并到所有的 Vue 组件中。通过全局混入,可以在多个组件中共享相同的逻辑或功能。

语法

Vue.mixin(mixin)
  • mixin: 混入对象,包含组件选项,生命周期钩子,方法等。

使用示例

// 定义一个混入对象
const myMixin = {
  data() {
    return {
      mixinData: 'This is mixin data',
    };
  },
  methods: {
    mixinMethod() {
      console.log('Mixin method called');
    },
  },
};

// 将混入对象应用到所有的 Vue 组件中
Vue.mixin(myMixin);

// 创建一个组件
new Vue({
  data() {
    return {
      componentData: 'This is component data',
    };
  },
  created() {
    console.log('Component created');
    console.log('Component and mixin data:', this.mixinData, this.componentData);
    this.mixinMethod();
  },
}).$mount('#app');

原理

当使用 Vue.mixin 时,混入对象的选项会被合并到每个组件的相应选项中。如果混入对象包含钩子函数(如 createdmounted 等),它们将与组件自身的钩子函数一起执行,但混入对象的钩子函数会在组件自身的钩子函数之前执行。

使用场景

  1. 共享全局功能: 将一些通用的方法、数据或生命周期钩子放在混入对象中,从而在所有组件中共享这些功能。

    // 全局混入对象
    const globalMixin = {
      data() {
        return {
          sharedData: 'This data is shared across components',
        };
      },
      methods: {
        sharedMethod() {
          console.log('This method is shared across components');
        },
      },
    };
    
    // 在应用中应用全局混入
    Vue.mixin(globalMixin);
    
  2. 全局错误处理: 在混入对象中添加全局错误处理逻辑,以便在所有组件中捕获和处理错误。

    const errorHandlingMixin = {
      created() {
        // 在混入对象中添加全局错误处理逻辑
        this.$options.errorCaptured = (err, vm, info) => {
          console.error('Global error captured:', err, vm, info);
          // 处理错误逻辑
          return false; // 阻止错误继续传播
        };
      },
    };
    
    Vue.mixin(errorHandlingMixin);
    

注意事项

  1. 慎用全局混入: 全局混入影响每个组件,因此要谨慎使用。如果滥用全局混入,可能会导致不可预测的问题。

  2. 钩子函数执行顺序: 混入对象的生命周期钩子函数会在组件自身的钩子函数之前执行。这一点需要注意,因为可能会影响到一些逻辑的执行顺序。

会在组件自身的钩子函数之前执行。

使用场景

  1. 共享全局功能: 将一些通用的方法、数据或生命周期钩子放在混入对象中,从而在所有组件中共享这些功能。

    // 全局混入对象
    const globalMixin = {
      data() {
        return {
          sharedData: 'This data is shared across components',
        };
      },
      methods: {
        sharedMethod() {
          console.log('This method is shared across components');
        },
      },
    };
    
    // 在应用中应用全局混入
    Vue.mixin(globalMixin);
    
  2. 全局错误处理: 在混入对象中添加全局错误处理逻辑,以便在所有组件中捕获和处理错误。

    const errorHandlingMixin = {
      created() {
        // 在混入对象中添加全局错误处理逻辑
        this.$options.errorCaptured = (err, vm, info) => {
          console.error('Global error captured:', err, vm, info);
          // 处理错误逻辑
          return false; // 阻止错误继续传播
        };
      },
    };
    
    Vue.mixin(errorHandlingMixin);
    

注意事项

  1. 慎用全局混入: 全局混入影响每个组件,因此要谨慎使用。如果滥用全局混入,可能会导致不可预测的问题。

  2. 钩子函数执行顺序: 混入对象的生命周期钩子函数会在组件自身的钩子函数之前执行。这一点需要注意,因为可能会影响到一些逻辑的执行顺序。

  • 22
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值