Vue的父子组件
在组件树中,组件与组件存在层级关系,而其中一种非常重要的关系就是父子组件的关系。参考以下案例,做一个简单关系概要:
<div id = "app">
<h2>app</h2>
<cpn></cpn>
</div>
<script src = "../JS/vue.js"></script>
<script>
const cpn2 = Vue.extend({
template: `
<div>
<h2>这是一个子组件</h2>
</div>`
})
const cpn1 = Vue.extend({
template: `
<div>
<h2>这是一个父组件</h2>
<cpn2></cpn2>
</div>`,
components: {
'cpn2': cpn2
}
})
let app = new Vue({
el: "#app",
data:{
message: "hello",
},
components: {
'cpn': cpn1
}
});
</script>
父组件cpn1将子组件cpn2包裹在自身components对象中,而引用该父组件只需将父组件包裹在挂载vue实例的components对象中,换而言之,vue实例属于根组件,相当于所有对象的父组件。
需要注意的是,注册后的子组件子标签只能在父组件应用而不能在vue实例中使用,这是因为:1.因为当子组件注册到父组件的components时,vue会编译好父组件的模块;2.该模块的内容已经决定了父组件将要渲染的html(相当于父组件中已经有利子组件中的内容)3.子标签只能在父组件中被识别,而直接在vue实例中使用则会被浏览器忽视。
结果如下:
父子组件通信
在开发中,往往一些数据确实需要从上层传递到到下层,比如一个页面中,我们从服务器请求到了很多数据,其中一部分数据并非是我们整个页面的大组件来展示的,而是需要下面的子组件进行展示。这个时候,并不会让子组件再次发送一个网络请求,而是直接让大组件(父组件)将数据传递给小组件(子组件)。Vue官方提供了一种方式:(1)通过props向子组件传递数据(pass props);(2)通过事件向父组件发送消息($emit events)
prop的大小写(驼峰验证)
HTML 中的标签名是大小写不敏感的,所以浏览器会把所有大写字符解释为小写字符。这意味着当你使用 DOM 中的模板时,camelCase (驼峰命名法) 的 prop 名需要使用其等价的 kebab-case (短横线分隔命名) 命名(但如果使用字符串模板的话该限制不存在):
Vue.component('blog-post', {
// 在 JavaScript 中是 camelCase 的
props: ['postTitle'],
template: '<h3>{{ postTitle }}</h3>'
})
<!-- 在 HTML 中是 kebab-case 的 -->
<blog-post post-title="hello!"></blog-post>
pros基本用法
在组件中,使用选项props来声明需要从父级接收到的数据。props的值有两种方式:1.字符串数组,数组中的字符串就是传递时的名称;2.对象,对象可以设置传递时的类型,也可以设置默认值等。下面案例简单示范一个props传递:
<div id = "app">
<h2>app</h2>
<cpn :cmovies="movies" :cmessage="message"></cpn>
</div>
<template id="cpn">
<div>
<h2>{{cmovies}}</h2>
<h2>{{cmessage}}</h2>
</div>
</template>
<script src = "../JS/vue.js"></script>
<script>
const cpn = {
template: "#cpn",
props: ['cmovies','cmessage'],
}
let app = new Vue({
el: "#app",
data:{
message: "hello",
movies: ['111','222','333']
},
components: {
cpn
}
});
</script>
我们将vue实例作为父组件,自定义的组件为它的子组件,由于组件已完成注册故可在父组件内自由使用。我们在实例中的data定义了meesage与movies两项属性,子标签中通过v-bind指令将实例中对应的属性传递给props中相应属性,最后再由props中的数据渲染到模板中。结果如下:
props数据验证
在前面,props选项是使用一个数组,除此之外也可以使用一个对象。当需要对props进行类型等验证时,就需要对象写法了。验证支持的数据类型有:String, Number, Boolean, Array, Object, Date, Function, Symbol 以及自定义类型。以下为例:
const cpn = {
template: "#cpn",
props: {
cmovies: {
type: Array,
default() {
return [];
}
},
cmessage: {
type: Number,
default: 111
}
},
}
let app = new Vue({
el: "#app",
data:{
message: [123],
movies: [111,222,333]
},
components: {
cpn
}
});
通过我们的校验规则,cmessage需要传入的类型必须指定为数字,但我们在检查页面时它依然会把父组件中不符要求的信息渲染到页面中,只有当你检查当前页面的控制台才会发现类型错误。注意那些 prop 会在一个组件实例创建之前进行验证,所以我们创造的组件中的 property (如 data
、computed
等) 在 default
或 validator
函数中是不可用的。所以对于格式错误的数据我们尽可能在父组件中处理完毕后再转交,或者进行表单验证,自定义验证规则。
当类型指定为对象或数组时,默认值必须从一个工厂函数中获得。