上面的组件在注册时,可以看到是全局组件,而全局组件的意思是可以在多个Vue实例下使用,但是,实际项目开发中,这样不是很方便,因此还有局部组件
全局组件的注册方法
Vue.component('组件名称',组件构造器名称)好处 所有的Vue实例都可以用 坏处容错率低,一般都需要在某个节点下使用
局部组件只能在当前Vue实例下使用 因此直接在创建的Vue的实例下注册
const app = new Vue({ el:"#app", data:{ }, components:{ //注意组件名称不能使用驼峰命名 'app-component':{ template:`<div>啊</div>`//内容必须被html元素包裹 }, //可以有data属性,但是里面必须是个函数 data:{ function(){ } } } })可以在的那个钱html标签上添加is属性+组件标签名称
Vue组件应该有自己保存自己数据的地方
所以,因为组件的内部的data是return的对象,因此这个data的对象可以被复用,这个组件就可以被复用,作为独立的组件运行相互不干扰
上面提到了,子组件是不能引用父组件或者Vue实例数据的 但是,在开发中,往往数据是需要从上层往下层传递的
将父组件传递进来的数据通过初始值保存起来 props的值可以通过组件data函数中的this.xxx直接获取 这样保存好的来自父组件的数据,就可以在不同组件中单独操作
这样,我子组件直接引用data函数返回的对象中的count就可以了嗷 <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>JS Bin</title> </head> <body> <div id="app"> <child-component a1='你好'></child-component> </div> <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script> <script> const app = new Vue({ el:"#app", data:{ }, components:{ 'child-component':{ template:`<div>{{count}}</div>`, props:['a1'], data(){ return{ count: this.a1 } } } } }) </script> </body> </html>另一种情况时props作为需要被转变的原始值传入,这种情况计算属性就可以 将父组件传递进来的数据,通过计算属性重新计算,返回值
小demo,根据父组件传进来的数字,决定子组件的宽度 <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>JS Bin</title> </head> <body> <div id="app"> <input type="text" v-model='width'> <child-component :a1='width'></child-component> </div> <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script> <script> const app = new Vue({ el:"#app", data:{ width:'0' }, components:{ 'child-component':{ template:`<div :style='style'>{{a1}}</div>`, props:['a1'], computed:{ style(){ return { width: this.a1 +'px', background: 'red', height: '100px' } } } } } }) </script> </body> </html>子组件使用$emit()触发事件 父组件用$on()监听事件
第一步 自定义事件第二步 在子组件使用$emit()触发事件,第一个参数是事件名,后面是要传递的数据第三步,在自定义事件中用一个参数接收 <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>JS Bin</title> </head> <body> <div id="app"> 点击数字发生变化:{{msg}} <child-component @change='handleMsg'></child-component> </div> <template id='aaa'> <button @click='add'>+</button> </template> <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script> <script> const app = new Vue({ el:'#app', methods:{ handleMsg(value){ this.msg=value//父组件事件方法中拿到子组件的值,并把值付给msg } }, data:{ msg:0 }, components:{ 'child-component':{ template:'#aaa', data(){ return { count: 0 } }, methods:{ add(){ this.count++//设置子组件点击事件的方法,点击按钮造成子组件的count++ this.$emit('change',this.count)//然后把子组件的count的值传递给父组件的自定义事件,第一个参数是自定义事件的名称,第二个参数是子组件要传递的值 } } } } }) </script> </body> </html>其实不需要使用自定义事件,直接绑定v-model,并$emit()触发input事件,效果是一样的
就是个语法糖因为v-model是双向绑定的,v-model本身绑定的是input事件,并且动态绑定value和data的值因此,原理就是将子组件的参数传给value,通过v-model,然后传给父组件的data.