广告
返回顶部
首页 > 资讯 > 前端开发 > JavaScript >vue使用mixins优化组件
  • 107
分享到

vue使用mixins优化组件

2024-04-02 19:04:59 107人浏览 薄情痞子
摘要

目录mixins 实现钩子函数的合并项目实践extend总结Vue 提供了 mixins 这个 api,可以让我们将组件中的可复用功能抽取出来,放入 mixin 中,然后在组件中引入

Vue 提供了 mixins 这个 api,可以让我们将组件中的可复用功能抽取出来,放入 mixin 中,然后在组件中引入 mixin,可以让组件显得不再臃肿,提高了代码的可复用性。

如何理解 mixins 呢 ?我们可以将 mixins 理解成一个数组,数组中有单或多个 mixin,mixin 的本质就是一个 js 对象,它可以有 data、created、methods 等等 vue 实例中拥有的所有属性,甚至可以在 mixins 中再次嵌套 mixins,It's amazing !

举个简单的栗子:


<div id="app">
  <h1>{{ message }}</h1>
</div>

const myMixin = {
  data() {
    return {
      message: 'this is mixin message'
    }
  },
  created() {
    console.log('mixin created')
  }
}

const vm = new Vue({
  el: '#app',
  mixins: [myMixin],

  data() {
    return {
      message: 'this is vue instance message'
    }
  },
  created() {
    console.log(this.message)
    // => Root Vue Instance
    console.log('vue instance created')
    // => created myMixin
    // => created Root Vue Instance
  }
})

mixins 与 Vue Instance 合并时,会将 created 等钩子函数合并成数组,mixins 的钩子优先调用,当 data、methods 对象键值冲突时,以组件优先。

PS: 如果对 mixins 的概念还不太清的小伙伴,可以去 vue 官方文档 看一下 vue mixins 的基本概念和用法。

mixins 实现

那 mixins 是如何实现的呢 ?当 vue 在实例化的时候,会调用 mergeOptions 函数进行 options 的合并,函数申明在 vue/src/core/util/options.js 文件。


export function mergeOptions(
  parent: Object,
  child: Object,
  vm?: Component
): Object {
  ...
  // 如果有 child.extends 递归调用 mergeOptions 实现属性拷贝
  const extendsFrom = child.extends
  if (extendsFrom) {
    parent = mergeOptions(parent, extendsFrom, vm)
  }
  // 如果有 child.mixins 递归调用 mergeOptions 实现属性拷贝
  if (child.mixins) {
    for (let i = 0, l = child.mixins.length; i < l; i++) {
      parent = mergeOptions(parent, child.mixins[i], vm)
    }
  }
  // 申明 options 空对象,用来保存属性拷贝结果
  const options = {}
  let key
  // 遍历 parent 对象,调用 mergeField 进行属性拷贝
  for (key in parent) {
    mergeField(key)
  }
  // 遍历 parent 对象,调用 mergeField 进行属性拷贝
  for (key in child) {
    if (!hasOwn(parent, key)) {
      mergeField(key)
    }
  }
  // 属性拷贝实现方法
  function mergeField(key) {
    // 穿透赋值,默认为 defaultStrat
    const strat = strats[key] || defaultStrat
    options[key] = strat(parent[key], child[key], vm, key)
  }
  return options
}

为了保持代码简洁,已经将 mergeOptions 函数不重要的代码删除,剩余部分我们慢慢来看。


const extendsFrom = child.extends
if (extendsFrom) {
  parent = mergeOptions(parent, extendsFrom, vm)
}

首先申明 extendsFrom 变量保存 child.extends,如果 extendsFrom 为真,递归调用 mergeOptions 进行属性拷贝,并且将 merge 结果保存到 parent 变量。


if (child.mixins) {
  for (let i = 0, l = child.mixins.length; i < l; i++) {
    parent = mergeOptions(parent, child.mixins[i], vm)
  }
}

如果 child.mixins 为真,循环 mixins 数组,递归调用 mergeOptions 实现属性拷贝,仍旧将 merge 结果保存到 parent 变量。

接下来是关于 parent、child 的属性赋值:


const options = {}
let key

for (key in parent) {
  mergeField(key)
}

for (key in child) {
  if (!hasOwn(parent, key)) {
    mergeField(key)
  }
}

申明 options 空对象,用来保存属性拷贝的结果,也作为递归调用 mergeOptions 的返回值。

这里首先会调用 for...in 对 parent 进行循环,在循环中不断调用 mergeField 函数。

