Vue基础(六)--组件及组件间的通讯

1.什么是组件

  • 扩展HTML元素,封装可重用的代码。
  • 组件是自定义元素(对象)。

2.定义组件的方式

方式1:先创建组件构造器,然后由组件构造器创建组件
方式2:直接创建组件

示例:

<!doctype html>
<html>

    <head>
        <meta charset="utf-8">
        <title></title>
        <meta name="viewport" content="width=device-width,initial-scale=1,minimum-scale=1,maximum-scale=1,user-scalable=no" />
        <link href="../css/mui.min.css" rel="stylesheet" />
    </head>

    <body>
        <header class="mui-bar mui-bar-nav">
            <h1 class="mui-title">定义组件的两种方式</h1>
        </header>
        <div class="mui-content" id="content">
            <yxc></yxc>
            <hello></hello>
        </div>
        <script src="../js/vue.js"></script>
        <script src="../js/mui.min.js"></script>
        <script type="text/javascript">
            mui.init()
            /**
             * 方式1:先创建组件构造器,然后由组件构造器创建组件
             */
            //1.使用Vue.extend创建一个组件构造器
            var MyComponent=Vue.extend({
                template:'<h3>hello world</h3>'
            })
            //2.使用Vue.component('标签名',组件构造器),根据组件构造器来创建组件
            Vue.component('yxc',MyComponent);
            
            
            /**
             * 方式2:直接创建组件(推荐)
             */
            Vue.component('hello',{
                template:'<h3>hello component!</h3>'
            })
            var vm=new Vue({//这里的vm也是一个组件,称为根组件Root
                el:"#content",
                data:{
                    
                }
            })
        </script>
    </body>

</html>

3.组件的分类

  • 全局组件
  • 局部组件

示例:

<!doctype html>
<html>

    <head>
        <meta charset="utf-8">
        <title></title>
        <meta name="viewport" content="width=device-width,initial-scale=1,minimum-scale=1,maximum-scale=1,user-scalable=no" />
        <link href="../css/mui.min.css" rel="stylesheet" />
    </head>

    <body>
        <header class="mui-bar mui-bar-nav">
            <h1 class="mui-title">定义组件的两种方式</h1>
        </header>
        <div class="mui-content" id="content">
            <hello></hello>
            <world></world>
        </div>
        <script src="../js/vue.js"></script>
        <script src="../js/mui.min.js"></script>
        <script type="text/javascript">
            mui.init()

            /**
             * 全局组件,可以在所有Vue实例中调用
             */
            Vue.component('hello', {
                template: '<h3>{{name}}</h3>',
                data:function(){//在组件中存储数据时,必须以函数的形式,函数返回一个对象
                    return{
                        name:"hello,我是全局组件"
                    }
                }
            })
            /**
             * 局部组件,只能在当前Vue实例中调用
             */
            var vm = new Vue({
                el: "#content",
                data: {

                },
                components: {//局部组件
                    'world': {
                        template: '<h3>hello,我是{{msg}}</h3>',
                        data(){
                            return{
                                msg:"局部组件"
                            }
                        }
                    }
                }
            })
        </script>
    </body>

</html>

4.引用模板

将组建的内容放到模板<template>中并引用.

示例:

<!doctype html>
<html>

    <head>
        <meta charset="utf-8">
        <title></title>
        <meta name="viewport" content="width=device-width,initial-scale=1,minimum-scale=1,maximum-scale=1,user-scalable=no" />
        <link href="../css/mui.min.css" rel="stylesheet" />
    </head>

    <body>
        <header class="mui-bar mui-bar-nav">
            <h1 class="mui-title">引用模板</h1>
        </header>
        <div class="mui-content" id="content">
            <my_temp></my_temp>
        </div>
        <!-- <template>必须有且只有一个根元素 -->
        <template id="test">
            <div>
                <h4>{{msg}}</h4>
                <ul>
                    <li v-for="item in arr">{{item}}</li>
                </ul>
            </div>
        </template>
        
        
        <script src="../js/vue.js"></script>
        <script src="../js/mui.min.js"></script>
        <script type="text/javascript">
            mui.init()
            /**
             * 局部组件,只能在当前Vue实例中调用
             */
            var vm = new Vue({
                el: "#content",
                data: {

                },
                components: {//局部组件
                    'my_temp': {
                        name:'tepmName',//指定组件的名称,默认为标签名,可以不展示
                        template: '#test',
                        data(){
                            return{
                                msg:"局部组件",
                                arr:['tom','jack','mike']
                            }
                        }
                    }
                }
            })
        </script>
    </body>

