1.组件机制
组件 (Component) 是 Vue.js 最强大的功能之一。组件可以扩展HTML元素,封装可重用的代码。在较高层面上,组件是自定义元素,Vue的编译器为它添加特殊功能。在有些情况下,组件也可以表现为用is特性进行了扩展的原生 HTML 元素。组件注册的时候需要为该组件指定各种参数。
因为组件是可复用的 Vue 实例,所以它们与 new Vue 接收相同的选项,例如 data、computed、watch、methods 以及生命周期钩子等。仅有的例外是像 el 这样根实例特有的选项。
组件的特点
组件可以进行任意次数的复用。
组件的data必须是一个函数,确保每个实例可以维护一份被返回对象的独立的拷贝,也就是任何一个组件的改变不会影响到其他组件。
javascript
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 的无谓的增加。局部注册的组件只能在当前组件中使用
全局组件-->全局变量
局部组件-->局部变量
全局注册
javascript
// 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>
javascript
// 创建组件
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.父组件传递数据给子组件 (可以传递静态属性 动态属性 )
<my-com title='' :msg='msg' attr-a=''>
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>
javascript
// 创建组件
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>
javascript
<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 } })
javascript
// 创建组件
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>
javascript
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' 观察子组件的变化