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}})