本文为转载,原文:Vue学习笔记入门篇——组件的通信数组
组件意味着协同工做,一般父子组件会是这样的关系:组件 A 在它的模版中使用了组件 B。它们之间必然须要相互通讯:父组件要给子组件传递数据,子组件须要将它内部发生的事情告知给父组件。然而,在一个良好定义的接口中尽量将父子组件解耦是很重要的。这保证了每一个组件能够在相对隔离的环境中书写和理解,也大幅提升了组件的可维护性和可重用性。
在 Vue 中,父子组件的关系能够总结为 props down, events up。父组件经过 props 向下传递数据给子组件,子组件经过 events 给父组件发送消息。看看它们是怎么工做的。app
组件实例的做用域是孤立的。这意味着不能 (也不该该) 在子组件的模板内直接引用父组件的数据。要让子组件使用父组件的数据,咱们须要经过子组件的 props 选项。
子组件要显式地用 props 选项声明它期待得到的数据:函数
<div id="example"> <input v-model="parentMsg"><br> <child :my-message="parentMsg"></child> </div>
Vue.component('child', { props:['myMessage'], template:'<span>{{myMessage}}</span>' }) new Vue({ el:'#example', data:{ parentMsg:'' } })
注意:
HTML 特性是不区分大小写的。因此,当使用的不是字符串模版,camelCased (驼峰式) 命名的 prop 须要转换为相对应的 kebab-case (短横线隔开式) 命名学习
结果以下:
这样,每当父组件的数据变化时,该变化也会传导给子组件。ui
初学者常犯的一个错误是使用字面量语法传递数值:this
<!-- 传递了一个字符串 "1" --> <comp some-prop="1"></comp>
由于它是一个字面 prop,它的值是字符串 “1” 而不是 number。若是想传递一个实际的 number,须要使用 v-bind,从而让它的值被看成 JavaScript 表达式计算:spa
<!-- 传递实际的 number --> <comp v-bind:some-prop="1"></comp>
prop 是单向绑定的:当父组件的属性变化时,将传导给子组件,可是不会反过来。这是为了防止子组件无心修改了父组件的状态——这会让应用的数据流难以理解。
另外,每次父组件更新时,子组件的全部 prop 都会更新为最新值。这意味着你不该该在子组件内部改变 prop。若是你这么作了,Vue 会在控制台给出警告。
为何咱们会有修改 prop 中数据的冲动呢?一般是这两种缘由:
prop 做为初始值传入后,子组件想把它看成局部数据来用;
prop 做为初始值传入,由子组件处理成其它数据输出。
对这两种缘由,正确的应对方式是:code
props: ['initialCounter'], data: function () { return { counter: this.initialCounter } }
props: ['size'], computed: { normalizedSize: function () { return this.size.trim().toLowerCase() } }
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 能够是下面原生构造器:component
咱们知道,父组件是使用 props 传递数据给子组件,但若是子组件要把数据传递回去,应该怎样作?那就是自定义事件!orm
每一个 Vue 实例都实现了事件接口 (Events interface),即:
使用 $on(eventName) 监听事件
使用 $emit(eventName) 触发事件
请看下面的例子:
<div id="counter-event-example"> <p>{{total}}</p> <button-counter v-on:increment="incrementTotal"></button-counter> <button-counter v-on:increment="incrementTotal"></button-counter> </div>
Vue.component('button-counter',{ template:'<button v-on:click="increment">{{counter}}</button>', data:function () { return { counter : 0 } }, methods:{ increment:function () { this.counter += 1 this.$emit('increment') } } }) new Vue({ el:'#counter-event-example', data:{ total:0 }, methods:{ incrementTotal:function () { this.total += 1 } } })
运行结果以下
在本例中,子组件已经和它外部彻底解耦了。它所作的只是报告本身的内部事件,至于父组件是否关心则与它无关。留意到这一点很重要。
有时候,你可能想在某个组件的根元素上监听一个原生事件。可使用 .native 修饰 v-on。例如:
<my-component v-on:click.native="doTheThing"></my-component>
<div id="app"> <switchbtn :result="result" @on-result-change="onResultChange"></switchbtn> <input type="button" value="change" @click="change"> </div>
Vue.component('switchbtn',{ template:"<div @click='change'>{{myResult?'开':'关'}}</div>", props:['result'], data:function () { return { myResult:this.result } }, watch:{ result : function (val) { this.myResult = val; }, myResult:function (val) { this.$emit("on-result-change", val); } }, methods:{ change:function () { this.myResult = !this.myResult; } } }) var app = new Vue({ el:'#app', data:{ result:true }, methods:{ change:function () { this.result = !this.result; }, onResultChange:function (val) { this.result = val; } } })
本文为原创,转载请注明出处
上一节:Vue学习笔记入门篇——组件的使用
返回目录
下一节:Vue学习笔记入门篇——组件的内容分发(slot)