Vue—组件
目录
- Vue---组件
- 定义组件
- 全局组件
- 局部组件
- 组件通讯`***重点***`
- 父子通信之父传子(props)
- 父子通信之子传父($emit)
- ref属性($refs)
- 动态组件
- 插槽
- 命名插槽
定义组件
全局组件
- vue2中template只能传递单标签,若要定义多个标签需要用div或其他包裹,vue3随意
<div id="app">
<Child1></Child1>
</div>
Vue.component('Child1', {
template: `
<p>我是{{ name }}</p>
`,
data() {
return {name: '组件1'}
},
})
局部组件
局部组件在注册后只能在当前实例或者是组件中使用
- 标签的命名只有首字母能大写,其余地方大写会直接报错
<div id="app2">
<mydiv></mydiv>
</div>
// 写法1
const vm2 = new Vue({
el: '#app2',
components: {
'mydiv': {
template: `<p>我是{{ name }}</p>`,
data() {
return {name: '组件2'}
}
}
}
})
// 写法2
let mydiv = {
template: `<p>我是{{ name }}</p>`,
data() {
return {name: '组件2'}
}
}
const vm2 = new Vue({
el: '#app2',
components: {
mydiv
}
})
组件通讯***重点***
在局部注册组件中我们是将组件注册到了vue根组件中,这里的根组件(**const vm2 = new Vue({})
**这部分)也就是父组件,那么他和局部组件(子)传递数据的过程就叫组件通讯
<div id="app2"> // 父
<mydiv></mydiv> // 子
</div>
父子通信之父传子(props)
- 关键字
props
:通过props
,父组件可以向子组件传递数据,子组件可以接收父组件传递的数据并在内部使用 - 案例中
<qwe :name="info.name" :age="info.age"></qwe>
的name和age其实就相当于是由props赋予的属性,因为在原根组件中是没有这两个属性的,他们是由props传递过来的
<div id="app">
<qwe :name="info.name" :age="info.age"></qwe>
</div>
let qwe = {
template: `
<div>
<p>你好</p>
<p>{{ name }}</p>
<p>{{ age }}</p>
</div>
`,
props:['name','age']
}
const vm = new Vue({
el: '#app',
data: {
info: {'name': '张三', 'age': 18}
},
components: {
qwe
}
})
- props应传递字符串形式属性名,并且与data不要存在同名属性
父子通信之子传父($emit)
- 关键字
$emit
:通过$emit
,子组件可以向父组件发送自定义事件,父组件可以监听这些事件并做出相应的处理
<div id="app">
// getchild为自定义事件,用于子传父
<child1 @getchild="handleGetChild"></child1>
我儿子叫{{childname}}
</div>
var child1 = {
template:
`
<button @click="handleSend">点我获得儿子</button>
`,
data() {
return {'name': '张三'}
},
methods: {
handleSend() {
// 传递this.name给父组件,也就是'张三'
this.$emit('getchild', this.name)
}
}
}
const vm = new Vue({
el: '#app',
data: {
childname: ''
},
components: {
child1
},
methods: {
handleGetChild(info) {
// info是子组件传递来的数据
this.childname = info
}
}
})
ref属性($refs)
- $refs关键字:可以从子组件、父组件、任意其他组件中获取数据、调用函数
沿用上述示例:
<div id="app">
// 新增绑定事件childRef
<child1 @getchild="handleGetChild" ref="childRef"></child1>
我儿子叫{{childname}}
</div>
var child1 = {
template:
`
<button @click="handleSend">点我获得儿子</button>
`,
data() {
return {'name': '张三'}
},
methods: {
handleSend() {
this.$emit('getchild', this.name)
},
sayHello(){
console.log('你好')}
}
}
const vm = new Vue({
el: '#app',
data: {
childname: ''
},
components: {
child1
},
methods: {
handleGetChild(info) {
// 打印子组件中的数据
console.log(this.$refs.childRef.name)
// 触发子组件中的函数satHello()
this.$refs.childRef.sayHello()
this.childname = info
}
}
})
- 此时点击按钮后会在控制台打印’张三 你好’
动态组件
- is关键字:可以接受一个组件名或对象,并根据该值渲染对应组件
<div id="app">
<button @click="handleSwitch(1)">点我打开组件1</button>
<button @click="handleSwitch(2)">点我打开组件2</button>
<button @click="handleSwitch(3)">点我打开组件3</button>
<components :is="current"></components>
</div>
var mydiv1 = {
template:
`
<div>我是组件1</div>
`
}
var mydiv2 = {
template:
`
<div>我是组件2</div>
`
}
var mydiv3 = {
template:
`
<div>我是组件3</div>
`
}
var vm = new Vue({
el: '#app',
data: {
current: '',
switchList: [mydiv1, mydiv2, mydiv3]
},
components: {
mydiv1,
mydiv2,
mydiv3,
},
methods: {
handleSwitch(s) {
this.current = this.switchList[s - 1]
}
}
})
插槽
一般情况下,组件内的内容都是写死的,只能通过通信或修改组件本身,这导致其扩展性非常差,因此出现了插槽这一概念,只需在组件中添加<slot></slot>
,就可以在body的组件标签中添加内容
<div id="app">
<p>-----父组件开始-----</p>
<mydiv></mydiv>
<mydiv><button>来自插槽的按钮</button></mydiv>
<mydiv>我是父组件,来占插槽的</mydiv>
<p>-----父组件结束-----</p>
</div>
var mydiv = {
template:
`
<div>
<p>----插槽开始----</p>
<slot></slot>
<p>----插槽结束----</p>
</div>
`
}
var vm = new Vue({
el:'#app',
components:{
mydiv
}
})
- 每个插槽都会接受父组件插入的所有数据
- 当插槽未被使用时他会沿用上一个父组件
<div id="app">
<p>-----父组件开始-----</p>
<mydiv><button>来自插槽的按钮</button></mydiv>
<p>-----父组件结束-----</p>
</div>
template:
`
<div>
<p>----插槽开始----</p>
<slot></slot>
<slot></slot>
<p>----插槽结束----</p>
</div>
`
命名插槽
- 命名插槽的好处,不会因为未使用插槽而自动填充
<div id="app">
<p>-----父组件开始-----</p>
<mydiv v-slot:a><button>来自插槽的按钮</button></mydiv>
<p>-----父组件结束-----</p>
</div>
var mydiv = {
template:
`
<div>
<p>----插槽开始----</p>
<slot name="a"></slot>
<slot name="b"></slot>
<p>----插槽结束----</p>
</div>
`
}
var vm = new Vue({
el:'#app',
components:{
mydiv
}
})