使用组件的原因
提高代码的复用性
组件的使用方法
- 全局注册
Vue.component('my-component',{
template:'我是组件的内容'
})
占内存
- 局部注册
var app = new Vue({
el: '#app',
data: {
},
components: {
'app-component': {
template: 'app-component'
}
}
})
- 由于HTML标签的限制,如
table
中只能有tr
、td
、tbody
,要想在table
中使用组件就要用到is
,这样一来,tbody
在文档中就会被组件替换掉
我们也可以利用这个属性来干掉其他事,比如动态组件,也就是点一个按钮就切换一个组件
组件使用的奇淫巧技
- 必须用连字符命名,如:my-compoent
- template中的内容必须要用DOM元素包裹
// 正确写法
template: 'app-component'
// 错误写法
template: 'app-component'
- 组件的定义中,还可以有data,methods,computed
- data必须是一个方法
components: {
'plus-component': {
template: '',
data: function () {
return {
count111: 1
}
}
}
}
使用props传递数据 父亲向儿子传递数据
- 在子组件上声明属性msg,然后在子组件处用props来接收
我是爸爸
- 动态向子组件传入信息,则用v-model
我是爸爸
- ==在props中定义的属性都可以在组件内使用,可以在template、computed、methods中使用==
单向数据流
只能父组件向子组件传递信息,子组件不能向父组件传递信息
在组件中使用从props传来的数据可以直接用this.xxx来获取
'child-component': {
props: ['msg'],
template: '{{count}}',
data:function(){
// 组件中的data要返回一个函数
return {
count: this.msg
}
}
}
- 用v-bind来绑定style属性的时候可以使用对象语法,注意
computed:{
xxx: function () {
return {
//这是用到了v-bind绑定style的对象语法
width: this.ccc + 'px',
'background-color': 'red',
height: 10 + 'px'
}
}
}
数据验证
在HTML中绝对不允许使用驼峰,因为HTML会把大写全部转化为小写。在props中可以用驼峰或短横线,在template和data、this.xxx中只能使用驼峰,这是因为在vue中短横线会被误认为减号,会报错。
==总结:在HTML中使用短横线,在vue中使用驼峰==
- 对传入的数据进行数据验证
注意props不能再返回一个数组,而是一个对象
组件之间的通信
子组件给父组件传递信息
实现一个功能,点击子组件的按钮,改变父组件的数据
我的账户余额为:{{count}}
子组件向父组件传递信息的步骤:
- 在父组件里写入自定义事件名,事件名后面跟着的是要执行的方法
- 子组件通过$emit向父组件传递信息,第一个参数是自定义的事件名,后面是要传递的参数,可以接无限个
在组件中使用v-model
v-model其实也是一个语法糖:
- 它等于先用v-bind绑定一个值
- 监听v-on了一个input事件
上述代码又可以简化成
我的账户余额为:{{total}}
非父组件之间的通信
非父组件之间的通信需要一个bus作为中介
在父组件的data内新建一个bus: new Vue()
对象。
然后在A组件内用this.$parent.bus.$emit('事件名',参数)
Vue.component('a-component',{
template: `
`,
data:function () {
return {
text: '我是A组件'
}
},
watch:{
//watch的用法,key代表要监听的数据,后面接操作
text: function () {
this.$root.bus.$emit('xxx',this.text)
}
}
})
在B组件内,在对应的钩子事件中用this.$parent.bus.$on('事件名',参数)
Vue.component('b-component',{
template: '我是b组件---{{textb}}',
data:function () {
return {
textb: 'bbbbb'
}
},
created: function () {
var _this = this
this.$root.bus.$on('xxx',function (value) {
// alert('created')
_this.textb = value
})
}
})
- 修改父组件的数据,父链
this.$parent.xxxx
- 修改儿子组件的数据,子链
在每个儿子组件上加上ref属性
然后在父组件上使用:
this.$refs.a.count = 'aaa' // 修改a组件的数据
使用slot分发内容
编译的作用域
{{message}}
message属于父组件的作用域
父组件模板内的内容在父组件内编译
子组件模板内的内容在子组件内编译
slot(插槽)的用法和作用
在下面这段代码中
{{message}}
message其实是渲染不出来的,尽管message的作用域在父组件,但我们想让它子组件内的template中渲染出来,这时我们就要使用到了slot功能。
slot的作用是混合父组件的内容和子组件的模板,从而弥补视图的不足
hello world
......
Vue.component('child-component',{
template: `
如果父组件没有内容,我就是子组件的默认内容
具名插槽
在要插入数据的标签使用slot属性,在子组件的template处使用slot标签,并且写上对应的name
我是标题
hello world
... ...
Vue.component('child-component',{
template: `
这里是header的默认内容
如果父组件没有内容,我就是子组件的默认内容
`,
作用域插槽
作用域插槽是一个特殊的插槽,可以从子组件的插槽中获取数据。使用一个可以复用的模板来替换已经渲染的元素
用法:先在子组件的slot标签上name属性和自定义的属性
Vue.component('child-component',{
template: `
这里是header的默认内容
`,
然后在父组件上,用slot对应其中的name,用slot-scope对应的自定义名字来获取从子组件传来的数据
{{props.text}}
现在已经可以不用template,可以直接使用标签如
在子组件中访问自己的slot
通过this.$slots.(NAME)
来访问
我是父组件的内容
Vue.component('child-component',{
template: `
这里是header的默认内容
`,
data:function () {
return {
message: '我是子组件的内容',
bool: true
}
},
mounted:function () {
var header = this.$slots.header
console.log(header)
console.log(header[0].elm.innerText)
}
})
组件的高级用法-动态组件
所谓的动态组件就是通过is属性来动态切换组件