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: BooleanisActive: [String, Boolean],name: {type: String,// 必填项// required: truedefault: "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’ 观察子组件的变化