天天看點

vue3 基礎-Mixin

mixin, 外部的對象能混入到 app 執行個體的操作

本篇開始來學習一波 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 進行配置

繼續閱讀