</html>

5. 动态组件

使用<component :is=''>组件,也就是多个组件使用同一个挂载点,然后动态的在它们之间切换。
用法:渲染一个“元组件”为动态组件。依 is 的值,来决定哪个组件被渲染。

<!-- 动态组件由 vm 实例的属性值 `componentId` 控制 -->
<component :is="componentId"></component>

示例:

<!doctype html>
<html>

    <head>
        <meta charset="utf-8">
        <title></title>
        <meta name="viewport" content="width=device-width,initial-scale=1,minimum-scale=1,maximum-scale=1,user-scalable=no" />
        <link href="../css/mui.min.css" rel="stylesheet" />
    </head>

    <body>
        <header class="mui-bar mui-bar-nav">
            <h1 class="mui-title">动态组件</h1>
        </header>
        <div class="mui-content" id="content">
            <button @click="flag='my_test1'">显示my_test1组件</button>
            <button @click="flag='my_test2'">显示my_test2组件</button>

            <div>
                <component :is='flag'></component>
            </div>
        </div>

        <!-- <template>必须有且只有一个根元素 -->
        <template id="test1">
            <div>
                <h4>{{msg}}</h4>
                <ul>
                    <li v-for="item in arr">{{item}}</li>
                </ul>
            </div>
        </template>


        <script src="../js/vue.js"></script>
        <script src="../js/mui.min.js"></script>
        <script type="text/javascript">
            mui.init()
            var vm = new Vue({
                el: "#content",
                data: {
                    flag: 'my_test1'
                },
                components: { //局部组件
                    'my_test1': {
                        name: 'tepmName', //指定组件的名称,默认为标签名,可以不展示
                        template: '#test1',
                        data() {
                            return {
                                msg: "我是test1组件",
                                arr: ['tom', 'jack', 'mike']
                            }
                        }
                    },
                    'my_test2': {
                        template: '<h4>我是test2组件{{y}}</h4>',
                        data() {
                            return {
                                y: Math.random()
                            }
                        }
                    }
                }
            })
        </script>
    </body>

</html>

6. keep-alive组件

用来缓存,避免重新渲染的。

示例:如下,如果不使用keep-alive,每次切换组件,那两个随机数都会重新生成,如果使用keep-alive组件,则可进行缓存,不重新创建。

<!doctype html>
<html>

    <head>
        <meta charset="utf-8">
        <title></title>
        <meta name="viewport" content="width=device-width,initial-scale=1,minimum-scale=1,maximum-scale=1,user-scalable=no" />
        <link href="../css/mui.min.css" rel="stylesheet" />
    </head>

    <body>
        <header class="mui-bar mui-bar-nav">
            <h1 class="mui-title">keep-alive</h1>
        </header>
        <div class="mui-content" id="content">
            <button @click="flag='my_test1'">显示my_test1组件</button>
            <button @click="flag='my_test2'">显示my_test2组件</button>

            <div>
                <!-- 使用keep-alive组件缓存非活动组件,可以保留状态,避免重新渲染,默认每次都会销毁非活动组件并重新创建 -->
                <keep-alive>
                    <component :is='flag'></component>
                </keep-alive>
            </div>
        </div>

        <script src="../js/vue.js"></script>
        <script src="../js/mui.min.js"></script>
        <script type="text/javascript">
            mui.init()
            var vm = new Vue({
                el: "#content",
                data: {
                    flag: 'my_test1'
                },
                components: {
                    'my_test1': {
                        name: 'tepmName', //指定组件的名称,默认为标签名,可以不展示
                        template: '<h4>我是test1组件{{x}}</h4>',
                        data() {
                            return {
                                x: Math.random()
                            }
                        }
                    },
                    'my_test2': {
                        template: '<h4>我是test2组件{{y}}</h4>',
                        data() {
                            return {
                                y: Math.random()
                            }
                        }
                    }
                }
            })
        </script>
    </body>

