在vue中查找子元素和父元素提供了this.$parent、this.$children,但是如果需要查找任意层级子元素和祖先元素并没有直接的API,需要封装方法:
案例
index.vue
<template>
<div>
<!-- jq closest效果 -->
jq closest效果 <br>
<com2 @comParentItem="com2Fun">
<!-- 父元素com1 -->
<com1>
<com2></com2>
</com1>
</com2>
<br>
<br>
<com1>
<!-- 父元素com1 -->
<com2>
<com1></com1>
</com2>
</com1>
</div>
</template>
<script>
import com1 from './com1'
import com2 from './com2'
export default {
//
components: {
com1,
com2
},
data(){
return { }
},
methods: {
/*
com2Fun的方法
*/
com2Fun(item){
console.log('触发父元素事件------ ');
console.log(item);
}
}
}
</script>
<style>
.item {
border: 1px solid red;
height: 30px;
line-height: 30px;
}
</style>
com1.vue
<!-- 组件一
实现找到任意子元素
-->
<template>
<div>
<slot>
<com3 @click.native="showChild">
<com3>
<com4 @comChilItem="comChilItemFun">
<com3 class="item" >
子元素列表1
</com3>
<com3 class="item">
子元素列表2
</com3>
<com3 class="item">
子元素列表3
</com3>
</com4>
</com3>
</com3>
</slot>
</div>
</template>
<script>
import com3 from './com3'
import com4 from './com4'
export default {
components: {
com3,
com4
},
data(){
return {}
},
methods: {
/*
找到指定的子元素
*/
broadcast(componentName, eventName, params, that){
//
broadcast.call(this, componentName, eventName, params, that);
function broadcast(componentName, eventName, params, that) {
//遍历所有子组件
this.$children.forEach(child => {
var name = child.$options._componentTag.toLowerCase();
//寻找符合指定名称的子组件
// if (name === componentName) {
if (componentName.includes(name)) {
//在符合的自组件上触发的事件,但是不会再继续寻找符合名称的组件的子集,原因?
child.$emit.apply(child, [eventName].concat(params));
} else {
//不符合继续寻找他的子集(即孙子组件)
broadcast.apply(child, [componentName, eventName, params].concat([that]));
}
});
}
},
showChild(){
//
this.broadcast('com4', 'comChilItem', {children: '2'});
},
comChilItemFun(item){
console.log('子组件被触发--------');
console.log(item);
}
}
}
</script>
<style>
</style>
com2.vue
<!-- 组件二
实现找到任意祖先元素
-->
<template>
<com1>
<slot>
<com4>
<com1>
<com1 @click.native="showParent">
<com1 class="item" >
列表1
</com1>
<com1 class="item">
列表2
</com1>
<com1 class="item">
列表3
</com1>
</com1>
</com1>
</com4>
</slot>
</com1>
</template>
<script>
import com1 from './com1.vue'
import com4 from './com4.vue'
export default {
components: {
com1,
com4
},
data(){
return {}
},
methods: {
/*
找到指定的父元素,仿jq的closest
*/
dispatch(componentName, eventName, params){
var parent = this.$parent || this.$root;
var name = parent.$options._componentTag.toLowerCase();
//寻找父级,如果父级不是符合的组件名,则循环向上查找
// while (parent && (!name || name !== componentName)) {
while (parent && (!name || !componentName.includes(name))) {
parent = parent.$parent;
if (parent) {
name = parent.$options._componentTag;
}
}
//找到符合组件名称的父级后,触发其事件。整体流程类似jQuery的closest方法
if (parent) {
parent.$emit.apply(parent, [eventName].concat(params));
}
},
showParent(){
// 找到指定的祖先元素
this.dispatch('com2', 'comParentItem', {parent: '1'});
}
}
}
</script>
<style>
</style>
com3.vue
<!-- 组件一 -->
<template>
<div>
<slot>
</slot>
</div>
</template>
<script>
export default {
data(){
return {}
},
methods: {
}
}
</script>
<style>
</style>
com4.vue
<!-- 组件一 -->
<template>
<div>
<slot>
</slot>
</div>
</template>
<script>
export default {
data(){
return {}
},
methods: {
}
}
</script>
<style>
</style>
网友评论