vue3 基础-Mixin

本篇开始来学习一波 vue 中的一些复用性代码的基础操作, 首先来介绍关于代码 "混入" mixin 的写法. 直观理解这个 mixin 就是一个 js 对象去 "混入" vue 的组件呀, 插件呀之类的片段中.

mixin 直观认识

<!DOCTYPE html>
<html lang="en">

<head>
  <title>mixin 混入</title>
  <script src="https://unpkg.com/vue@3"></script>
</head>

<body>
  <div id="root"></div>
  <script>
    // mixin 对象混入
    const myMixin = {
      data () {
        return { num: 999 }
      }
    }

    const app = Vue.createApp({
      data () {
        return { num: 666, youge:"nb" }
      },
      // 其实就是在 vue 之外定义的一段代码, 通过 mixins 属性混进来
      mixins: [myMixin],
      template: `
      <div>
        <div>{{num}} - {{youge}}</div>
      </div>
      `
    })
    const vm = app.mount('#root')

  </script>
</body>

</html>

上述代码即我们在 vue 的外面定义了一个叫 myMixin 的对象, 里面也有一个 data ( ) 的方法. 然后将其整个通过 vue 实例 app 的 mixins 属性成功 "混入" 了进来. 这个其实就是混入的概念呀.

值得注意的是, 属性发生冲突时, 如这里的组件 data 和 混合 data 冲突, 或者 methods 冲突, 组件属性的优先级会高于 mixin 的优先级.

生命周期函数混入

和 data ( ) 是相反的, 会先执行 mixin, 后执行组件的.

<!DOCTYPE html>
<html lang="en">

<head>
  <title>mixin 混入</title>
  <script src="https://unpkg.com/vue@3"></script>
</head>

<body>
  <div id="root"></div>
  <script>
    // mixin 对象混入
    const myMixin = {
      data () {
        return { num: 999, youge:"nb" }
      },
      // 生命周期函数先执行 mixin, 后执行组件的
      created () {
        console.log('mixin created')
      }
    }

    const app = Vue.createApp({
      data () {
        return { num: 666 }
      },
      mixins: [myMixin],
      // 组件的生命周期函数会被后执行
      created () {
        console.log('app created')
      },
      template: `
      <div>
        <div>{{num}} - {{youge}}</div>
      </div>
      `
    })
    const vm = app.mount('#root')

  </script>
</body>

</html>

这种在 vue 之外定义的对象, 通过 mixins 属性可以实现最外层的混入. 但如果有子组件的存在, 则子组件就不能使用这个 mixin 因为它是局部的, 就和之前局部组件和全局组件一样. 如果一定要使用, 则可以在子组件中进行 mixin, 这就略有一丢麻烦

<!DOCTYPE html>
<html lang="en">

<head>
  <title>子组件用 mixin</title>
  <script src="https://unpkg.com/vue@3"></script>
</head>

<body>
  <div id="root"></div>
  <script>
    const myMixin = {
      data () {
        return { num: 999, youge:"nb" }
      },
    }

    const app = Vue.createApp({
      data () {
        return { num: 666 }
      },
      mixins: [myMixin],
      created () {
        console.log('app created')
      },
      template: `
      <div>
        <div>{{num}} - {{youge}}</div>
        <Son />
      </div>
      `
    })

    // 子组件不能直接用父组件的 mixin, 只能自己来进行混入
    app.component('Son', {
      mixins: [myMixin],
      template: `<div>son-{{youge}}</div>`
    })

    const vm = app.mount('#root')

  </script>
</body>

</html>

可以发现这样写 mixin 其实是一个局部的, 一次定义多次引用, 这个没啥问题, 但基于咱对这种 vue 的父子组件来说, 感觉还是有点怪怪的, 理想中, 这个这个 mixin 都混入父组件了, 为啥子组件还不能直接引用, 额, 它就是不能.

当然, 我们还通过注册全局 mixin 来实现它.

<!DOCTYPE html>
<html lang="en">

<head>
  <title>全局 mixin</title>
  <script src="https://unpkg.com/vue@3"></script>
</head>

<body>
  <div id="root"></div>
  <script>
    const app = Vue.createApp({
      data() {
        return { num: 666 }
      },
      created() {
        console.log('app created')
      },
      template: `
      <div>
        <div>{{num}} - {{youge}}</div>
      </div>
      `
    })

    // 注册全局 mixin 所有组件自动注入
    app.mixin({
      data() {
        return { num: 999, youge: "nb" }
      },
      created() {
        console.log('mixin created')
      }
    })

    const vm = app.mount('#root')

  </script>
</body>

</html>

则通过 app.mixin ({ }) 的写法就将这个这个 mixin 对象全局混入了. 但是呢这种写法不推荐, 这和全局组件一样的, 一个是维护上的问题, 一个是性能上的问题啦.

自定义属性

在默认情况下, 组件中的属性优先级高于 mixin 中的属性, 其演示如下:

<!DOCTYPE html>
<html lang="en">

<head>
  <title>自定义属性</title>
  <script src="https://unpkg.com/vue@3"></script>
</head>

<body>
  <div id="root"></div>
  <script>
    const myMixin = {
      num: 666
    }

    const app = Vue.createApp({
      mixins: [myMixin],
      num: 999,
      template: `
      <div>
        <div>{{this.$options.num}}</div>
      </div>
      `
    })

    const vm = app.mount('#root')

  </script>
</body>

</html>

注意在 vue 实例中, 所有的属性最终都会挂载到 $options 中, 只不过我们常用的 data, methods, template ... 等已经有内置了就直接对应上啦. 那对于其他的就是挂载到最外层呀.

但 vue 也提供了对于这种自定义属性的合并策略是可以自定义的, 比如我们就要让 mixin 的属性优先级高于组件, 则可以通过 app.config.optionMergeStrategies.xxx 的方式进行配置即可.

<!DOCTYPE html>
<html lang="en">

<head>
  <title>自定义属性的优先配置</title>
  <script src="https://unpkg.com/vue@3"></script>
</head>

<body>
  <div id="root"></div>
  <script>
    const myMixin = {
      num: 666
    }

    const app = Vue.createApp({
      mixins: [myMixin],
      num: 999,
      template: `
      <div>
        <div>{{this.$options.num}}</div>
      </div>
      `
    })

    // 编写 自定义属性 的优先策略配置
    app.config.optionMergeStrategies.num = (mixinValue, appValue) => {
      return mixinValue || appValue
    }
  
    const vm = app.mount('#root')

  </script>
</body>

</html>

但基于 vue3 的新特性, 其实这种 mixin 的写法相对少了很多, 更多则会有 CompositonAPI 的方式来做替换会显得更加强大和灵活啦.

小结

  • mixin 混入的意思就是在 vue 实例之外的对象可以通过 app 的 mixins 属性混入 vue 中来管理使用
  • 组件 data, methods 的优先级高于 mixin , 即只会显示一个
  • 生命周期函数 mixin 的优先级高于组件, 会依次调用
  • 自定义属性的组件优先级高于 mixin, 但可通过 app.config.optionMergeStrategies.xxx 进行配置
posted @ 2022-09-24 23:00  致于数据科学家的小陈  阅读(1203)  评论(0编辑  收藏  举报