接着调用 for...in 对 child 进行循环,这里有点不太一样,会调用 hasOwn 判断 parent 上是否有这个 key,如果没有再调用 mergeField 函数,这样避免了重复调用。

那么这个 mergeField 函数到底是用来做什么的呢?


function mergeField(key) {
  // 穿透赋值,默认为 defaultStrat
  const strat = strats[key] || defaultStrat
  options[key] = strat(parent[key], child[key], vm, key)
}

mergeField 函数接收一个 key,首先会申明 strat 变量,如果 strats[key] 为真,就将 strats[key] 赋值给 strat。


const strats = config.optionMergeStrategies
...
optionMergeStrategies: Object.create(null),
...

strats 其实就是 Object.create(null),Object.create 用来创建一个新对象,strats 默认是调用 Object.create(null) 生成的空对象。

顺便说一句,vue 也向外暴露了 Vue.config.optionMergeStrategies,可以实现自定义选项合并策略。

如果 strats[key] 为假,这里会用 || 做穿透赋值,将 defaultStrat 默认函数赋值给 strat。


const defaultStrat = function(parentVal: any, childVal: any): any {
  return childVal === undefined ? parentVal : childVal
}

defaultStrat 函数返回一个三元表达式,如果 childVal 为 undefined,返回 parentVal,否则返回 childVal,这里主要以 childVal 优先,这也是为什么有 component > mixins > extends 这样的优先级。

mergeField 函数最后会将调用 strat 的结果赋值给 options[key]。

mergeOptions 函数最后会 merge 所有 options、 mixins、 extends,并将 options 对象返回,然后再去实例化 vue。

钩子函数的合并

我们来看看钩子函数是怎么进行合并的。


function mergeHook(
  parentVal: ?Array<Function>,
  childVal: ?Function | ?Array<Function>
): ?Array<Function> {
  return childVal
    ? parentVal
      ? parentVal.concat(childVal)
      : Array.isArray(childVal)
      ? childVal
      : [childVal]
    : parentVal
}

LIFECYCLE_HOOKS.forEach(hook => {
  strats[hook] = mergeHook
})

循环 LIFECYCLE_HOOKS 数组,不断调用 mergeHook 函数,将返回值赋值给 strats[hook]。


export const LIFECYCLE_HOOKS = [
  'beforeCreate',
  'created',
  'beforeMount',
  'mounted',
  'beforeUpdate',
  'updated',
  'beforeDestroy',
  'destroyed',
  'activated',
  'deactivated',
  'errorCaptured'
]

LIFECYCLE_HOOKS 就是申明的 vue 所有的钩子函数字符串

mergeHook 函数会返回 3 层嵌套的三元表达式。


return childVal
  ? parentVal
    ? parentVal.concat(childVal)
    : Array.isArray(childVal)
    ? childVal
    : [childVal]
  : parentVal

第一层,如果 childVal 为真,返回第二层三元表达式,如果为假,返回 parentVal。

第二层,如果 parentVal 为真,返回 parentVal 和 childVal 合并后的数组,如果 parentVal 为假,返回第三层三元表达式。

第三层,如果 childVal 是数组,返回 childVal,否则将 childVal 包装成数组返回。


new Vue({
  created: [
    function() {
      console.log('冲冲冲!')
    },
    function() {
      console.log('鸭鸭鸭!')
    }
  ]
})
// => 冲冲冲!
// => 鸭鸭鸭!

项目实践

使用 vue 的小伙伴们,当然也少不了在项目中使用 element-ui。比如使用 Table 表格的时候,免不了申明 tableData、total、pageSize 一些 Table 表格、Pagination 分页需要的参数。

我们可以将重复的 data、methods 写在一个 tableMixin 中。


export default {
  data() {
    return {
      total: 0,
      pageNo: 1,
      pageSize: 10,
      tableData: [],
      loading: false
    }
  },

  created() {
    this.searchData()
  },

  methods: {
    // 预申明,防止报错
    searchData() {},

    handleSizeChange(size) {
      this.pageSize = size
      this.searchData()
    },

    handleCurrentChange(page) {
      this.pageNo = page
      this.searchData()
    },

    handleSearchData() {
      this.pageNo = 1
      this.searchData()
    }
  }
}

当我们需要使用时直接引入即可:


import tableMixin from './tableMixin'

export default {
  ...
  mixins: [tableMixin],
  methods: {
    searchData() {
      ...
    }
  }
}

我们在组件内会重新申明 searchData 方法。类似这种 methods 对象形式的 key,如果 key 相同,组件内的 key 会覆盖 tableMixin 中的 key。

