1.组件机制
组件 (Component) 是 Vue.js 最强大的功能之一。组件可以扩展HTML元素,封装可重用的代码。在较高层面上,组件是自定义元素,Vue的编译器为它添加特殊功能。在有些情况下,组件也可以表现为用is特性进行了扩展的原生 HTML 元素。组件注册的时候需要为该组件指定各种参数。
因为组件是可复用的 Vue 实例,所以它们与 new Vue 接收相同的选项,例如 data、computed、watch、methods 以及生命周期钩子等。仅有的例外是像 el 这样根实例特有的选项。
### 组件的特点 * 组件可以进行任意次数的复用。 * 组件的data必须是一个函数,确保每个实例可以维护一份被返回对象的独立的拷贝,也就是任何一个组件的改变不会影响到其他组件。 let component = { data () { return { count: 0 } }, template: '<button v-on:click="count++">You clicked me {{ count }} times.</button>' } 一个组件的 data 选项必须是一个函数,因此每个实例可以维护一份被返回对象的独立的拷贝
2.组件注册
要想进行组件使用得先进行组件注册
- 全局注册
- 可以使用Vue.component(tagName, options) 注册一个全局组件, 注册之后可以用在任何新创建的 Vue 根实例的模板中
Vue.component(‘my-component-name’,component) - 局部注册
全局注册往往是不够理想的。比如,如果你使用一个像 webpack 这样的构建系统,全局注册所有的组件意味着即便你已经不再使用一个组件了,它仍然会被包含在你最终的构建结果中。这造成了用户下载的 JavaScript 的无谓的增加。局部注册的组件只能在当前组件中使用
全局组件–>全局变量
局部组件–>局部变量
全局注册 ### js代码 // 1.创建组件 let mycom = { data() { return { Commsg: '组件数据' } }, methods:{ changeObj(){ if(this.Commsg==='组件数据'){ this.Commsg='修改后的组件数据' }else{ this.Commsg='组件数据' } } }, // 模板 template: ` <div> <br> 组件使用 <br> ------------------------- <br> <span>{{Commsg}}</span> <span>{{Commsg}}</span> <button @click='changeObj'>更改数据模型中的数据</button> </div> ` }; // 全局注册 Vue.component('my-com',mycom) new Vue({ el: '#app', data: { } }) ### html代码 <div id="app"> <my-com></my-com> <my-com></my-com> <my-com></my-com> </div>
### 局部注册 ### html代码 <div id="app"> <my-com-b></my-com-b> -------------------- <my-com-a></my-com-a> </div> ### js代码 // 创建组件 let myComA={ // 模板 template:` <div>A组件</div> ` }; let myComB={ components:{ 'my-com-a':myComA }, // 模板 template:` <div>B组件 <my-com-a></my-com-a> </div> ` }; //全局注册 // Vue.component('my-com-a',myComA) Vue.component('my-com-b',myComB) new Vue({ components:{ 'my-com-a':myComA }, el:'#app', data:{ } })
3.组件交互/通信/传值
组件 A 在它的模板中使用了组件 B。它们之间必然需要相互通信:父组件可能要给子组件下发数据,子组件则可能要将它内部发生的事情告知父组件。在 Vue 中,父子组件的关系可以总结为 prop 向下传递,事件向上传递。父组件通过 prop 给子组件下发数据,子组件通过事件给父组件发送消息。
1.子组件内使用父组件数据 父-子
1.父组件传递数据给子组件 (可以传递静态属性 动态属性 )
2.子组件接收并处理数据
{
props:[‘title’,‘msg’,'attrA],
template:``
}
2.父组件内使用子组件的数据
事件发射 自定义事件
在子组件内发射 在父组件内接受
子组件发射时机
1.手动按钮发送
2.监听子组件内数据变化,然后发射
在子组件内监听comMsg的变化,this.$emit('',this.comMsg)
父组件的事件处理程序调用,可以更改父组件数据模型中的数据,同步反映到父组件视图中
### 父组件传递数据给子组件 ### html代码 <div id="app"> <!-- 父组件给子组件传递数据 --> <my-com :msg='msg' title='父组件向子组件传值' attr-a='父组件给自组件的静态数据'></my-com> </div> ### js代码 // 创建组件 let myCom={ // 接受父组件传递的数据 props:['title','msg','attrA'], data(){ return { } }, template:` <div>组件通信 <br> <span>{{msg}}--{{title}}--{{attrA}}</span> </div> ` } new Vue({ components:{ "my-com":myCom }, el:"#app", data:{ msg:'我是父组件' } })
### 子组件向父组件传递数据 ### html代码 <div id="app"> {{msg}} <my-a title='父组件静态数据' :msg='msg' data-attr='父组件静态数据' @my-event='handler'> </my-a> </div> </div> ### js代码 <script> // 创建组件 let myA={ props:['title','msg','dataAttr'], data(){ return { subMsg:'子组件数据' } }, methods:{ toSend(){ // 参数 第一个参数自定义事件名称 第二个参数传递的数据 this.$emit('my-event',this.subMsg,100) } }, template:` <div> {{subMsg}}-- {{msg}}-- {{dataAttr}}-- <button @click='toSend'>发射数据</button> </div> }; // 全局注册 Vue.component('my-a',myA) new Vue({ el:"#app", data:{ msg:'父组件数据' }, methods: { handler(a,b){ console.log(a,b) } }, })
4.组件传值
父组件通过属性绑定的方式将参数传递给子组件,子组件通过props声明期望从父组件那里获取的参数。camelCase (驼峰命名法) 的 prop 名需要使用其等价的 kebab-case (短横线分隔命名) 命名:
希望每个prop都有指定的值类型。这时,你可以以对象形式列出prop,这些property的名称和值分别是prop各自的名称和类型
父组件给子组件数据的时候,子组件可以定义数据类型
静态传参:不加冒号,传字符串
动态传参:加冒号,传number、boolean、object、数组类型的值,变量
props: {
title: String,
likes: Number,
isPublished: Boolean,
commentIds: Array,
author: Object,
callback: Function,
contactsPromise: Promise // or any other constructor
}
prop验证
我们可以为组件的 prop 指定验证要求,例如你知道的这些类型。如果有一个需求没有被满足,则 Vue 会在浏览器控制台中警告你。这在开发一个会被别人用到的组件时尤其有帮助。
Vue.component(‘my-component’, {
props: {
// 基础的类型检查 (null
和 undefined
会通过任何类型验证)
propA: Number,
// 多个可能的类型
propB: [String, Number],
// 必填的字符串
propC: { type: String, required: true },
// 带有默认值的数字
propD: { type: Number, default: 100 }
})
### js代码 // 创建组件 let myA={ props:['title','msg'], data(){ return { subMsg:'子组件' } }, template:` <div> {{title}}-{{msg}} </div> ` } Vue.component( 'my-a',myA ) new Vue({ el:'#app', data:{ msg:'父组件' } }) ### html代码 <div id="app"> {{msg}} <my-a title='hello' :msg='msg' ></my-a> </div>
### html代码 <div id="app"> {{msg}} <!-- <my-a sub-msg="父给子" :stus="[1,2,3]" :is-active="undefined"></my-a> --> <!-- <my-a sub-msg="父给子" :stus="[1,2,3]" :is-active="true"></my-a> --> <my-a :msg="msg" sub-msg="父给子" :is-active="true" :age="80"></my-a> </div> ### js代码 let myA = { props: { msg: String, subMsg: String, // stus: Array, stus: { type: Array, // 错误 // default: [6, 7, 8] // 正确 Object/Array要一个工厂函数返回默认值 default() { return [6, 7, 8]; } }, // isActive: Boolean isActive: [String, Boolean], name: { type: String, // 必填项 // required: true default: "lisi" }, // 自定义校验规则 age: { type: Number, // 校验器 // value 是形参,实参是将来父组件给子组件传递的数据 validator(value) { /* if(value>50){ return true; }else{ return false; } */ return value > 50; } } }, template: ` <div> {{subMsg}} {{stus}} {{isActive}} {{name}} {{age}} {{msg}} </div> ` }; Vue.component('my-a', myA); let vm = new Vue({ el: '#app', data: { msg: 'hello' }, methods: {} })
单向数据流(数据更改的方向)
父组件可以改给子组件的数据
父改子可以
子组件不可以改父组件的数据
子改父不行
修改父组件的msg 子组件的msg跟着修改但是反过来不行
vm.msg=‘hello vue’ 观察子组件的变化