Vue组件的使用方法
Vue组件化思想
组件化是Vue中的重要思想
- 他提供了一种抽象,让我们可以开发出一个个可复用的小组件来构造我们的应用
- 任何应用都会被抽象成一颗组件树
组件化思想的应用
- 尽可能的将页面拆分成一个个可复用的小组件
- 方便代码管理,可复用性强
注册组件的基本步骤
组件使用分为三个步骤
- 1.调用Vue.extend创建构造器
传入template代表我们自定义组件的模板,该模板就是使用到组件的地方,要显示的html代码 - 2.Vue.component() 注册组件(全局注册和局部注册)
调用Vue.component()是将刚才的构造器注册成一个组件,并给他取一个组件的标签名称
需要两个参数,:1.注册组件的名称 2. 被注册的构造器的名称 - 使用组件
组件必须被挂载在某个Vue实例下,否则他不会生效
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script>
//创建组件构造器
const cpnC = Vue.extend({
template:`<div>啊</div>`
})
//注册组件(全局组件,意味着可以在多个vue实例中使用)
Vue.component('cpn',cpnC)
const app = new Vue({
el:"#app",
data:{
}
})
</script>
vue的全局组件和局部组件
上面的组件在注册时,可以看到是全局组件,而全局组件的意思是可以在多个Vue实例下使用,但是,实际项目开发中,这样不是很方便,因此还有局部组件
全局组件
全局组件的注册方法
Vue.component('组件名称',组件构造器名称)
好处 所有的Vue实例都可以用
坏处容错率低,一般都需要在某个节点下使用
局部组件
局部组件只能在当前Vue实例下使用
因此直接在创建的Vue的实例下注册
const app = new Vue({
el:"#app",
data:{
},
components:{
//注意组件名称不能使用驼峰命名
'app-component':{
template:`<div>啊</div>`//内容必须被html元素包裹
},
//可以有data属性,但是里面必须是个函数
data:{
function(){
}
}
}
})
当某些html标签不能放入我们的自定义组件时
可以在的那个钱html标签上添加is属性+组件标签名称
组件内部是不能访问Vue实例数据的
Vue组件应该有自己保存自己数据的地方
那么组件内部的数据放在哪里呢?
- 就像Vue实例一样,组件内部也有个data属性
- 但是这个data属性必须是一个函数
- 而且这个函数返回一个对象,对象内部保存数据
const app = new Vue({
el:"#app",
data:{
},
components:{
'cpn2':{
template:"#cpn2",
data(){
return {
msg: '干嘛'
}
}
}
}
})
所以,因为组件的内部的data是return的对象,因此这个data的对象可以被复用,这个组件就可以被复用,作为独立的组件运行相互不干扰
父子件通信
上面提到了,子组件是不能引用父组件或者Vue实例数据的
但是,在开发中,往往数据是需要从上层往下层传递的
那么如何进行父子间通信呢
- 使用props向子组件传递数据
- 通过事件像父组件传递数据
关于父组件像子组件传递信息,可以这么理解
- 首先,父组件在应用子组件的元素标签上引用一个属性 a1 ,标签内容为你好
- 子组件使用props传递父组件的内容
- 此时,props数组中的’属性名称’,就是父组件元素标签上的属性.
- 那么属性名称=‘内容’,此时props数组内的’属性名称’.两个属性名称相同,达到了引用的方法
- 那么这个属性内容就可以被引用,在子组件的模板上直接使用属性名称,就可以引用属性内容
- 而父组件的属性一般都是动态绑定的,绑定在Vue的实例中的data中
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>JS Bin</title>
</head>
<body>
<div id="app">
<child-component a1='你好'></child-component>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script>
const app = new Vue({
el:"#app",
data:{
},
components:{
'child-component':{
template:`<div>{
{a1}}</div>`,
props:['a1']
}
}
})
</script>
</body>
</html>
单向数据流
第一种使用场景
将父组件传递进来的数据通过初始值保存起来
props的值可以通过组件data函数中的this.xxx直接获取
这样保存好的来自父组件的数据,就可以在不同组件中单独操作
- 这样,我子组件直接引用data函数返回的对象中的count就可以了嗷
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>JS Bin</title>
</head>
<body>
<div id="app">
<child-component a1='你好'></child-component>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script>
const app = new Vue({
el:"#app",
data:{
},
components:{
'child-component':{
template:`<div>{
{count}}</div>`,
props:['a1'],
data(){
return{
count: this.a1
}
}
}
}
})
</script>
</body>
</html>
第二种使用场景
另一种情况时props作为需要被转变的原始值传入,这种情况计算属性就可以
将父组件传递进来的数据,通过计算属性重新计算,返回值
- 小demo,根据父组件传进来的数字,决定子组件的宽度
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>JS Bin</title>
</head>
<body>
<div id="app">
<input type="text" v-model='width'>
<child-component :a1='width'></child-component>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script>
const app = new Vue({
el:"#app",
data:{
width:'0'
},
components:{
'child-component':{
template:`<div :style='style'>{
{a1}}</div>`,
props:['a1'],
computed:{
style(){
return {
width: this.a1 +'px',
background: 'red',
height: '100px'
}
}
}
}
}
})
</script>
</body>
</html>
那么子组件怎么给父组件传递信息呢?
子组件使用$emit()触发事件
父组件用$on()监听事件
- 第一步 自定义事件
- 第二步 在子组件使用
$emit()
触发事件,第一个参数是事件名,后面是要传递的数据 - 第三步,在自定义事件中用一个参数接收
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>JS Bin</title>
</head>
<body>
<div id="app">
点击数字发生变化:{
{
msg}}
<child-component @change='handleMsg'></child-component>
</div>
<template id='aaa'>
<button @click='add'>+</button>
</template>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script>
const app = new Vue({
el:'#app',
methods:{
handleMsg(value){
this.msg=value//父组件事件方法中拿到子组件的值,并把值付给msg
}
},
data:{
msg:0
},
components:{
'child-component':{
template:'#aaa',
data(){
return {
count: 0
}
},
methods:{
add(){
this.count++//设置子组件点击事件的方法,点击按钮造成子组件的count++
this.$emit('change',this.count)//然后把子组件的count的值传递给父组件的自定义事件,第一个参数是自定义事件的名称,第二个参数是子组件要传递的值
}
}
}
}
})
</script>
</body>
</html>
上面的例子使用的是自定义事件
其实不需要使用自定义事件,直接绑定v-model,并$emit()触发input事件,效果是一样的
- 就是个语法糖
- 因为v-model是双向绑定的,v-model本身绑定的是input事件,并且动态绑定value和data的值
- 因此,原理就是将子组件的参数传给value,通过v-model,然后传给父组件的data.