</html>

7.组件间的数据传递

7.1 父子组件

在一个组件内部定义另一个组件,称为父子组件。子组件只能在父组件中使用。
默认情况下,子组件无法访问父组件中的数据,每个组件实例的作用域是独立的

7.2 组件间数据传递(通信)

(1)子组件访问父组件中的数据

a)在调用子组件时,绑定想要获取的父组件的数据
b)在子组件内部,使用props选项声明获取的数据,即接收来自父组件的数据。
注:组件中的数据共有三种形式,data、props、computed

示例:

<!doctype html>
<html>

  <head>
      <meta charset="utf-8">
      <title></title>
      <meta name="viewport" content="width=device-width,initial-scale=1,minimum-scale=1,maximum-scale=1,user-scalable=no" />
      <link href="../css/mui.min.css" rel="stylesheet" />
  </head>

  <body>
      <div class="mui-content" id="content">
          <my_hello></my_hello>
      </div>
      <!-- <template>必须有且只有一个根元素 -->
      <template id="hello">
          <div>
              <h4>我是hello父组件</h4>
              <h4>访问自己的数据:{{msg}}、{{name}}、{{age}}、{{user.id}}</h4>
              
              <hr>
              <my_world :message="msg" :age="age" :user="user"></my_world>
          </div>
      </template>
      
      <template id="world">
          <div>
              <h5>我是world子组件</h5>
              <h5>访问父组件中的数据:{{message}},{{age}}、{{user.username}}</h5>
          </div>
      </template>
      <script src="../js/vue.js"></script>
      <script src="../js/mui.min.js"></script>
      <script type="text/javascript">
          mui.init()
          var vm = new Vue({ //根组件
              el: "#content",
              components: {
                  'my_hello': { //父组件
                      template: "#hello",
                      data() {
                          return {
                              msg: 'hello',
                              name: 'jack',
                              age: 23,
                              user: {
                                  id: 2014311951,
                                  username: 'yxc'
                              }
                          }
                      },
                      components: {
                          'my_world': { //子组件
                              template: '#world',
                              props:['message','age','user']//接收父组件传过来的数据
                          }
                      }
                  }
              }
          })
      </script>
  </body>

</html>

props
props 可以是数组或对象,用于接收来自父组件的数据。props 可以是简单的数组,或者使用对象作为替代,对象允许配置高级选项,如类型检测、自定义验证和设置默认值。

你可以基于对象的语法使用以下选项:

  • type: 可以是下列原生构造函数中的一种:String、Number、Boolean、Array、Object、Date、Function、Symbol、任何自定义构造函数、或上述内容组成的数组。会检查一个 prop 是否是给定的类型,否则抛出警告。Prop 类型的更多信息在此。
  • default: any
    为该 prop 指定一个默认值。如果该 prop 没有被传入,则换做用这个值。对象或数组的默认值必须从一个工厂函数返回。
  • required: Boolean
    定义该 prop 是否是必填项。在非生产环境中,如果这个值为 truthy 且该 + prop 没有被传入的,则一个控制台警告将会被抛出。
  • validator: Function
    自定义验证函数会将该 prop 的值作为唯一的参数代入。在非生产环境下,如果该函数返回一个 falsy 的值 (也就是验证失败),一个控制台警告将会被抛出。你可以在这里查阅更多 prop 验证的相关信息。
    示例:

// 简单语法

Vue.component('props-demo-simple', {
  props: ['size', 'myMessage']
})

// 对象语法,提供验证
Vue.component('props-demo-advanced', {
  props: {
    // 检测类型
    height: Number,
    // 检测类型 + 其他验证
    age: {
      type: Number,
      default: 0,
      required: true,
      validator: function (value) {
        return value >= 0
      }
    }
  }
})

示例:

