• vue.js学习之组件(上篇)


    本文的Demo和源代码已放到GitHub,如果您觉得本篇内容不错,请点个赞,或在GitHub上加个星星!

    https://github.com/zwl-jasmine95/Vue_test

     以下所有知识都是基于vue.js 2.0版本


    组件 (Component) 是 Vue.js 最强大的功能之一。组件可以扩展 HTML 元素,封装可重用的代码。在较高层面上,组件是自定义元素,Vue.js 的编译器为它添加特殊功能。在有些情况下,组件也可以是原生 HTML 元素的形式,以 is 特性扩展。

    一、组件的创建与注册

    1、全局组件

    组件的使用有两个步骤:注册组件  使用组件。

    (1)要注册一个全局组件,可以使用 :

    Vue.component(tagName, options)

    例如:

    Vue.component('my-component', {
      // 选项
    })

     (2)创建根实例:

    //创建根实例
     var vm = new Vue({
            el:'#component-demo'
     });

    案例:

     1 <!DOCTYPE html>
     2 <html lang="en">
     3 <head>
     4     <meta charset="UTF-8">
     5     <title>全局组件(component)的基本使用</title>
     6 </head>
     7 <body>
     8     <div id="component-demo">
     9         <!-- 2. #component-demo是Vue实例挂载的元素,应该在挂载元素范围内使用组件-->
    10         <hello-component></hello-component>
    11     </div>
    12 
    13 <script type="text/javascript" src="../lib/js/vue.js"></script>
    14 <script type="text/javascript">
    15 
    16     //1.全局组件注册,并指定组件的标签,组件的HTML标签为<hello-component>
    17     Vue.component('hello-component',{
    18         template:'<h1>hello component!</h1>'
    19     });
    20 
    21     //创建根实例
    22     var vm = new Vue({
    23         el:'#component-demo'
    24     });
    25 
    26 </script>
    27 </body>
    28 </html>

    注意事项:

    1. 对于自定义标签名,Vue.js 不强制要求遵循 W3C 规则 (小写,并且包含一个短杠),尽管遵循这个规则比较好。
    2. 注册组件必须发生在根实例初始化前。
    3. 如果自定义标签名使用的是驼峰式命名,在使用的时候仍然要在大写字母处加上短杠,并将大写字母改为小写。例如:命名为‘helloWorldComponent’,在使用时变为<hello-world-component></hello-world-component>

    2、局部组件

     调用Vue.component()注册组件时,组件的注册是全局的,这意味着该组件可以在任意Vue示例下使用。
    如果不需要全局注册,或者是让组件使用在其它组件内,可以用选项对象的components属性实现局部注册

     1     <div id="component-demo">
     2         <local-component></local-component>
     3     </div>
     4     <script type="text/javascript">
     5     
     6         var child = {
     7             template:'<h1>局部组件的基本使用!</h1>'
     8         };
     9     
    10         var vm = new Vue({
    11             el:'#component-demo',
    12             components:{
    13                 'local-component':child
    14             }
    15         });
    16     </script>

    由于local-component组件是注册在#component-demo元素对应的Vue实例下的,所以它不能在其它Vue实例下使用。如果你这样做了,浏览器会提示一个错误:

     1 <!DOCTYPE html>
     2 <html lang="en">
     3 <head>
     4     <meta charset="UTF-8">
     5     <title>局部组件</title>
     6 </head>
     7 <body>
     8 
     9     <div id="component-demo">
    10         <local-component></local-component>
    11     </div>
    12 
    13     <div id="component-demo2">
    14         <!--这里会报错,因为local-component是#component-demo的局部组件,不能在其他地方使用-->
    15         <local-component></local-component>
    16     </div>
    17 
    18 <script type="text/javascript" src="../lib/js/vue.js"></script>
    19 <script type="text/javascript">
    20 
    21     var child = {
    22         template:'<h1>局部组件的基本使用!</h1>'
    23     };
    24 
    25     var vm = new Vue({
    26         el:'#component-demo',
    27         components:{
    28             'local-component':child
    29         }
    30     });
    31 
    32     var vm2 = new Vue({
    33         el:'#component-demo2'
    34     });
    35 
    36 
    37 </script>
    38 </body>
    39 </html>

     组件意味着协同工作,通常父子组件会是这样的关系:组件 A 在它的模版中使用了组件 B。它们之间必然需要相互通信:父组件要给子组件传递数据,子组件需要将它内部发生的事情告知给父组件。然而,在一个良好定义的接口中尽可能将父子组件解耦是很重要的。这保证了每个组件可以在相对隔离的环境中书写和理解,也大幅提高了组件的可维护性和可重用性。

    在 Vue 中,父子组件的关系可以总结为 props down, events up。父组件通过 props 向下传递数据给子组件,子组件通过 events 给父组件发送消息。


    二、组件的DOM模板解析说明

     当使用 DOM 作为模版时 (例如,将 el 选项挂载到一个已存在的元素上), 你会受到 HTML 的一些限制,因为 Vue 只有在浏览器解析和标准化 HTML 后才能获取模版内容。尤其像这些元素 <ul><ol><table><select> 限制了能被它包裹的元素,而一些像 <option> 这样的元素只能出现在某些其它元素内部。

    在自定义组件中使用这些受限制的元素时会导致一些问题,例如:

    <table>
      <my-row>...</my-row>
    </table>

    自定义组件 <my-row> 被认为是无效的内容,因此在渲染的时候会导致错误。变通的方案是使用特殊的 is 属性:

    <table>
      <tr is="my-row"></tr>
    </table>

    应当注意,如果您使用来自以下来源之一的字符串模板,这些限制将不适用:

    • <script type="text/x-template">
    • JavaScript 内联模版字符串
    • .vue 组件

    因此,有必要的话请使用字符串模版。


    三、组件字符串模板

    上述组件注册方法在template选项中拼接HTML元素比较麻烦,这也导致了HTML和JavaScript的高耦合性。庆幸的是,Vue.js提供了两种方式将定义在JavaScript中的HTML模板分离出来。

     1、使用 script 标签

     1 <!DOCTYPE html>
     2 <html lang="en">
     3 <head>
     4     <meta charset="UTF-8">
     5     <title>使用script标签</title>
     6 </head>
     7 <body>
     8 <div id="demo">
     9     <my-component></my-component>
    10 </div>
    11 
    12 <script type="text/x-template" id="myComponent">
    13     <h1>组件使用之使用script标签</h1>
    14 </script>
    15 
    16 <script type="text/javascript" src="../lib/js/vue.js"></script>
    17 <script type="text/javascript">
    18     Vue.component('my-component',{
    19         template:'#myComponent'
    20     });
    21 
    22     var vm = new Vue({
    23         el:'#demo'
    24     });
    25 </script>
    26 </body>
    27 </html>

    template选项现在不再是HTML元素,而是一个id,Vue.js根据这个id查找对应的元素,然后将这个元素内的HTML作为模板进行编译。

     

    注意:使用<script>标签时,type指定为text/x-template,意在告诉浏览器这不是一段js脚本,浏览器在解析HTML文档时会忽略<script>标签内定义的内容。

     2、使用 template 标签

     如果使用<template>标签,则不需要指定type属性。

     1 <!DOCTYPE html>
     2 <html lang="en">
     3 <head>
     4     <meta charset="UTF-8">
     5     <title>使用template标签</title>
     6 </head>
     7 <body>
     8 <div id="demo">
     9     <my-component></my-component>
    10 </div>
    11 
    12 <template id="myComponent">
    13     <h1>组件使用之使用template标签</h1>
    14 </template>
    15 
    16 <script type="text/javascript" src="../lib/js/vue.js"></script>
    17 <script type="text/javascript">
    18     Vue.component('my-component',{
    19         template:'#myComponent'
    20     });
    21 
    22     var vm = new Vue({
    23         el:'#demo'
    24     });
    25 </script>
    26 </body>
    27 </html>

    建议使用<script>或<template>标签来定义组件的HTML模板。这使得HTML代码和JavaScript代码是分离的,便于阅读和维护。


    四、组件data选项的限制

    通过 Vue 构造器传入的各种选项大多数都可以在组件里用。data 是一个例外,它必须是函数。

    如果这样写:

    Vue.component('hello-component',{
            template:'<h1>{{message}}</h1>',
            data:{
                message:1
            }
    });

    会报错:

     所以应该改为:

    Vue.component('my-component',{
            template:'<h1>{{message}}</h1>',
            data:function () {
                return {message : 'data必须为函数'};
            }
     });

    五、props—父组件向子组件传递信息

    组件实例的作用域是孤立的。这意味着不能 (也不应该) 在子组件的模板内直接引用父组件的数据。要让子组件使用父组件的数据,我们需要通过子组件的 props 选项。

     1、静态数据

     1    <div id="demo">
     2         <child-component message="hello props!"></child-component>
     3     </div>
     4 
     5     <template id="myComponent">
     6         <h1>{{message}}</h1>
     7     </template>
     8 
     9     <script type="text/javascript" src="../lib/js/vue.js"></script>
    10     <script type="text/javascript">
    11         var child = {
    12             // 声明 props
    13             props: ['message'],
    14             // 就像 data 一样,prop 可以用在模板内
    15             // 同样也可以在 vm 实例中像“this.message”这样使用
    16             template:'#myComponent'
    17         };
    18 
    19         var vm = new Vue({
    20             el:'#demo',
    21             components:{
    22                 'child-component':child
    23             }
    24         });
    25     </script>

    HTML 特性是不区分大小写的。所以,当使用的不是字符串模版,camelCased (驼峰式) 命名的 prop 需要转换为相对应的 kebab-case (短横线隔开式) 命名

     2、动态数据

    在模板中,要动态地绑定父组件的数据到子模板的 props,与绑定到任何普通的HTML特性相类似,就是用 v-bind。每当父组件的数据变化时,该变化也会传导给子组件。

     1 <body>
     2     <div id="demo">
     3         父组件信息:<input type="text" v-model="parentMessage">
     4         <child-component v-bind:message="parentMessage"></child-component>
     5     </div>
     6 
     7     <template id="myComponent">
     8         <h1>子组件获取的信息为:{{message}}</h1>
     9     </template>
    10 
    11     <script type="text/javascript" src="../lib/js/vue.js"></script>
    12     <script type="text/javascript">
    13 
    14         var child = {
    15             props: ['message'],
    16             template:'#myComponent'
    17         };
    18 
    19         var vm = new Vue({
    20             el:'#demo',
    21             data:{
    22                 parentMessage:'这里是父组件信息!'
    23             },
    24             components:{
    25                 'child-component':child
    26             }
    27         });
    28     </script>
    29 </body>

    demo

    初学者常犯的一个错误是使用字面量语法传递数值:

    <!-- 传递了一个字符串 "1" -->
    <comp some-prop="1"></comp>

    因为它是一个字面 prop,它的值是字符串 "1" 而不是 number。如果想传递一个实际的 number,需要使用 v-bind,从而让它的值被当作 JavaScript 表达式计算:

    <!-- 传递实际的 number -->
    <comp v-bind:some-prop="1"></comp>

    3、props的绑定类型—单项绑定

    prop 是单向绑定的:当父组件的属性变化时,将传导给子组件,但是不会反过来。这是为了防止子组件无意修改了父组件的状态。

     1 <!DOCTYPE html>
     2 <html lang="en">
     3 <head>
     4     <meta charset="UTF-8">
     5     <title>props单项数据绑定</title>
     6     <link rel="stylesheet" href="../lib/css/bootstrap.min.css">
     7 </head>
     8 <body>
     9     <div id="demo">
    10         <table class="table table-striped">
    11             <tr>
    12                 <td colspan="3">父组件数据</td>
    13             </tr>
    14             <tr>
    15                 <td>姓名</td>
    16                 <td>{{parentName}}</td>
    17                 <td><input type="text" v-model="parentName"/></td>
    18             </tr>
    19             <tr>
    20                 <td>年龄</td>
    21                 <td>{{parentAge}}</td>
    22                 <td><input type="text" v-model="parentAge"/></td>
    23             </tr>
    24         </table>
    25 
    26         <!--注意这里camelCased (驼峰式) 命名的 prop 需要转换为相对应的 kebab-case (短横线隔开式) 命名-->
    27         <child-component v-bind:child-name="parentName" v-bind:child-age="parentAge"></child-component>
    28 
    29     </div>
    30 
    31     <template id="myComponent">
    32         <table class="table table-striped">
    33             <tr>
    34                 <td colspan="3">子组件数据</td>
    35             </tr>
    36             <tr>
    37                 <td>姓名</td>
    38                 <td>{{childName}}</td>
    39             </tr>
    40             <tr>
    41                 <td>年龄</td>
    42                 <td>{{childAge}}</td>
    43             </tr>
    44         </table>
    45     </template>
    46 
    47     <script type="text/javascript" src="../lib/js/vue.js"></script>
    48     <script type="text/javascript">
    49 
    50         var child = {
    51             template:'#myComponent',
    52             props: ['childName','childAge']
    53 
    54         };
    55 
    56         var vm = new Vue({
    57             el:'#demo',
    58             data:{
    59                 parentName:'*茉莉花开*',
    60                 parentAge:22
    61             },
    62             components:{
    63                 'child-component':child
    64             }
    65         });
    66     </script>
    67 </body>
    68 </html>

    父组件的数据更改时,子组件的数据也跟着修改:

    每次父组件更新时,子组件的所有 prop 都会更新为最新值。这意味着你不应该在子组件内部改变 prop。如果你这么做了,Vue 会在控制台给出警告。

    为什么我们会有修改 prop 中数据的冲动呢?通常是这两种原因:

    1. prop 作为初始值传入后,子组件想把它当作局部数据来用;

    2. prop 作为初始值传入,由子组件处理成其它数据输出。

    对这两种原因,正确的应对方式是:

    1. 定义一个局部变量,并用 prop 的值初始化它:

      props: ['initialCounter'],
      data: function () {
          return { counter: this.initialCounter }
      }
    2. 定义一个计算属性,处理 prop 的值并返回。

      props: ['size'],
      computed: {
          normalizedSize: function () {
              return this.size.trim().toLowerCase()
          }
      }

    针对上述demo代码,我们可以稍作修改,将子组件从父组件获取的姓名变为新的姓名:

    我们可以看到效果:

    !!!在这里,父组件的姓名改变时,子组件的姓名不会跟着改变。

    demo

    注意:

    1.在 JavaScript 中对象和数组是引用类型,指向同一个内存空间,如果 prop 是一个对象或数组,在子组件内部改变它会影响父组件的状态。

    2.Vue 2.x相比较Vue 1.x而言,升级变化除了实现了Virtual-Dom以外,给使用者最大不适就是移除的组件的props的双向绑定功能。以往在Vue1.x中利用propstwoWay.sync绑定修饰符就可以实现props的双向绑定功能,但是在Vue2中彻底废弃了此功能,如果需要双向绑定需要自己来实现。

    4、props验证

     我们可以为组件的 props 指定验证规格。如果传入的数据不符合规格,Vue 会发出警告。当组件给其他人使用时,这很有用。

     要指定验证规格,需要用 对象的形式,而不能用字符串数组:

    Vue.component('example', {
      props: {
    
        // 基础类型检测 (`null` 意思是任何类型都可以)
        propA: Number,
    
        // 多种类型
        propB: [String, Number],
    
        // 必传且是字符串
        propC: {
          type: String,
          required: true
        },
    
        // 数字,有默认值
        propD: {
          type: Number,
          default: 100
        },
    
        // 数组/对象的默认值应当由一个工厂函数返回
        propE: {
          type: Object,
          default: function () {
            return { message: 'hello' }
          }
        },
    
        // 自定义验证函数
        propF: {
          validator: function (value) {
            return value > 10
          }
        }
      }
    })

    type 可以是下面原生构造器:

    • String
    • Number
    • Boolean
    • Function
    • Object
    • Array
    • Symbol

    type 也可以是一个自定义构造器函数,使用 instanceof 检测。

    当 prop 验证失败,Vue 会在抛出警告 (如果使用的是开发版本)。注意 props 会在组件实例创建之前进行校验,所以在 default 或 validator 函数里,诸如 datacomputed 或 methods 等实例属性还无法使用。

     实例:将第三小节中的demo代码修改,给传递的数据姓名和年龄加上验证,姓名必须为字符串类型,年龄必须为数字且不为空:

    在年龄那输入“m”,可以看见控制台报错了。因为传递的数据是字符串类型,而年龄props验证要求的是数字。

     demo


    六、组件自定义事件

    父组件是使用 props 传递数据给子组件,但子组件怎么跟父组件通信呢?这个时候 Vue 的自定义事件系统就派得上用场了。

     1、使用 v-on 绑定自定义事件

    每个 Vue 实例都实现了事件接口 (Events interface),即:

    • 使用 $on(eventName) 监听事件
    • 使用 $emit(eventName) 触发事件

    另外,父组件可以在使用子组件的地方直接用 v-on 来监听子组件触发的事件。不能用 $on 侦听子组件抛出的事件,而必须在模板里直接用 v-on 绑定。

     1 <!DOCTYPE html>
     2 <html lang="en">
     3 <head>
     4     <meta charset="UTF-8">
     5     <title>v-on绑定自定义事件</title>
     6     <script type="text/javascript" src="../lib/js/vue.js"></script>
     7 </head>
     8 <body>
     9     <div id="counter-event-example">
    10         <p>{{ total }}</p>
    11         <button-counter v-on:add="incrementTotal"></button-counter>
    12     </div>
    13 
    14     <script type="text/javascript">
    15 
    16         Vue.component('button-counter', {
    17             template: '<button v-on:click="incrementCounter">{{ counter }}</button>',
    18             data: function () {
    19                 return {
    20                     counter: 0
    21                 }
    22             },
    23             methods: {
    24                 incrementCounter: function () {
    25                     this.counter += 1;
    26                     this.$emit('add'); //向父组件报告,自己发生了‘add’事件
    27                 }
    28             }
    29         });
    30         new Vue({
    31             el: '#counter-event-example',
    32             data: {
    33                 total: 0
    34             },
    35             methods: {
    36                 incrementTotal: function () {
    37                     this.total += 1
    38                 }
    39             }
    40         })
    41     </script>
    42 </body>
    43 </html>
    View Code

    分析:

     第一步:在子组件里面把点击事件(click)绑定给了函数 incrementCounter(即图片里面的步骤1),这里容易理解,即点击了子组件的按钮将会触发位于子组件的 incrementCounter函数。

     第二步:在触发 incrementCounter 函数的时候,子组件的数字在原来值的基础上加1,并且表示向父组件报告自己触发了 add 事件(至于发生的事件叫什么名字,可以随意取名,只要在父组件中绑定时名称一致即可。)。

    第三步:  在子组件触发add事件的时候,父组件调用 incrementTotal 函数来响应子组件。

    这时我们回想步骤2,在子组件我们已经使用emit来进行通知,所以,这样就形成父子组件间的相互呼应传递信息,其实在开发的过程中父子组件通讯也都是使用这样的方法,父组件传递信息给子组件的时候会通过props参数,通常不会直接在子组件中修改父组件传递下来的信息,而且通过这样的一个钩子去通知父组件对某些参数进行改变。

    第四步:定义父组件的 incrementTotal 函数,数值在原基础上加1。

     2、给组件绑定原生事件

    有时候,你可能想在某个组件的根元素上监听一个原生事件。可以使用 .native 修饰 v-on。例如:

    <my-component v-on:click.native="doTheThing"></my-component>

    3、使用自定义事件的表单输入组件

    自定义事件可以用来创建自定义的表单输入组件,使用 v-model 来进行数据双向绑定。看看这个:

    <input v-model="something">

    这不过是以下示例的语法糖:

    <input v-bind:value="something" v-on:input="something = $event.target.value">

    所以在组件中使用时,它相当于下面的简写:

    <custom-input v-bind:value="something" v-on:input="something = arguments[0]"></custom-input>

    接受一个 value 属性所以要让组件的 v-model 生效,它应该 (在 2.2.0+ 这是可配置的):

    • 接受一个 value 属性
    • 在有新的值时触发 input 事件

    demo

     1 <div id="demo">
     2         <currency-input v-model="price"></currency-input>
     3     </div>
     4 
     5     <template id="currency">
     6         <span>$<input ref="input" v-bind:value="value" v-on:input="updateValue($event.target.value)" /></span>
     7     </template>
     8 
     9     <script type="text/javascript">
    10         Vue.component('currency-input',{
    11             template:'#currency',
    12             props: ['value'],
    13             methods: {
    14                 // 不是直接更新值,而是使用此方法来对输入值进行格式化和位数限制
    15                 updateValue: function (value) {
    16                     var formattedValue = value
    17                     // 删除两侧的空格符
    18                             .trim()
    19                             // 保留 2 小数位
    20                             .slice(0,value.indexOf('.') === -1 ? value.length: value.indexOf('.') + 3);
    21                     // 如果值不统一,手动覆盖以保持一致
    22                     if (formattedValue !== value) {
    23                         this.$refs.input.value = formattedValue
    24                     }
    25                     // 通过 input 事件发出数值
    26                     this.$emit('input', Number(formattedValue))
    27                 }
    28             }
    29         });
    30 
    31         var vm = new Vue({
    32             el:'#demo',
    33             data:{
    34                 price:''
    35             }
    36         })
    37     </script>

     (只能输入小数点后两位,只能输入数字)

     特殊属性 ref

    (预期:string)ref 被用来给元素或子组件注册引用信息。引用信息将会注册在父组件的 $refs 对象上。如果在普通的 DOM 元素上使用,引用指向的就是 DOM 元素; 如果用在子组件上,引用就指向组件实例:

    <!-- vm.$refs.p will be the DOM node -->
    <p ref="p">hello</p>
    <!-- vm.$refs.child will be the child comp instance -->
    <child-comp ref="child"></child-comp>

    当 v-for 用于元素或组件的时候,引用信息将是包含 DOM 节点或组件实例的数组。

    关于ref注册时间的重要说明: 因为ref本身是作为渲染结果被创建的,在初始渲染的时候你不能访问它们 - 它们还不存在!$refs 也不是响应式的,因此你不应该试图用它在模版中做数据绑定。

    4、定制组件的v-model

     (2.2.0新增)

    默认情况下,一个组件的 v-model 会使用 value 属性和 input 事件,但是诸如单选框、复选框之类的输入类型可能把 value 属性用作了别的目的。model 选项可以回避这样的冲突:

    Vue.component('my-checkbox', {
      model: {
        prop: 'checked',
        event: 'change'
      },
      props: {
        checked: Boolean,
        // this allows using the `value` prop for a different purpose
        value: String
      },
      // ...
    })
    <my-checkbox v-model="foo" value="some value"></my-checkbox>

    上述代码等价于:

    <my-checkbox :checked="foo" @change="val => { foo = val }" value="some value"></my-checkbox>

    5、.sync修饰符

    在一些情况下,我们可能会需要对一个 prop 进行『双向绑定』。事实上,这正是 Vue 1.x 中的 .sync修饰符所提供的功能。当一个子组件改变了一个 prop 的值时,这个变化也会同步到父组件中所绑定的值。这很方便,但也会导致问题,因为它破坏了『单向数据流』的假设。由于子组件改变 prop 的代码和普通的状态改动代码毫无区别,当光看子组件的代码时,你完全不知道它何时悄悄地改变了父组件的状态。这在 debug 复杂结构的应用时会带来很高的维护成本。

    上面所说的正是我们在 2.0 中移除 .sync 的理由。但是在 2.0 发布之后的实际应用中,我们发现 .sync 还是有其适用之处,比如在开发可复用的组件库时。我们需要做的只是让子组件改变父组件状态的代码更容易被区分。

    从 2.3.0 起我们重新引入了 .sync 修饰符,但是这次它只是作为一个编译时的语法糖存在。它会被扩展为一个自动更新父组件属性的 v-on 侦听器。

    如下代码

    <comp :foo.sync="bar"></comp>

    会被扩展为:

    <comp :foo="bar" @update:foo="val => bar = val"></comp>

    当子组件需要更新 foo 的值时,它需要显式地触发一个更新事件:

    this.$emit('update:foo', newValue)

     6、非父子组件通信

    有时候两个组件也需要通信 (非父子关系)。在简单的场景下,可以使用一个空的 Vue 实例作为中央事件总线,相当于中转站,可以用它来传递事件和接收事件。

    var bus = new Vue()
    
    // 触发组件 A 中的事件
    bus.$emit('id-selected', 1)
    
    // 在组件 B 创建的钩子中监听事件
    bus.$on('id-selected', function (id) {
      // ...
    })

    下面用一个实例来说明:

     1 <div id="demo">
     2         <a-component></a-component>
     3         <b-component></b-component>
     4     </div>
     5 
     6 
     7     <script type="text/javascript">
     8         Vue.component('a-component',{
     9             template:'<button @click="submit">提交</button>',
    10             methods: {
    11                 submit() {
    12                     // 事件名字自定义,用不同的名字区别事件
    13                     this.$root.Bus.$emit('eventName', 123)
    14                 }
    15             }
    16         });
    17 
    18         Vue.component('b-component',{
    19             template:'<p>{{message}}</p>',
    20             data:function () {
    21               return {
    22                   message:'b子组件'
    23               }
    24             },
    25 
    26             // 当前实例创建完成就监听这个事件
    27             created(){
    28                 this.$root.Bus.$on('eventName', function (value) {
    29                     console.log(value);
    30                 });
    31             },
    32 
    33             // 在组件销毁时别忘了解除事件绑定
    34             beforeDestroy() {
    35                 this.$root.Bus.$off('eventName')
    36             }
    37         });
    38 
    39         var vm = new Vue({
    40             el:'#demo',
    41             data: {
    42                 // 空的实例放到根组件下,所有的子组件都能调用
    43                 Bus: new Vue()
    44             }
    45         })
    46     </script>


    本文的Demo和源代码已放到GitHub  https://github.com/zwl-jasmine95/Vue_test

     点个赞呗~~┑( ̄▽  ̄)┍

  • 相关阅读:
    OpenCASCADE Chamfer 3D Basics
    OpenCASCADE Chamfer 2D
    .NetCore 连接 Oracle 数据库,直接C# 或者 ORM框架(EFCore、XPO)
    心内科疾病指南
    HttpClient 调用 RestAPI 接口的用法
    在 Blazor 应用中使用 DevExtreme widgets
    2021 最近一次检查甘油三脂,验证苯扎贝特的效果。
    紫鹊界本味湘菜,
    如何Rest接口获取网上的股票数据,有哪些资源?-- 推荐Tushare金融数据
    优秀常用的「资源搜索网站」,收藏
  • 原文地址:https://www.cnblogs.com/jasmine-95/p/7275178.html
Copyright © 2020-2023  润新知