当然我们也可以在 mixins 中嵌套 mixins,申明 axiOSMixin:


import tableMixin from './tableMixin'

export default {
  mixins: [tableMixin],

  methods: {
    handleFetch(url) {
      const { pageNo, pageSize } = this
      this.loading = true

      this.axios({
        method: 'post',
        url,
        data: {
          ...this.params,
          pageNo,
          pageSize
        }
      })
        .then(({ data = [] }) => {
          this.tableData = data
          this.loading = false
        })
        .catch(error => {
          this.loading = false
        })
    }
  }
}

引入 axiosMixin:


import axiosMixin from './axiosMixin'

export default {
  ...
  mixins: [axiosMixin],
  created() {
    this.handleFetch('/user/12345')
  }
}

在 axios 中,我们可以预先处理 axios 的 success、error 的后续调用,是不是少写了很多代码。

extend

顺便讲一下 extend,与 mixins 相似,只能传入一个 options 对象,并且 mixins 的优先级比较高,会覆盖 extend 同名 key 值。


// 如果有 child.extends 递归调用 mergeOptions 实现属性拷贝
const extendsFrom = child.extends
if (extendsFrom) {
  parent = mergeOptions(parent, extendsFrom, vm)
}
// 如果有 child.mixins 递归调用 mergeOptions 实现属性拷贝
if (child.mixins) {
  for (let i = 0, l = child.mixins.length; i < l; i++) {
    parent = mergeOptions(parent, child.mixins[i], vm)
  }
}

// 如果有 child.extends 递归调用 mergeOptions 实现属性拷贝
const extendsFrom = child.extends
if (extendsFrom) {
  parent = mergeOptions(parent, extendsFrom, vm)
}
// 如果有 child.mixins 递归调用 mergeOptions 实现属性拷贝
if (child.mixins) {
  for (let i = 0, l = child.mixins.length; i < l; i++) {
    parent = mergeOptions(parent, child.mixins[i], vm)
  }
}

在 mergeOptions 函数中,会先对 extends 进行属性拷贝,然后再对 mixin 进行拷贝,在调用 mergeField 函数的时候会优先取 child 的 key。

虽然 extends 的同名 key 会被 mixins 的覆盖,但是 extends 是优先执行的。

总结

注意一下 vue 中 mixins 的优先级,component > mixins > extends。

我们暂且将 mixins 称作是组件模块化,灵活运用组件模块化,可以将组件内的重复代码提取出来,实现代码复用,也使我们的代码更加清晰,效率也大大提高。

当然,mixins 还有更加神奇的操作等你去探索。

以上就是vue使用mixins优化组件的详细内容,更多关于vue 用mixins优化组件的资料请关注编程网其它相关文章!

--结束END--

本文标题: vue使用mixins优化组件