<!doctype html>
<html>

    <head>
        <meta charset="utf-8">
        <title></title>
        <meta name="viewport" content="width=device-width,initial-scale=1,minimum-scale=1,maximum-scale=1,user-scalable=no" />
        <link href="../css/mui.min.css" rel="stylesheet" />
    </head>

    <body>
        <div class="mui-content" id="content">
            <my_hello></my_hello>
        </div>
        <!-- <template>必须有且只有一个根元素 -->
        <template id="hello">
            <div>
                <h4>我是hello父组件</h4>
                <h4>访问自己的数据:{{msg}}、{{name}}、{{age}}、{{user.id}}</h4>

                <hr>
                <my_world :message="msg" :age="age" :name="name" :user="user"></my_world>
            </div>
        </template>

        <template id="world">
            <div>
                <h5>我是world子组件</h5>
                <h5>访问父组件中的数据:{{message}},{{age}},{{name}},{{user.username}}</h5>
            </div>
        </template>
        <script src="../js/vue.js"></script>
        <script src="../js/mui.min.js"></script>
        <script type="text/javascript">
            mui.init()
            var vm = new Vue({ //根组件
                el: "#content",
                components: {
                    'my_hello': { //父组件
                        template: "#hello",
                        data() {
                            return {
                                msg: 'hello',
                                name: 'jack',
                                age: 23,
                                user: {
                                    id: 2014311951,
                                    username: 'yxc'
                                }
                            }
                        },
                        components: {
                            'my_world': { //子组件
                                template: '#world',
                                // props:['message','age','user']//接收父组件传过来的数据
                                props: { //也可以是对象,允许配置高级设置,如类型判断,数据校验,设置默认值
                                    message: String,
                                    age: {
                                        type: Number,
                                        default: 18,
                                        validator: function(value) {
                                            return value >= 0;
                                        }
                                    },
                                    name: {
                                        type: String,
                                        required: true,
                                    },
                                    user: {
                                        type: Object,
                                        default: function(){//对象或数组的默认值必须使用函数的属性来返回
                                            return {id: 2014311950,username: 'jack'};
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            })
        </script>
    </body>

</html>

总结:父组件通过props向下传递数据给子组件

(2)父组件访问子组件中的数据

a)在子组件中使用vm.$emit(事件名,数据)出发一个自定义事件,事件名自定义
b)父组件在使用子组件的地方监听子组件触发的事件,并在父组件中定义方法,用来获取数据

示例:

<!doctype html>
<html>

    <head>
        <meta charset="utf-8">
        <title></title>
        <meta name="viewport" content="width=device-width,initial-scale=1,minimum-scale=1,maximum-scale=1,user-scalable=no" />
        <link href="../css/mui.min.css" rel="stylesheet" />
    </head>

    <body>
        <div class="mui-content" id="content">
            <my_hello></my_hello>
        </div>
        <!-- <template>必须有且只有一个根元素 -->
        <template id="hello">
            <div>
                <h4>我是hello父组件</h4>
                <h4>访问自己的数据:{{msg}}、{{name}}、{{age}}、{{user.id}}</h4>
                <h4>访问子组件中的数据:{{h_sex}},{{h_height}}</h4>
                <hr>
                <my_world :message="msg" :age="age" :name="name" :user="user" @e-world="getData"></my_world>
            </div>
        </template>

        <template id="world">
            <div>
                <h5>我是world子组件</h5>
                <h5>访问父组件中的数据:{{message}},{{age}},{{name}},{{user.username}}</h5>

                <button @click="sendData()">将子组件中的数据向上发送到父组件</button>
            </div>
        </template>
        <script src="../js/vue.js"></script>
        <script src="../js/mui.min.js"></script>
        <script type="text/javascript">
            mui.init()
            var vm = new Vue({ //根组件
                el: "#content",
                components: {
                    'my_hello': { //父组件
                        template: "#hello",
                        methods: {
                            getData(sex, height) {
                                console.log(sex);
                                console.log(height);
                                this.h_sex = sex;
                                this.h_height = height;
                            }
                        },
                        data() {
                            return {
                                msg: 'hello',
                                name: 'jack',
                                age: 23,
                                user: {
                                    id: 2014311951,
                                    username: 'yxc'
                                },
                                h_sex: '',
                                h_height: ''
                            }
                        },
                        components: {
                            'my_world': { //子组件
                                data() {
                                    return {
                                        sex: 'male',
                                        height: 100
                                    }
                                },
                                template: '#world',
                                // props:['message','age','user']//接收父组件传过来的数据
                                props: { //也可以是对象,允许配置高级设置,如类型判断,数据校验,设置默认值
                                    message: String,
                                    age: {
                                        type: Number,
                                        default: 18,
                                        validator: function(value) {
                                            return value >= 0;
                                        }
                                    },
                                    name: {
                                        type: String,
                                        required: true,
                                    },
                                    user: {
                                        type: Object,
                                        default: function() { //对象或数组的默认值必须使用函数的属性来返回
                                            return {
                                                id: 2014311950,
                                                username: 'jack'
                                            };
                                        }
                                    }
                                },
                                methods: {
                                    sendData() {
                                        console.log(this); //这个this表示当前子组件实例
                                        this.$emit('e-world', this.sex, this.height); //触发一个自定义事件,发送数据
                                    }
                                }
                            }
                        }
                    }
                }
            })
        </script>
    </body>

</html>

总结:子组件通过events给父组件发送消息,实际上就是子组件把自己的数据发送到父组件。

8. 单向数据流

props是单向绑定的,当父组件的属性发生改变时,将传到给子组件,但是不会反过来。
且不允许子组件直接修改父组件中的数据,会报错。
示例:

<!doctype html>
<html>

    <head>
        <meta charset="utf-8">
        <title></title>
        <meta name="viewport" content="width=device-width,initial-scale=1,minimum-scale=1,maximum-scale=1,user-scalable=no" />
        <link href="../css/mui.min.css" rel="stylesheet" />
    </head>

    <body>
        <div id="content">
            <h2>父组件:{{name}}</h2>
            <!-- 父组件数据改变时子组件中的数据也会变 -->
            <input v-model="name" />
            
            <my-hello :name="name"></my-hello>
        </div>
        
        <template id="hello">
            <div>
                <h3>子组件{{name}}</h3>
                <button @click="change">修改数据</button>
            </div>
        </template>
        <script src="../js/mui.min.js"></script>
        <script src="../js/vue.js"></script>
        <script type="text/javascript">
            mui.init()
            var vm=new Vue({//父组件
                el:"#content",
                data:{
                    name:"hello"
                },
                components:{
                    'my-hello':{//子组件
                        data(){
                            return{
                            }
                        },
                        template:"#hello",
                        props:['name'],
                        methods:{
                            change:function(){//不允许子组件直接修改父组件中的数据,会报错
                                this.name="change hello"
                            }
                        }
                    }
                }
            })
        </script>
    </body>

</html>

解决方式

方式1:如果子组件想把它作为局部数据来使用,可以将数据存入另一个变量中再操作,不影响父组件中的数据。
示例:

<!doctype html>
<html>

    <head>
        <meta charset="utf-8">
        <title></title>
        <meta name="viewport" content="width=device-width,initial-scale=1,minimum-scale=1,maximum-scale=1,user-scalable=no" />
        <link href="../css/mui.min.css" rel="stylesheet" />
    </head>

    <body>
        <div id="content">
            <h2>父组件:{{name}}</h2>
            <!-- 父组件数据改变时子组件中的数据也会变 -->
            <input v-model="name" />
            
            <my-hello :name="name"></my-hello>
        </div>
        
        <template id="hello">
            <div>
                <h3>子组件{{userName}}</h3>
                <button @click="change">修改数据</button>
            </div>
        </template>
        <script src="../js/mui.min.js"></script>
        <script src="../js/vue.js"></script>
        <script type="text/javascript">
            mui.init()
            var vm=new Vue({//父组件
                el:"#content",
                data:{
                    name:"hello"
                },
                components:{
                    'my-hello':{//子组件
                        data(){
                            return{
                                userName:this.name//将父组件传过来的值赋到新变量userName中
                            }
                        },
                        template:"#hello",
                        props:['name'],
                        methods:{
                            change:function(){
                                // this.name="change hello"//不允许子组件直接修改父组件中的数据,会报错
                                this.userName="change hello"
                            }
                        }
                    }
                }
            })
        </script>
    </body>

</html>

方式2:如果子组件想修改数据并且同步更新到父组件,两个方法:

① 使用 .sync (1.0版本支持,2.0版本中不支持,2.3版本又开始支持)
需要显示的触发一个更新事件
示例:

<!doctype html>
<html>

   <head>
       <meta charset="utf-8">
       <title></title>
       <meta name="viewport" content="width=device-width,initial-scale=1,minimum-scale=1,maximum-scale=1,user-scalable=no" />
       <link href="../css/mui.min.css" rel="stylesheet" />
   </head>

   <body>
       <div id="content">
           <h2>父组件:{{name}}</h2>
           <input v-model="name" />
           
           <!-- 使用.sync -->
           <my-hello :name.sync="name"></my-hello>
       </div>
       
       <template id="hello">
           <div>
               <h3>子组件{{name}}</h3>
               <button @click="change">修改数据</button>
           </div>
       </template>
       <script src="../js/mui.min.js"></script>
       <script src="../js/vue.js"></script>
       <script type="text/javascript">
           mui.init()
           var vm=new Vue({//父组件
               el:"#content",
               data:{
                   name:"hello"
               },
               components:{
                   'my-hello':{//子组件
                       data(){
                           return{
                           }
                       },
                       template:"#hello",
                       props:['name'],
                       methods:{
                           change:function(){
                               this.$emit('update:name','change hello');//方式2:使用.sync 显示触发一个更新事件,父组件也会更新
                           }
                       }
                   }
               }
           })
       </script>
   </body>

</html>

② 可以将父组件中的数据包装成对象,然后在子组件中修改对象的属性(因为对象是引用类型,指向同一个内存空间),推荐使用。
示例:

<!doctype html>
<html>

    <head>
        <meta charset="utf-8">
        <title></title>
        <meta name="viewport" content="width=device-width,initial-scale=1,minimum-scale=1,maximum-scale=1,user-scalable=no" />
        <link href="../css/mui.min.css" rel="stylesheet" />
    </head>

    <body>
        <div id="content">
            <h2>父组件:{{name}}</h2>
            <input v-model="name" />
            <h2>父组件:{{user.age}}</h2>

            <!-- 使用.sync -->
            <my-hello :name.sync="name" :user="user"></my-hello>
        </div>

        <template id="hello">
            <div>
                <h3>子组件{{name}}</h3>
                <h2>子组件:{{user.age}}</h2>
                <button @click="change">修改数据</button>
            </div>
        </template>
        <script src="../js/mui.min.js"></script>
        <script src="../js/vue.js"></script>
        <script type="text/javascript">
            mui.init()
            var vm = new Vue({ //父组件
                el: "#content",
                data: {
                    name: "hello",
                    user: { //包装成一个对象,子组件修改属性时将改变,因为指向的是同一个内存空间
                        name: "chaoyoung",
                        age: 23
                    }
                },
                components: {
                    'my-hello': { //子组件
                        data() {
                            return {}
                        },
                        template: "#hello",
                        props: ['name', 'user'],
                        methods: {
                            change: function() {
                                // this.$emit('update:name','change hello');//方式2:使用.sync 显示触发一个更新事件,父组件也会更新
                                this.user.age = 18;
                            }
                        }
                    }
                }
            })
        </script>
    </body>

</html>

9.非父子组件间的通讯

非父子组件间通讯,可以通过一个空的Vue实例作为中央事件总线(事件中心),用它来触发事件和监听事件。
步骤:

1.创建空的Vue实例
var Event=new Vue();

2.触发事件
Event.$emit('事件名',数据);

3.监听事件
Event.$on('事件名',data=>{})

示例:

<!doctype html>
<html>

  <head>
      <meta charset="utf-8">
      <title></title>
      <meta name="viewport" content="width=device-width,initial-scale=1,minimum-scale=1,maximum-scale=1,user-scalable=no" />
      <link href="../css/mui.min.css" rel="stylesheet" />
  </head>

  <body>
      <div id="content">
          <my-a></my-a>
          <my-b></my-b>
          <my-c></my-c>
      </div>
      <template id="a">
          <div>
              <h3>A组件{{name}}</h3>
              <button @click="send">(A)将数据发送给C组件</button>
          </div>
      </template>
      <template id="b">
          <div>
              <h3>B组件{{age}}</h3>
              <button @click="send">(B)将数据发送给C组件</button>
          </div>
      </template>
      <template id="c">
          <div>
              <h3>C组件{{namec}},{{agec}}</h3>
          </div>
      </template>

      <script src="../js/vue.js"></script>
      <script src="../js/mui.min.js"></script>
      <script type="text/javascript">
          mui.init()

          //定义一个空的Vue实例
          var Event = new Vue();

          var A = {
              template: "#a",
              data() {
                  return {
                      name: 'yxc'
                  }
              },
              methods: {
                  send: function() {
                      //发送
                      Event.$emit('data-a', this.name);
                  }
              }
          }

          var B = {
              template: "#b",
              data() {
                  return {
                      age: 23
                  }
              },
              methods: {
                  send: function() {
                      //发送
                      Event.$emit('data-b', this.age);
                  }
              }
          }
          var C = {
              template: "#c",
              data() {
                  return {
                      namec: "",
                      agec: 0
                  }
              },
              mounted() { //在模板编译完成之后执行
                  //这里不能用普通函数function(name){},否则this是指全局实例Event,也就不能将值赋到C组件
                  // Event.$on('data-a',function(name){
                  //  console.log(name);
                  //  this.namec=name;
                  // })
                  
                  Event.$on('data-a', name => {//使用箭头函数
                      console.log(name);
                      this.namec = name;
                  })
                  Event.$on('data-b', age => {
                      console.log(age);
                      this.agec = age;
                  })
              }
          }

          var vm = new Vue({
              el: "#content",
              components: {
                  'my-a': A,
                  'my-b': B,
                  'my-c': C
              }
          })
      </script>
  </body>

</html>

10.slot内容分发

本意:位置,槽

示例:用来获取组件中的原内容,类似argular中的trasclude指令。

  • 单一slot
<!doctype html>
<html>

    <head>
        <meta charset="utf-8">
        <title></title>
        <meta name="viewport" content="width=device-width,initial-scale=1,minimum-scale=1,maximum-scale=1,user-scalable=no" />
        <link href="../css/mui.min.css" rel="stylesheet" />
    </head>

    <body>
        <div id="content">
            <my-hello>这是原内容,则显示此原内容</my-hello>
            
            <my-hello></my-hello>
        </div>
        <template id="hello">
            <div>
                <h3>hello组件内容</h3>
                <!-- 如果要获取原内容,用内置组件slot -->
                <slot>如果没有原内容,则显示此内容</slot>
            </div>
        </template>
        
        <script src="../js/vue.js"></script>
        <script src="../js/mui.min.js"></script>
        <script type="text/javascript">
            mui.init()
            var vm=new Vue({
                el:"#content",
                components:{
                    'my-hello':{
                        template:"#hello"
                    }
                }
            })
        </script>
    </body>

</html>

  • 具名slot

    就是给原内容加上slot标签,然后根据slot名称来展示。
<!doctype html>
<html>

    <head>
        <meta charset="utf-8">
        <title></title>
        <meta name="viewport" content="width=device-width,initial-scale=1,minimum-scale=1,maximum-scale=1,user-scalable=no" />
        <link href="../css/mui.min.css" rel="stylesheet" />
    </head>

    <body>
        <div id="content">
            <!-- <my-hello>这是原内容,则显示此原内容</my-hello> -->
            <!-- <my-hello></my-hello> -->
            <my-hello>
                <ul slot="test1">
                    <li>111</li>
                    <li>222</li>
                    <li>333</li>
                </ul>
                <ol slot="test2">
                    <li>aaa</li>
                    <li>bbb</li>
                    <li>ccc</li>
                </ol>
            </my-hello>
        </div>
        <template id="hello">
            <div>
                <slot name="test1"></slot>
                <h3>hello组件内容</h3>
                <slot name="test2"></slot>
                <!-- 如果要获取原内容,用内置组件slot -->
                <!-- <slot>如果没有原内容,则显示此内容</slot> -->
            </div>
        </template>
        
        <script src="../js/vue.js"></script>
        <script src="../js/mui.min.js"></script>
        <script type="text/javascript">
            mui.init()
            var vm=new Vue({
                el:"#content",
                components:{
                    'my-hello':{
                        template:"#hello"
                    }
                }
            })
        </script>
    </body>

</html>

原创不易,转载请注明出处。

发布了42 篇原创文章 · 获赞 64 · 访问量 4万+

猜你喜欢

转载自blog.csdn.net/xch_yang/article/details/102803500