zoukankan      html  css  js  c++  java
  • Vue中的Mixins

    在项目开发的时候,常会碰到这样的一种现象:有两个组件非常相似,比如较为熟悉的 Modal 、 Tooltip 和 Popover ,它们都具有同样的基本函数,而且它们之前也有足够的不同。很多时候,就让人很难做出选择:是把它们拆会成多个不同的组件呢?还是只使用一个组件,创建足够的属性来改变不同的情况。

    这些解决方案都不够完美。如果拆会成多个组件,就不得不冒着如果功能变动你要在多个文件中更新它的风险。另一方面,太多的属笥会很快变得混乱,难维护,甚至对于组件开发者自已面言,也是件难事。

    在Vue中,对于这样的场景,官方提供了一种叫混入 (mixins) 的特性。使用 mixins 允许你封装一块在应用的其他组件中都可以使用的函数。如果被正确的使用,他们不会改变函数作用域外部的任何东西,所以多次执行,只要是同样的输入,总是能得到一样的值。

    既然Vue的 mixins 这么优秀,那应该怎么使用呢?今天我们的目的就是学习如何在Vue的项目中使用 mixins 。

    什么是Mixins

    Vue的官方文档是这样描述 mixins 的:mixins是一种分发Vue组件中可复用功能的一种灵活方式。

     mixins 是一个JavaScript对象,可以包含组件中的任意选项,比如Vue实例中生命周期的各个钩子函数,也可以是 data 、 components 、 methods 或 directives 等。在Vue中, mixins 为我们提供了在Vue组件中共用功能的方法。使用方式很简单,将共用的功能以对象的方式传入 mixins 选项中。当组件使用 mixins 对象时,所有 mixins 对象的选项都将被混入该组件本身的选项。

    如何创建Mixins

    在Vue中,创建 mixins 方法很简单。简单一点的,在Vue组件中,我们将 mixins 对象指定为:

     1 const myMixin = {
     2     created () {
     3         console.log(`来自Mixins中的消息`)
     4     }
     5 }
     6 
     7 let app = new Vue({
     8     el: '#app',
     9     mixins: [myMixin]
    10 })

    上面看到的方式是在组件中声明一个 mixins 对象。如果组件多起来,这样的方式,感觉还是没有解决我们文章提到的需求一样。更好的做法,我们可以像下面这样做。比如在项目的src下面创建一个存放 mixins 的目录,比如一个叫 mixin 目录。然后这个目录中创建你想要的.js文件,比如这里创建了一个叫 mixins.js :

    为了方便演示,把上面创建的 mixins 相关的代码移入 mixins.js 文件中:

    1 // src/mixins/mixins.js
    2 export const myMixin = {
    3     created() {
    4         console.log(`来自Mixins中的消息`);
    5     }
    6 };

    在需要使用该 mixins 的组件中先引入 mixins.js 文件,接着在组件中的 mixins 选择中调用在 mixins.js 创建的 mixins ,比如:

    // HelloWorld.vue
    <script>
    import { myMixin, myMixin2 } from "../mixins/mixins.js";
    
    export default {
        name: "HelloWorld",
        data() {
            return {
                msg: "From Vue Component"
            };
        },
        mixins: [myMixin]
    };
    </script>

    这种方式和前面使用  mixins  方式最终得到的结果是一样的。

    使用  mixins  ,在  mixins  中指定的任何选项都会立即与Vue组件的选项合并。可以在组件的  mixins  数组中指定多个  mixin  。一旦指定了,所有的  mixin  选项都会被导入到组件中。比如:

     1 // mixins.js
     2 export const mixObj = {
     3     created() {
     4         this.hello()
     5     },
     6     methods: {
     7         hello() {
     8             console.log(`Hello from Mixin`)
     9         }
    10     }
    11 }
    12 export const minObjAnother = {
    13     created () {
    14         this.prompt()
    15     },
    16     methods: {
    17         prompt() {
    18             console.log(`Prompt from Mixin Another`)
    19         },
    20         hello() {
    21             console.log(`Hello from Mixin Another`)
    22         }
    23     }
    24 }

    如果在组件中要同时调用  mixObj  和  minObjAnother  两个  mixins  时,需要在组件的  mixins  选项的值添加这两个  mixins  ,比如:

    1 <!-- HelloWorld.vue -->
    2 <script>
    3 import { mixObj, minObjAnother } from "../mixins/mixins.js";
    4 
    5 export default {
    6     name: "HelloWorld",
    7     mixins: [mixObj, minObjAnother],
    8 };
    9 </script>

    此时在  console  中输出的结果如下:

    Vue2.0学习笔记:Vue中的Mixins

    从输出的结果中我们可以看出,  mixObjAnother  中的  hello()  方法取替了  mixObj  中的  hello()  方法。

    是不是感到疑惑。如果是,请继续往下阅读。

    合并选项和冲突

    当组件和混入对象含有同名选项时,这些选项将以恰当的方式混合。

    什么是“ 恰当的方式 ”?对于我这样的初学者而言,有点难于理解。上例中我们看到了,每个  mixins  对象中都具有生命周期的钩子(Vue生命周期)和方法(甚至其他的),而且这些东西都是可用的。另外在Vue中的组件,同样也有这些生命周期的钩子函数和方法。所以当在组件上注册重复的过程时,顺序显得尤其重要。

    默认是  mixins  上会首先被注册,组件上的接着注册!

    这样的做主要是因为必要时可以重写。

    组件拥有最终发言权: 当有一个冲突并且这个组件不得不决定哪个胜出的时候,这真的变得很重要,否则,所有东西都被放在一个数组中执行,  mixins  中的先执行,组件中的接着执行。

    在Vue中  mixins  常见的合并主要有三种情形:数据  data  、生命周期中的钩子函数和值为对象的选项。接下来,咱们分别来看看这三种情形:

    数据合并

    数据对象在内部分进行浅合并(一层属性深度),在和组件的数据发生冲突时, 以组件数据优先 。

     1 // mixins.js
     2 export const mixObj = {
     3     data() {
     4         return {
     5             msg: "Message from Mixin Object"
     6         };
     7     }
     8 };
     9 export const minObjAnother = {
    10     data() {
    11         return {
    12             msg: "Message from Mixin Object Another",
    13             name: "Foo"
    14         };
    15     }
    16 };
    17 
    18 <!-- HelloWorld.vue -->
    19 <script>
    20     import { mixObj, minObjAnother } from "../mixins/mixins.js";
    21 
    22     export default {
    23         name: "HelloWorld",
    24         data() {
    25             return {
    26                 msg: "Message from Vue Component",
    27                 name: 'Bar',
    28                 age: 20
    29             };
    30         },
    31         mixins: [mixObj, minObjAnother],
    32         created () {
    33             console.log(this.$data)
    34         }
    35     };
    36 </script>

    Vue2.0学习笔记:Vue中的Mixins

    最终的结果是, HelloWorld 组件中的 msg 和 name 取替了 mixins 中的,另外 age 字段被合并进行。

    钩子函数合并

    当组件使用的  mixins 对象有相同的选项时,比如钩子函数,就会全部被合并到一个数组中,因此都会被执行,并且  mixins `对象中的钩子会先被执行。

     1 const myMixin = {
     2     created () {
     3         console.log(`来自Mixins中的消息`)
     4     }
     5 }
     6 
     7 new Vue({
     8     el: '#app',
     9     mixins: [myMixin],
    10     created () {
    11         console.log(`来自组件中的消息`)
    12     }
    13 })

    Vue2.0学习笔记:Vue中的Mixins

    值为对象选项合并

    当 mixins 对象和组件中的选项的值为对象时,比如  methods  、  components  和  directives  ,将被混合为同一个对象。当两个对象键名冲突时, 组件选项优先 。

     1 const myMixin = {
     2     data () {
     3         return {
     4             msg: 'From Vue Mixins'
     5         }
     6     },
     7     created() {
     8         console.log(`来自Mixins的消息`)
     9     },
    10     methods: {
    11         message () {
    12             console.log(this.msg)
    13         }
    14     }
    15 };
    16 export default {
    17     name: "HelloWorld",
    18     data() {
    19         return {
    20             msg: "From Vue Component"
    21         };
    22     },
    23     mixins: [myMixin],
    24     created() {
    25         console.log(`来自组件的消息`)
    26     },
    27     methods: {
    28         message () {
    29             console.log(this.msg)
    30         }
    31     }
    32 };

    Vue2.0学习笔记:Vue中的Mixins

    全局Mixins

    当我们使用全局混合时,我们不是指能够在每个组件上访问它们,就像是过滤器一样。我们能够通过  mixins:[myMixins]  访问组件上的混合对象。

    全局混合被注册到了每个单一组件上。因此,它们的使用场景极其有限并且要非常的小心。一个我能想到的用途就是它像一个插件,你需要赋予它访问所有东西的权限。但即使在这种情况下,我也对你正在做的保持警惕,尤其是你在应用中扩展的函数,可能对你来说是不可知的

    为了创建一个全局实例,我们可以把它放在 Vue 实例之上。在一个典型的 Vue-cli 初始化的项目中,它可能在你的  main.js  文件中。

    1 Vue.mixin({
    2     mounted() {
    3         console.log('hello from mixin!')
    4     }
    5 })
    6 
    7 new Vue({
    8     ...
    9 })

    谨慎使用全局混入对象,因为会影响到每个单独创建的 Vue 实例 (包括第三方模板)。大多数情况下,只应当应用于自定义选项,就像上面示例一样。也可以将其用作 Plugins 以避免产生重复应用。

    使用Mixins实例

    经过上面的介绍,我们对Vue中的  mixins  应该有了一定的了解。接下来通过简单的实例来向大家阐述在项目中怎么使用上面介绍的  mixins  。

    先来看一个简单的示例,也就是文章中提到的  Modal  和  Tooltip  组件。虽然这两个组件是不同的组件,但实际上它们的作用是类似的: 切换一个状态布尔值 。换句话说,这两个组件表面上看起来不一样,用法不一样,但逻辑是一样的。

     1 // 模态框
     2 const Modal = {
     3     template: '#modal',
     4     data() {
     5         return {
     6             isShowing: false
     7         }
     8     },
     9     methods: {
    10         toggleShow() {
    11             this.isShowing = !this.isShowing;
    12         }
    13     },
    14     components: {
    15         appChild: Child
    16     }
    17 }
    18 
    19 // 提示框
    20 const Tooltip = {
    21     template: '#tooltip',
    22     data() {
    23         return {
    24             isShowing: false
    25         }
    26     },
    27     methods: {
    28         toggleShow() {
    29             this.isShowing = !this.isShowing;
    30         }
    31     },
    32     components: {
    33         appChild: Child
    34     }
    35 }

    我们可以提取出这个逻辑并创建可以被重用的项:

     1 // toggle.js
     2 export const toggle = {
     3     data() {
     4         return {
     5             isShowing: false
     6         };
     7     },
     8     methods: {
     9         toggleShow() {
    10             this.isShowing = !this.isShowing;
    11         }
    12     }
    13 };
    14 
    15 <!-- Modal.vue -->
    16 <template>
    17     <div>
    18         <h3>Let's trigger this here modal!</h3>
    19         <button @click="toggleShow">
    20             <span v-if="isShowing">Hide child</span>
    21             <span v-else>Show child</span>
    22         </button>
    23         <Child v-if="isShowing" class="modal">
    24             <button @click="toggleShow">Close</button>
    25         </Child>
    26     </div>
    27 </template>
    28 
    29 <script>
    30     import Child from "./Child";
    31     import { toggle } from "../mixins/toggle.js";
    32 
    33     export default {
    34         name: "Modal",
    35         mixins: [toggle],
    36         components: {
    37             Child
    38         }
    39     };
    40 </script>
    41 
    42 <!-- ToolTip.vue -->
    43 <template>
    44     <div class="tooltip-demo">
    45         <h3 @click="toggleShow">
    46             <span v-if="isShowing">Click Me Again</span>
    47         <span v-else>Click Me Please</span>
    48         </h3>
    49         <Child v-if="isShowing" class="tooltip">
    50             <p>I'm a tooltip this time</p>
    51         </Child>
    52     </div>
    53 </template>
    54 
    55 <script>
    56     import { toggle } from '../mixins/toggle.js'
    57     import Child from './Child'
    58 
    59     export default {
    60         name: 'ToolTip',
    61         mixins: [toggle],
    62         components: {
    63             Child
    64         }
    65     }
    66 </script>

    著作权归作者所有。
    商业转载请联系作者获得授权,非商业转载请注明出处。
    原文: https://www.w3cplus.com/vue/vue-mixins.html © w3cplus.com著作权归作者所有。

  • 相关阅读:
    如何让json_decode解码变的更加强壮
    scp命令
    Centos7安装postgresql
    ubuntu安装Java环境
    ubuntu开放端口
    VMware安装Ubuntu
    redis主从安装
    redis主从学习
    redis集群学习
    C++ 09 顺序容器
  • 原文地址:https://www.cnblogs.com/joyco773/p/14741899.html
Copyright © 2011-2022 走看看