// 自定义Person构造器 function Person(name, age) { this.name = name this.age = age } Vue.component('my-component', { template: `<div>名字: {{ person-prop.name }}, 年龄: {{ person-prop.age }} </div>`, props: { person-prop: { type: Person // 指定类型 } } }) new Vue({ el: '#app2', data: { person: 2 // 传入Number类型会报错 } })
非Prop类型的属性也可以像在html标签中添加data-开头的自定义属性一样,给自定义组件添加任意的属性。而不仅限于data-*形式,这样做的话,Vue会把这个属性放在自定义组件的根元素上。一个自定义组件的模板只能有一个根元素。
覆盖非Prop属性如果父组件向子组件的非prop属性传递了值,那么这个值会覆盖子组件模板中的特性。
<div> <my-component2 att="helloParent"></my-component2> </div> <script> Vue.component('my-component2', { template: `<div att="helloChild">子组件原有的特性被覆盖了</div>` }) new Vue({ el: '#app3' }) </script>
上面渲染的结果是,div的att属性是helloParent。
注意:前面已经提到过,覆盖原则对于class和style不适用,而是采用了合并(merge)的原则。
<div> <my-component2 att="helloParent"></my-component2> </div> <script> Vue.component('my-component2', { template: `<div att="helloChild">子组件原有的特性被覆盖了</div>` }) new Vue({ el: '#app3' }) </script>
上面的渲染结果是,div的类名是class1 class2,行内样式是color:red; background:yellow;。
自定义事件通过prop属性,父组件可以向子组件传递数据,而子组件的自定义事件就是用来将内部的数据报告给父组件的。
<div> <my-component2 v-on:myclick="onClick"></my-component2> </div> <script> Vue.component('my-component2', { template: `<div> <button type="button" @click="childClick">点击我触发自定义事件</button> </div>`, methods: { childClick () { this.$emit('myclick', '这是我暴露出去的数据', '这是我暴露出去的数据2') } } }) new Vue({ el: '#app3', methods: { onClick () { console.log(arguments) } } }) </script>
如上所示,共分为以下步骤:
子组件在自己的方法中将自定义事件以及需要发出的数据通过以下代码发送出去
this.$emit('myclick', '这是我暴露出去的数据', '这是我暴露出去的数据2')
第一个参数是自定义事件的名字
后面的参数是依次想要发送出去的数据
父组件利用v-on为事件绑定处理器
<my-component2 v-on:myclick="onClick"></my-component2>
这样,在Vue实例的methods方法中就可以调用传进来的参数了
注意: 在使用v-on绑定事件处理方法时,不应该传进任何参数,而是直接写v-on:myclick="onClick",不然,子组件暴露出来的数据就无法获取到了
绑定原生事件如果想在某个组件的根元素上监听一个原生事件。可以使用 .native 修饰 v-on
<my-component v-on:click.native="doTheThing"></my-component>
探究v-modelv-model可以对表单控件实现数据的双向绑定,它的原理就是利用了绑定属性和事件来实现的。比如input控件。不使用v-model,可以这样实现数据的双向绑定:
<div> <input type="text" v-bind:value="text" v-on:input="changeValue($event.target.value)"> {{text}} </div> <script> new Vue({ el: '#app4', data: { text: '444' }, methods: { changeValue (value) { this.text = value } } }) </script>
上面的代码同样实现了数据的双向绑定。其本质就是:
把input的value特性绑定到Vue实例的属性text上,text改变,input中的内容也会改变
然后把表单的input事件处理函数设置为Vue实例的一个方法,这个方法会根据输入参数改变Vue中text`的值
相应的,在input中输入内容时,触发了input事件,把event.target.value传给这个方法,最后就实现了改变绑定的数据的效果。
而v-model就是上面这种方式的语法糖,也就是把上面的写法封装了一下,方便我们使用。
理解了v-model的内幕,也就可以把这个效果用在自定义表单组件上了。
来实现一个简单的只能输入hello的表单输入组件。