子传父:自定义事件 v-on
  • props用于父组件向子组件传递数据,还有一种比较常见的是子组件传递数据或事件到父组件中。我们应该如何处理呢?这个时候,我们需要使用自定义事件向父组件传递参数来完成。
  • 我们之前学习的v-on不仅仅可以用于监听DOM事件,也可以用于组件间的自定义事件。

自定义事件流程:

在子组件中,通过$emit()来触发事件。

在父组件中,通过v-on来监听子组件。

举例:click事件

  1. 子组件:模板template中,建立一个click事件,@click="post(text),将要传递的数据作为参数。
  2. 子组件:建立post方法,用this.$emit(),发射自定义指令名和发射的参数
   post(arg) {
       this.$emit('post-text', arg)
   }
  1. 在父!组件的模板HTML中,子组件标签上,添加自定义指令及方法

注意@post-text=“recData” recData 不要加参数或()

   <message-cpn @post-text="recData">
   </message-cpn>
  1. 在父组件中,写recData方法,来接收数据
   methods: {
       recData(text) {
           console.log(text);
       }
   },
传递字符串
<!DOCTYPE html>
<html>
    <head>
        <meta charset="utf-8">
        <title></title>
        <script src="js/v2.6.10/vue.js"></script>
    </head>
    <body>
        <div id="app">
            <msg @post-text="rec"></msg>
        </div>
        <template id="msgTemplate">
            <div>
                <button @click="post(text)">{{text}}</button>
            </div>
        </template>
        <script>
            let msg = {
                data() {
                    return {
                        text: '五一节日快乐!'
                    }
                },
                methods: {
                    post(text) {
                        // $emit 用于子组件向父组件传递数据的方法。
                        // 两个参数: 1、向父组件提供的一个自定义指令名。 2、子组件要发送出去的数据。
                        this.$emit('post-text', text)
                    }
                },
                template: msgTemplate
            }
            let app = new Vue({
                el: '#app',
                components: {
                    msg
                },
                methods: {
                    rec(value) {
                        alert(value)
                    }
                },
            })
        </script>
    </body>
</html>





传递对象
<!DOCTYPE html>
<html>
    <head>
        <meta charset="utf-8">
        <title></title>
        <script src="js/v2.6.10/vue.js"></script>
    </head>
    <body>
        <div id="app">
            <nav-list @item-click="goUrl"></nav-list>
        </div>

        <template id="navListTemplate">
            <div>
                <button v-for="(item,index) in navList" @click="post(item)" >{{item.name}}</button>
            </div>
        </template>
        <script>
            let navList = {
                data() {
                    return {
                        navList: [
                            {id:1,name:"java"},
                            {id:2,name:"html"},
                            {id:3,name:"css"},
                            {id:4,name:"js"}
                        ]
                    }
                },
                methods: {
                    post(item){
                        this.$emit('item-click',item)
                    }
                },
                template: navListTemplate
            }
            let app = new Vue({
                el: '#app',
                components: {
                    "nav-list":navList
                },
                methods: {
                    goUrl(item){
                        console.log(item);
                    }
                },
            })
        </script>
    </body>
</html>

兄弟组件通信

留坑,将工程的时候讲

访问组件DOM

  • $parent 在子组件中访问父级DOM 不常用
  • $children 在父组件访问子级DOM 1个子组件 肯定[0] 如果多个子组件 [0,1,2] 他的顺序是不一定的。需要数组进行一个遍历,才能应用
  • $root 访问根DOM
  • $refs 直接定位需要访问的组件

插槽

Vue 实现了一套内容分发的 API,将<slot>元素作为承载分发内容的出口,这是vue文档上的说明。具体来说,slot就是可以让你在组件内添加内容的‘空间’.使用插槽是在存在父子关系的组件,可以在子组件中决定插槽的位置,同时子组件也可以给这些插槽的默认信息,当父组件中没有需要给子组件插槽插入信息时,显示的是子组件插槽定义的默认信息。

默认插槽: 通过父标签的内容 替换插槽内容

具名插槽 :给插槽命一个名。 通过父标签的内容 替换插槽内容

作用域插槽: 通过子组件的数据 在父组件里展示

默认插槽的使用

