VueJS(七)

    技术2022-07-12  82

    今天继续学习组件通信

    昨天学到父组件在子组件的自定义标签上使用v-on来监听子组件触发的自定义事件

    <body> <div id="app"> <p>总数:{{total}}</p> <my-component @increase="handleGetTotal" @reduce="handleGetTotal"></my-component> </div> <script> Vue.component('my-component',{ template:'\ <div>\ <button @click="handleIncrease">+1</button>\ <button @click="handleReduce">-1</button>\ </div>', data:function(){ return { counter:0 } }, methods:{ handleIncrease:function(){ this.counter++; this.$emit('increase',this.counter); }, handleReduce:function(){ this.counter--; this.$emit('reduce',this.counter); }, } }); var app =new Vue({ el:'#app', data:{ total:0 }, methods:{ handleGetTotal:function(total){ this.total = total; }, } }) </script> </body>

    子组件一共两个按钮,分别实现加一减一的功能,在改变组件data中的counter后,通过$emit()再把它传递给父组件,父组件使用两个v-on绑定(v-on:可以简写成@),$emit()的第一个参数是自定义事件的名字,后面的都是需要传递的参数,可以多写或者不写。 这个就是子组件向父组件传递数据的过程!!!

    v-on在珠江上除了有监听自定义事件的功能外,还可以监听DOM时间,用上.native的修饰符表示监听的是一个原生事件(???不知道)

    <my-qian v-on:click.native="handleClick"></my-qian>

    使用v-model 自定义组件上可以使用v-model指令

    <script> Vue.component('my-component',{ template:'<button @click="handleClick">+1</button>', data:function(){ return{ counter:0 } }, methods:{ handleClick:function(){ this.counter++; this.$emit('input',this.counter); } } }); var app = new Vue({ el:'#app', data:{ total:0 } }) </script> </body>

    就标签本来是通过绑定函数,函数再传值,使用v-model的时候就是直接绑定了数据

    v-model还可以用来创建自定义的表单输入组件

    <body> <div id="app"> <p>{{total}}</p> <my-component v-model="total"></my-component> <button @click = "handleReduce">-1</button> </div> <script> Vue.component('my-component',{ props:['value'], template:'<input :value="value" @input="updateValue">', methods:{ updateValue:function(event){ this.$emit('input',event.target.value); } } }); var app = new Vue({ el:'#app', data:{ total:0 }, methods:{ handleReduce:function(){ this.total--; } } }) </script> </body>

    非父子组件通信 一般指的是兄弟组件和跨多级组件

    vue它所使用的方式是找一个空的vue实例作为中央事件总线 也就是所谓的中介

    <body> <div id="app"> {{message}} <component-a></component-a> </div> <script> var bus = new Vue(); Vue.component('component-a',{ template:'<button @click="handleEvent">传递时间</button>', methods:{ handleEvent:function(){ bus.$emit('on-message','来自组件component-a的内容'); } } }); var app = new Vue({ el:'#app', data:{ message:'' }, mounted:function(){ var _this = this; bus.$on('on-message',function(msg){ _this.message = msg; }); } }) </script> </body>

    首先,他这里是创建了一个空的vue实例,bus,定义了一个组件comonent-a,还有一个vue实例app 在实例app注册的内容中监听了来自bus的一个事件on-message,在组件中点击按钮会通过bus把事件on-message发出去,此时app就会收到来自bus的事件

    简单概括流程就是这个组件是注册了一个按钮,按钮点击的函数handleEvent内容是bus,然后注册的实例app是在监听这个bus的事件的,一旦点击将函数的参数赋值给message,这样一来就做到了组件和一个vue实例之间的数据通信,实质上他们是通过bus交流的,bus获得了组件的数据,vue实例又通过bus获得数据,属实绕

    除了使用中央事件总线bus这个手段外,还有两种方法:

    父链 在子组件中,使用this.$parent可以直接访问该组件的父实例或组件,父组件也可以使用this.$children来访问他所有的子组件,而且可以递归向上或向下无限访问,直至根实例或最内层的组件

    <body> <div id="app"> {{message}} <component-a></component-a> </div> <script> Vue.component('component-a',{ template:'<button @click="handleEvent">通过父链直接修改数据</button>', methods:{ handleEvent:function(){ this.$parent.message='xxxxxxxxxx'; } } }); var app = new Vue({ el:'#app', data:{ message:'' } }) </script> </body>

    就直接访问父的数据,但是书上说这样容易提高耦合度,应该避免 推荐使用props和$emit来通信

    然后是子组件索引

    <body> <div id="app"> <button @click="handleRef">通过ref获取子组件实例</button> <component-a ref="comA"></component-a> </div> <script> Vue.component('component-a',{ template:'<div>子组件</div>', data:function(){ return { message:'子组件内容' } } }); var app =new Vue({ el:'#app', methods:{ handleRef:function(){ var msg = this.$refs.comA.message; console.log(msg); } } }) </script> </body>

    就是通过一个索引一样的形式,

    var msg = this.$refs.comA.message;

    获得组件中message的数据值

    使用slot分发内容 混合使用父组件内容和子组件模板的时候,会使用到slot

    props传递数据、events触发事件、slot内容分发构成了Vue组件的3个API来源

    作用域的概念 编译的作用域

    <child-component> {{message}} </child-component>

    这里的message就是一个shot?,他绑定的是父组件的数据而不是组件<child-component>的数据 父组件模板的内容实在父组件的作用域内编译,子组件模板的内容实在子组件作用域内编译? 这好像说的废话

    <body> <div id="app"> <my-qian v-show="showqian"></my-qian> </div> <script> Vue.component('my-qian',{ template:'<div>子组件</div>' }); var app = new Vue({ el:'#app', data:{ showqian:true } }) </script> </body>
    Processed: 0.012, SQL: 9