本文链接: https://www.lsjlt.com/news/124889.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
  • vue使用mixins优化组件
    目录mixins 实现钩子函数的合并项目实践extend总结vue 提供了 mixins 这个 API,可以让我们将组件中的可复用功能抽取出来,放入 mixin 中,然后在组件中引入...
    99+
    2022-11-12
  • vue 父子组件共用mixins的注意点
    目录父子组件共用mixins的注意点详解mixins混入使用什么是Mixins?什么时候使用Mixins?如何创建Mixins?如何使用Mixins?Mixins的特点Mixins合...
    99+
    2022-11-13
  • Vue混入mixins分发组件可复用功能
    目录前言一、后端返回数据与字典数据之前的转换二、文件下载的混入三、Element表格最后一行合计数据的混入前言 那就是说,你可以单独写个逻辑文件,默认导出一个对象,对象里面可以包含d...
    99+
    2022-11-13
  • Vue 组件化基本使用详情
    目录1、什么叫做组件化 2、基本使用前言: 有时候有一组html结构的代码,并且这个上面可能还绑定了事件。然后这段代码可能有多个地方都被使用到了,如果都是拷贝来拷贝去,很多代码都是重...
    99+
    2022-11-12
  • Vue中如何使用vue mixins
    这篇文章主要介绍了Vue中如何使用vue mixins,具有一定借鉴价值,感兴趣的朋友可以参考下,希望大家阅读完这篇文章之后大有收获,下面让小编带着大家一起了解一下。使用场景:例如我们在Vue单页面开发的时...
    99+
    2022-10-19
  • Vue组件化ref,props, mixin怎么使用
    这篇文章主要介绍“Vue组件化ref,props, mixin怎么使用”的相关知识,小编通过实际案例向大家展示操作过程,操作方法简单快捷,实用性强,希望这篇“Vue组件化ref,props, mixin怎么使用”文章能帮...
    99+
    2023-06-30
  • Vue使用echarts可视化组件的方法
    echarts组件官网地址:https://echarts.apache.org/examples/zh/index.html 1.找到脚手架项目所在地址,执行cnpm instal...
    99+
    2022-11-12
  • 如何使用Vue实现组件化通讯
    这篇文章主要介绍了如何使用Vue实现组件化通讯的相关知识,内容详细易懂,操作简单快捷,具有一定借鉴价值,相信大家阅读完这篇如何使用Vue实现组件化通讯文章都会有所收获,下面我们一起来看看吧。1. Vue的组成文件(.vue)分为三部分,分别...
    99+
    2023-07-04
  • Vue中如何使用echarts可视化组件
    这篇文章将为大家详细讲解有关Vue中如何使用echarts可视化组件,文章内容质量较高,因此小编分享给大家做个参考,希望大家阅读完这篇文章后对相关知识有一定的了解。找到脚手架项目所在地址,执行cnpm install echarts,安装e...
    99+
    2023-06-20
  • vue组件化中slot怎么用
    这篇文章将为大家详细讲解有关vue组件化中slot怎么用,小编觉得挺实用的,因此分享给大家做个参考,希望大家阅读完这篇文章后可以有所收获。前言slot可以在子组件中开启插槽,在父组件引用该组建时,可以定义这...
    99+
    2022-10-19
  • Vue mixins混入如何使用
    这篇文章主要介绍了Vue mixins混入如何使用的相关知识,内容详细易懂,操作简单快捷,具有一定借鉴价值,相信大家阅读完这篇Vue mixins混入如何使用文章都会有所收获,下面我们一起来看看吧。一、什么是Mixins...
    99+
    2023-07-05
  • Vue首屏性能优化组件知识点总结
    Vue首屏性能优化组件 简单实现一个Vue首屏性能优化组件,现代化浏览器提供了很多新接口,在不考虑IE兼容性的情况下,这些接口可以很大程度上减少编写代码的工作量以及做一些性能优化方...
    99+
    2022-11-12
  • 使用vue组件封装共用的组件
    目录这里提供两种vue封装共用组件的方法方法一方法二vue封装公共组件调用方法这里提供两种vue封装共用组件的方法 方法一 main.js中 import ListItem from...
    99+
    2022-11-13
  • Vue组件中的父子组件使用
    目录Vue组件中的父子组件父组件向子组件传值子组件向父组件传值Vue父子组件的生命周期总结Vue组件中的父子组件 父组件向子组件传值 父组件通过属性绑定(v-bind:)的形式, 把...
    99+
    2023-01-28
    Vue组件 Vue父子组件 Vue父子组件使用
  • PHP的优化加速组件Opcache怎么使用
    这篇文章主要讲解了“PHP的优化加速组件Opcache怎么使用”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“PHP的优化加速组件Opcache怎么使用”吧!Opcache是一种通过将解析的P...
    99+
    2023-06-27
  • Vue项目首屏性能优化组件实战指南
    目录Vue首屏性能优化组件 描述 IntersectionObserver requestIdleCallback 实现 总结Vue首屏性能优化组件 简单实现一个Vue首屏性能优化...
    99+
    2022-11-12
  • Vue项目首屏性能优化组件方法教程
    本篇内容主要讲解“Vue项目首屏性能优化组件方法教程”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“Vue项目首屏性能优化组件方法教程”吧!Vue首屏性能优化组件简单实现一个Vue首屏性能优化组件...
    99+
    2023-06-25
  • Vue子组件监听父组件值的变化
    目录子组件监听父组件值变化子组件监听父组件的值同步更新数据子组件监听父组件值变化 子组件中利用watch监听父组件值的变化 // 子组件 props: ["a"],     watc...
    99+
    2022-11-13
  • Vue组件化常用方法之组件传值与通信
    相关知识点 父组件传值到子组件 子组件传值到父组件 兄弟组件之间传值 祖代和后代之间传值 任意两个组件之间传值 父组件传值到子组件 父组件传值到子组件基本方...
    99+
    2022-11-11
  • vue组件非单文件组件的使用步骤
    目录一,什么是组件二,非单文件组件2.1使用组件的三大步骤1.创建组件2.注册组件3.使用组件4.关于写法的注意点2.2组件的嵌套关于VueComponent 一,什么是组件 实现应...
    99+
    2023-01-11
    vue非单文件组件 vue组件
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作