组件传值

Vue 组件传值

一. 父子组件传值

​ 步骤: 1. 在子组件标签中通过v-bind把自定义属性赋值为父组件的动态数据

​ 2. 在子组件对象中通过props字段添加自定义属性
​ props: ["myData"]
​ 3, 在子组件模板中, 使用自定义属性渲染数据
{{myData}}

<body>
    <script src='vue.js'></script>
    <!-- vue模板 -->
    <div id='myApp'>
        父组件中的输入: 
        <input type="text" v-model="name"> <br>
        <hr>
        子组件的显示:
        <my-com :my-data="name"></my-com>
    </div>
    <!-- 组件模板 -->
    <template id='com'>
        <span>
            {{myData}}
        </span>
    </template>  
    <script>
        // 组件
        Vue.component('myCom',{
            template: '#com',
            // 使用props字段添加自定义属性,用于接收父组件传值, 值是数组结构
            props: ["myData"],
            // created() {
            //     console.log(this.myData)
            // },
            // watch:{
            //     myData(newValue){console.log(newValue)}
            // },
            // computed:{ }
        })
        // 根组件
        var vm = new Vue({
            el: '#myApp',
            data: {
                name: "张三"
            }
        })
        // 总结: 父组件向子组件传值步骤: 
        // 1, 在子组件对象中通过props字段添加自定义属性
            // props: ["myData"]
        // 2, 在子组件标签中通过v-bind把自定义属性赋值为父组件的动态数据
            // <my-com :my-data="name"></my-com>
        // 3, 在子组件模板中, 使用自定义属性渲染数据
            // <span> {{myData}} </span>
    </script>

二 . 子传父

<body>
    <script src='vue.js'></script>
    <!-- vue模板 -->
    <div id='myApp'>
        <!-- 在组件标签上使用v-on绑定自定义事件, 调用父组件中的函数  -->
        <my-com @myevent="getData"></my-com> <hr>
        父组件显示: {{fatherData}}
    </div>
    <!-- 组件模板 -->
    <template id='com'>
        <div>
            子组件输入: <input type="text" v-model="childData">
        </div>
    </template>
    <script>
        // 组件
        Vue.component('myCom',{
            template: '#com',
            data(){
                return{
                    childData: "child"
                }
            },
            watch:{
                childData(newValue){
                    // 监听到子组件数据更新时,把新数据发送给父组件
                    // 原理: 子组件调用$emit函数发射一个自定义事件, 在父组件中监听事件并在事件函数中取值
                    this.$emit("myevent", newValue) 
                    // 参数一是自定义事件名, 事件名必须用小写
                    // 参数二是发送的数据
                }
            }
        })
        // 根组件
        var vm = new Vue({
            el: '#myApp',
            data: {
                fatherData:""
            },
            methods: {
                //在父组件的事件函数中拿到参数中的数据并展示
                getData(data){
                    this.fatherData = data
                }
            }
        })
        // 总结: 子组件向父组件传值的步骤:
        // 1, 在子组件中合适的位置, 通过$emit函数发射自定义事件,把数据发出去
            // this.$emit("myevent", newValue) 
        // 2, 在子组件标签上, 通过v-on绑定自定义事件,调用父组件中的事件函数
            // <my-com @myevent="getData"></my-com>
        // 3, 在父组件的事件函数中拿到参数中的数据并展示
            //  getData(data){ this.fatherData = data } 
    </script>
</body>

