<五>子父组件间的交互
组件(Component)是 Vue.js 最强大的功能之一,组件可以扩展 HTML 元素,封装可重用的代码。
1、基本定义和使用
<body> <div id="app"> <child></child> <child1></child1> </div> <script src="vue.js"></script> <script> // 全局注册 Vue.component('child', { template: '<h1>自定义组件!</h1>' }) var ChildTemplate = { template: '<h1>自定义组件!</h1>' } var app = new Vue({ el: '#app' , components: { // <child1> 将只在父模板可用,局部注册 'child1': ChildTemplate } }); </script>
2、父组件向子组件交互,props 单向传递
<body> <div id="app"> <div> <input v-model="parentMsg"> <br> <child v-bind:message="parentMsg"></child> </div> </div> <script src="vue.js"></script> <script> // 全局注册 Vue.component('child', { props:['message'], template: '<h1>{{message}}</h1>' }) var app = new Vue({ el: '#app', data:{ parentMsg:'' } }); </script>
3、props验证,如上面例子,如果message只接收数值型用于计算,但是该值是用户输入,这时候用户可以随便输入,但是字符型数据并不是我们想要的。
因此传入的参数可能会在开发子组件的人的意料之外,程序就会发生错误,在函数调用之前先检查一下函数一样,props可以进行一个预先检查。
<body> <div id="app"> <div> <input v-model="parentMsg"> <br> <child v-bind:message="parentMsg"></child> </div> </div> <script src="vue.js"></script> <script> // 全局注册 Vue.component('child', { props:{ message:Number //只能传入数值型 }, template: '<h1>{{message}}</h1>' }) var app = new Vue({ el: '#app', data:{ parentMsg:0 } }); </script>
结果:当没有对输入框的输入值限定为数值型时,看结果
vue会自动给出一个warn提示,只是个警告,没有强制报错。这个警告不知道怎么捕捉(噗)
给输入框输入一个限定类型,
<input v-model.Number="parentMsg">
这样就可以自动将输入值过滤字符并将输入值自动转换成数字型,这样就不会出现这个警告了。
props验证有多种类型。
当允许多种类型时,比如允许输入string和number类型时props的定义
props:{ message:[Number,String] //只能传入数值型 },
所有的验证如下:
props: { // 基础类型检测 (`null` 意思是任何类型都可以) A: Number, // 多种类型 B: [String, Number], // 必传且是字符串 C: { type: String, required: true }, // 数字,有默认值 D: { type: Number, default: 100 }, // 数组/对象的默认值应当由一个工厂函数返回 E: { type: Object, default: function () { return { message: 'hello' } } }, // 自定义验证函数 F: { validator: function (value) { return value > 10 } } }
4、上面是父组件向子组件传递数据,那如果子组件向父组件传递数据呢?
- 使用 $on(eventName) 监听事件
- 使用 $emit(eventName) 触发事件
父组件可以在使用子组件的地方直接用 v-on 来监听子组件触发的事件。
<body> <div id="app"> <p>{{ total }}</p> <child v-on:increment="incrementTotal"></child> </div> <script src="vue.js"></script> <script> // 全局注册 Vue.component('child', { template: '<button v-on:click="changeName">{{ counter }}</button>', data:function () { return { counter: 0 } }, methods: { changeName: function () { this.counter += 1 this.$emit('increment') } }, }) var app = new Vue({ el: '#app', data:{ total: 0 } , methods: { incrementTotal: function () { this.total += 1 } } }); </script>
如代码所示,将一个方法绑定一个别名传递给子组件,然后子组件使用
this.$emit('increment')
触发这个参数就行了。