<!DOCTYPE html>
<html>
    <head>
        <meta charset="utf-8">
        <title></title>
        <script src="js/v2.6.10/vue.js"></script>
    </head>
    <body>
        <div id="app">
            <top-cpn>时尚男鞋</top-cpn>

        </div>
        <!-- 插槽slot 是用在子组件的模板中 <slot></slot> -->
        <template id="topTemplate">
            <div>
                <img src="img/btnstart.png" alt="" srcset="">
                <span style="color: aquamarine;font-size: 30px;">
                    <slot></slot>
                </span>

            </div>
        </template>

        <script>
            let topCpn = {
                template: topTemplate,
            }

            let app = new Vue({
                el: '#app',
                components: {
                    "top-cpn":topCpn
                }

            })
        </script>
    </body>
</html>

具名插槽的使用

<!DOCTYPE html>
<html>
    <head>
        <meta charset="utf-8">
        <title></title>
        <script src="js/v2.6.10/vue.js"></script>
    </head>
    <body>
        <div id="app">
            <top-cpn>
                <template #one>
                    时尚男鞋
                </template>
                <template v-slot:three>
                    时尚女鞋
                </template>
            </top-cpn>
        </div>
        <!-- 插槽slot 是用在子组件的模板中 <slot></slot> -->
        <template id="topTemplate">
            <div>
                <div class="testSolt">
                    <p class="title">具名插槽</p>
                    <!-- 给插槽加name 属性,就是所谓的具名插槽 -->
                    <slot name="one"></slot>
                    <slot name="two"></slot>
                </div>
                <!-- 子组件也可以同时定义多个具名插槽 -->
                <div style="margin-top:300px;background:#fff;height:100px;color:blue;">
                    <slot name="three"></slot>
                </div>
            </div>
        </template>

        <script>
            let topCpn = {
                template: topTemplate,
            }

            let app = new Vue({
                el: '#app',
                components: {
                    "top-cpn": topCpn
                }

            })
        </script>
    </body>
</html>

作用域插槽的使用

<!DOCTYPE html>
<html>
    <head>
        <meta charset="utf-8">
        <title></title>
        <script src="js/v2.6.10/vue.js"></script>
    </head>
    <body>
        <div id="app">
            <top-cpn >
                <!-- 插槽里面同时可以插入一个组件 或者字符串内容等都可以 -->
                <template v-slot="slotProps">
                <p>{{slotProps.obj.msg}}---{{slotProps.obj.message}}</p>
                </template>
            </top-cpn>
        </div>

        <template id="topTemplate">
            <div>
                <div class="testSolt">
                    <p class="title">作用域插槽</p>
                    <!-- 子组件中告诉父组件,要实现obj里的信息 -->
                    <slot :obj="obj">默认信息</slot>
                </div>
            </div>
        </template>
        <script>
            let topCpn = {
                data() {
                    return {
                        obj: {
                            msg: '我是msg',
                            messge: '我是message'
                        }
                    }
                },
                template: topTemplate,
            }

            let app = new Vue({
                el: '#app',
                components: {
                    "top-cpn": topCpn
                }

            })
        </script>
    </body>
</html>

api

nextTick

set delete
<!DOCTYPE html>
<html>
    <head>
        <meta charset="utf-8" />
        <title></title>
        <!-- <script src="https://unpkg.com/vue@next"></script> -->
        <script src="js/v2.6.10/vue.js" type="text/javascript" charset="utf-8"></script>
    </head>
    <body>
        <div id="app">
            <!-- 插值表达式:通过两个大括号,把变量包起来 -->
            <!-- <div ref="showtext">{{showText}}</div>-->
            <button @click="addAge">添加年龄</button>
            {{obj}}
        </div>
        <script>
            let vm = new Vue({
                el: '#app', // el = element的缩写 挂载到那个元素上,或者将来渲染到那个区域 id #app css基础选择器 # id . class 
                data: {
                    showText: 'Hello Vue',
                    obj: {
                        name: "hahaha",
                        sex: "男性"
                    }
                },
                mounted() {
                    // console.log(this.$refs.showtext.innerText);
                },
                methods: {
                    addAge() {
                        // this.obj.age = 12
                        // 动态添加对象的属性,并且希望在视图中实时更新
                        this.$set(this.obj,"age",18)
                        console.log(this.obj);
                    }
                },
            });
        </script>
    </body>
</html>