三 . 非父子组件传值

 <script src='vue.js'></script>
    <!-- vue模板 -->
    <div id='myApp'>
        <my-com1></my-com1>
        <my-com2></my-com2>
    </div>
    <!-- 组件模板 -->
    <template id='com1'>
        <div>
            组件1输入 : <input type="text" v-model="name">
        </div>
    </template>
    <template id='com2'>
        <div>
            组件2显示 : {{name2}}
        </div>
    </template>
    <script>

        // 总线: 在全局作用域创建一个空的vue对象,视作总线.用于非父子传值
        var bus = new Vue();

        // 组件1
        Vue.component('myCom1',{
            template: '#com1',
            data(){
                return{
                    name:"张三"
                }
            },
            watch: {
                name(value){
                    // 调用$emit自定义事件把数据发出去
                    // this.$emit()
                    // 使用bus总线调用$emit发送数据
                    bus.$emit("myevent", value)
                    console.log("发送")
                }
            }
        })
        // 组件2
        Vue.component('myCom2',{
            template: '#com2',
            data(){
                return{
                    name2: ""
                }
            },
            created() {
                console.log(this)
                // 在另一个组件的初始化函数created中使用bus总线监听自定义事件,取值
                // bus.$on("myevent", function(data){
                //     // 在事件函数中this指向事件目标bus, 不是当前组件com2
                //     console.log("接收",data, this)
                //     this.name2 = data
                // })
                // 使用箭头函数保证函数中的this和函数外的this保持一致为com2
                bus.$on("myevent", (data)=>{
                    // 在事件函数中this指向事件目标bus, 不是当前组件com2
                    console.log("接收",data, this)
                    this.name2 = data
                })

                // 注意: 每一个组件对象中都有属性 _uid 它是一个索引值, 记录的是这个组件创建的顺序(第一个创建的组件,_uid是0, 往后依次增加)
            },
        })
        // 根组件
        var vm = new Vue({
            el: '#myApp',
            data: {
            },
            methods: {
            }
        })
    
        // 总结: 非父子组件传值/兄弟组件传值/bus总线传值  
        // 1, 在全局作用域中创建空的vue对象, 称之为总线bus
            // var bus = new Vue();
        // 2, 在一个组件中合适的位置,通过bus总线调用$emit发送数据
            // bus.$emit("myevent", value)
        // 3, 在另一个组件中的初始化函数created中,使用bus总线监听事件, 接收数据并展示
            // bus.$on("myevent", (data)=>{ this.name2 = data })
           </script>

四 . 插槽传值

 <script src='vue.js'></script>
    <!-- vue模板 -->
    <div id='myApp'>
        父组件输入:                           
        <input type="text" v-model="name"> <hr>
        <my-com>默认在组件标签之间的信息会被忽略</my-com>
        <!-- 把父组件中的动态数据写入子组件标签中 -->
        <my-com>{{name}}</my-com>
    </div>
    <!-- 组件模板 -->
    <template id='com'>
        <div>
            <!-- 使用slot插槽标签显示子组件标签中的信息 -->
            子组件显示: <slot></slot>
        </div>
    </template>
    <script>
        // 组件
        Vue.component('myCom',{
            template: '#com',
            created() {
                // 在组件对象中拿不到插槽数据
            },
        })
        // 根组件
        var vm = new Vue({
            el: '#myApp',
            data: {
                name: "张三"
            }
        })

五 . 具名插槽

    <script src='vue.js'></script>
    <!-- vue模板 -->
    <div id='myApp'>
        <my-com>父组件动态数据</my-com> <hr>
        <my-com>
            <span slot="s1">父组件数据1</span>
            <span slot="s2">父组件数据3</span>
        </my-com>
    </div>
    <!-- 组件模板 -->
    <template id='com'>
        <div>
            <!-- 子组件模板中的每一个slot标签都会把插槽数据渲染一遍 -->
            <!-- 子组件显示: <slot></slot> <slot></slot> -->

            <!-- 当给slot标签添加name属性时, slot插槽就叫具名插槽 -->
            <!-- 具名插槽: 作用可以把插槽中的部分数据分发给不同的slot标签单独渲染 -->
            <slot name="s1"></slot> <br>
            子组件数据2 <br>
            <slot name="s2"></slot>
        </div>
    </template>
    <script>
        // 组件
        Vue.component('myCom',{
            template: '#com'
        })
        // 根组件
        var vm = new Vue({
            el: '#myApp'
        })
        // 总结: 插槽的用法
        // 1, 子组件模板中slot标签如果没有name属性会把插槽数据全部渲染
        // 2, slot标签添加name属性后,只会渲染插槽数据中拥有slot属性且name属性和slot属性值相同的数据
    </script>

posted @ 2021-12-02 10:33  水波凌步  阅读(158)  评论(0)    收藏  举报