美文网首页1024Vue.js前端Vue专辑
44.Vue实现查找任意层级子元素和祖先元素

44.Vue实现查找任意层级子元素和祖先元素

作者: 圆梦人生 | 来源:发表于2019-12-27 12:50 被阅读0次

    在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>
    

    相关文章

      网友评论

        本文标题:44.Vue实现查找任意层级子元素和祖先元素

        本文链接:https://www.haomeiwen.com/subject/hxqdoctx.html