Vue组件
Vue组件
Vue实例与组件
通过new Vue()
产生的是Vue实例,而Vue实例也可以看做根组件。
我们也可以通过Vue.component()
产生Vue组件,所谓组件就是可以复用到其他的实例中的部件,它分为全局组件和局部组件。
- 全局组件:全局组件又称根组件,它可以在任意位置被调用
- 局部组件:局部组件只能在定义位置的实例/组件中使用
组件的基本使用
全局组件定义方法
Vue.component(
'child', // 组件标签名
{
template: `<h1>html模板</h1>
用模板字符串编写即可,它的子组件只能在这里使用
<grandchild></grandchild>
`, // 里面写html内容,必须包在一个标签中
data() { // 比起data:数据对象,这种返回对象的方式每次都是新产生的,可以复用
return {
name: '彭于晏',
t: null
}
},
methods: {}, // 组件方法,可以在组件标签范围内使用
components: { // 子组件
'grandchild': {
template: `
<div>
<h1>局部组件---{{ gcdata }}</h1>
</div>`,
data() {
return {
gcdata: '孙子'
}
}
},
}
})
注意事项:
- Vue实例是通过el挂载html的标签,而Vue组件是成为html的一种标签
- template的html内容,必须最终包含在一个标签内
- 因为对象都是引用型的,所以作为复用的组件,data要以函数的形式产出返回,而不能直接用键值对的形式,因为这种情况组件被用多次时会共用一份data
- components字段可以作为组件的子组件,也可以作为实例的子组件
组件基础使用方法
<div id='app'>Vue实例通过el='#app'的方式绑定标签(挂载)
# 组件标签名child,将对应组件的template中的模板添加到此标签的位置进行渲染
<child></child>
# 另一种调用形式
<child/>
# 不是根组件不能在全局使用 x
<grandchild></grandchild>
</div>
# 由于是根组件,什么位置都可以,和app实例也无关
<child></child>
局部组件定义的两种方式
-
第一种是上述示例代码中,直接嵌套的方式
-
第二种是先定义一个对象,然后在放入全局组件的component中
let grandchild ={ template: ``, data() {}, } Vue.component( 'child', // 组件标签名 { template: `` // 里面写html内容,必须包在一个标签中 data() {}, // 返回数据的方法 methods: {}, // 组件方法,可以在组件标签范围内使用 components: { // 子组件 grandchild } })
组件间通信
父标签与子标签中的变量名默认是隔离的,想使用对方的数据则需要数据传递。
自定义属性 -- 实现父传子通信
<div id="app">
<!--pdata就是在props中注册的属性,在这里通过属性方法绑定父组件的数据,
在子组件中可以通过pdata引用-->
<child :pdata="parentData"></child>
</div>
<script>
let child = {
template: `
<div>
<p>父组件传过来的:{{pdata}}</p>
<p>子组件自己的:{{childdata}}</p>
</div>`,
data() {
return {childdata: '儿子数据'}
},
// props: ['pdata']
props:{
pdata:String,
}
}
new Vue({
el: '#app',
data: {
parentData: '父亲数据'
},
components:{
child
}
})
</script>
- 自定义属性需要注册在props中,props可以是数组形式和对象形式
- 数组形式则就是直接注册了自定义属性
- 对象形式的键作为自定义属性,后面用于数据属性限制如String、Number
- 注册的属性可以通过属性方法
:attr="pdata"
绑定父组件的数据 - 自定义属性最好采取单词,其他形式都有可能出错,尤其是小驼峰
自定义组件 -- 实现子传父通信
<div id="app">
<p>子组件传递过来的数据:{{parentData}}</p>
<!---myevent事件触发了父组件中的方法,并传入了子组件的数据-->
<child @myevent="handleEvent"></child>
</div>
<script>
let child = {
template: `
<div>
<hr>
<input type="text" v-model="childdata">
<button @click="loadToParent">上传到父组件</button>
<hr>
</div>`,
data() {
return {childdata: ''}
},
methods:{
loadToParent(){
// $emit方法将数据传给myevent事件触发的函数
this.$emit('myevent',this.childdata)
}
}
}
new Vue({
el: '#app',
data: {
parentData: ''
},
methods: {
handleEvent(childdata){
// 父组件拿到了子组件的数据进行操作
this.parentData=childdata
}
},
components:{
child
}
})
</script>
-
$emit方法将数据传给myevent事件触发的函数
-
myevent事件触发了父组件中的方法,并传入了子组件的数据
@myevent事件可以写在子组件的属性中
-
父组件定义的方法要定义一个形参接收子组件的数据
ref属性 -- 实现完全通信
在Vue实例/组件中的标签或者组件都可以添加ref属性,添加了ref属性的标签/组件都会被根组件的this.$refs
接收组织成一个对象。
- html原生标签加ref属性,$refs中对应的值为DOM标签
- vue组件添加ref属性,$refs中对应的值为Vue组件对象,包含组件的所有属性包括数据属性,并且因为对象的引用传值,我们也可以对其进行修改。
由于ref属性取和修改组件属性都非常方便,所以就可以用于父子组件间的完全通信。
<div id="app">
<p ref="pEle">子组件传递过来的数据:{{parentData}}</p>
<child ref="child"></child>
<button @click="handleClick">上传</button>
</div>
<script>
let child = {
template: `
<div>
<hr>
<input type="text" v-model="childdata">
<hr>
</div>`,
data() {
return {childdata: ''}
},
}
new Vue({
el: '#app',
data: {
parentData: ''
},
methods: {
handleClick(){
this.parentData=this.$refs.child.childdata
console.log(this.$refs)
}
},
components:{
child
}
})
</script>
组件进阶方法
动态组件
组件标签,vue提供用来根据组件名反射组件的:
<component is="组件名"></component>
那么我们可以对is属性做数据绑定,通过:is="变量"
达到动态组件的效果。
<div id="app">
<span @click="handleClick('aComponent')">a组件</span>|
<span @click="handleClick('bComponent')">b组件</span>|
<span @click="handleClick('cComponent')">c组件</span>
<br>
<component :is="showComponent"></component>
</div>
<script>
let aComponent = {template: `<h1>a组件</h1>`}
let bComponent = {template: `<h1>b组件</h1>`}
let cComponent = {template: `<h1>c组件</h1>`}
new Vue({
el: '#app',
data: {
showComponent: 'aComponent'
},
methods: {
handleClick(componentName){
this.showComponent = componentName
}
},
components: {aComponent, bComponent, cComponent}
})
</script>
keep-alive标签
在上述代码的基础上,只需要在component标签外侧添加keep-alive标签嵌套,就能保证内部的所有产生的组件只会隐藏不会销毁,这样就保证了一些组件在进行一些操作后能够保存状态,而不会重新加载导致状态丢失。
<keep-alive>
<component :is="showComponent"></component>
</keep-alive>
插槽
组件的模板中可以使用slot标签预留位置,当在组件被调用时,可以在组件标签体中书写html标签,这样增强了组件的拓展性和灵活性。
匿名插槽
- 在child组件标签内书写html代码,标签就会渲染到组件模板slot的位置
- 如果预留了多个slot并没有命名则每个slot的位置都会渲染插入的html代码
<div id="app">
<child>
<h1>匿名插入</h1>
</child>
</div>
<script>
let child = {
template: `
<div>
<hr>
<slot></slot>
<hr>
<slot></slot>
<hr>
</div>`,
}
new Vue({
el: '#app',
data: {},
methods: {},
components: {child}
})
</script>
具名插槽
- 给模板slot标签加上name,则就变成了具名插槽
- 通过具名插槽插入的标签,需要添加对应的slot属性
slot="slot1"
- 组件标签体中的其他标签(没有slot属性)都插入到匿名插槽中。
<div id="app">
<child>
<h1>匿名插入</h1>
<h1 slot="slot1">slot1插入</h1>
<h1 slot="slot2">slot2插入</h1>
<h1>没添加slot属性的标签都是匿名插入</h1>
</child>
</div>
<script>
let child = {
template: `
<div>
<slot></slot>
<hr>
<slot name="slot1"></slot>
<hr>
<slot name="slot2"></slot>
<hr>
</div>`,
}
new Vue({
el: '#app',
data: {},
methods: {},
components: {child}
})
</script>
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· 【自荐】一款简洁、开源的在线白板工具 Drawnix