vue单文件完成父组件向子组件传值

父组件向子组件传值

  • 流程:父组件向子组件传递数据,首先要在父组件中使用v-bind命令将要传递的数据绑定到子组件上,在子组件中的props属性接收父组件传递过来的数据

  • 测试选题

    • 测试传基本类型
    • 测试传对象类型
    • 测试传数组类型
  • 目的:测试父组件传递不同类型数据给子组件,观察子组件是否可以动态渲染

测试一 传基本类型

  • 由父组件由字符串改数值加字符串,观察能否动态渲染
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
    <title>Document</title>
    <style>
        #father {
            display: flex;
            justify-items: center;
            flex-direction: column;
        }
        
        .button {
            width: 100px;
        }
    </style>
</head>

<body>
    <div id="father">
        <son-component :message="fatherMessage"></son-component>
        <button class="button" @click="handleButtonClick"> 字符串数值类型混合传值 </button>
    </div>
    <script>
        Vue.component("son-component", {

            template: `<div id="son" ><p>{{this.message}}</p></div>`,
            props: ["message"]
        })
        new Vue({
            el: '#father',
            data() {
                return {
                    fatherMessage: 'Hello son!'
                }
            },
            methods: {
                handleButtonClick() {
                    this.fatherMessage = "字符串数值混合传值" + 1820299979 + "@qq.com"
                }
            }
        })
    </script>
</body>

</html>

测试二 传对象类型

  • 父组件新增加一个key **结论:**子组件可以成功动态渲染

  • 父组件修改一个key的value **结论:**子组件可以成功动态渲染

  • 父组件修改变对象的引用 **结论:**子组件可以成功动态渲染

  • 父组件key:null改成有值 **结论:**子组件可以成功动态渲染

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
    <title>Document</title>
    <style>
        #father {
            display: flex;
            justify-items: center;
            flex-direction: column;
        }
        
        .button {
            width: 200px;
        }
    </style>
</head>

<body>
    <div id="father">
        <son-component :message="fatherMessage"></son-component>
        <button class="button" @click="handleButtonAddClick"> 新增一个对象</button>
        <button class="button" @click="handleButtonChangeClick"> 改变对象value值</button>
        <button class="button" @click="handleButtonChangeYinYongClick"> 改变对象的引用</button>
        <button class="button" @click="handleButtonChangeEmptyClick"> 由空对象变成有值</button>
    </div>
    <script>
        Vue.component("son-component", {

            template: `<div id="son" ><p>{{this.message}}</p></div>`,
            props: {
                message: {

                }
            }
        })
        new Vue({
            el: '#father',
            data() {
                return {
                    fatherMessage: {
                        city: "杭州",
                        test: null
                    }
                }
            },
            methods: {
                handleButtonAddClick() {
                    this.fatherMessage.block = "西湖区"
                },
                handleButtonChangeClick() {
                    this.fatherMessage.city = "哈尔滨"
                },
                handleButtonChangeYinYongClick() {
                    this.fatherMessage = {
                        movie: "流浪地球",

                    }
                },
                handleButtonChangeEmptyClick() {
                    this.fatherMessage.test = "征服未知,勇做先躯"
                }
            }
        })
    </script>
</body>

</html>

测试三 传数组类型

  • 父组件新增加一个元素 **结论:**子组件可以成功动态渲染

  • 父组件修改一个元素 **结论:**子组件可以成功动态渲染

  • 父组件用splice方法删除数值 **结论:**子组件可以成功动态渲染

  • 父组件由slice方法切割数值 结论:子组件不能完成动态渲染

  • 父组件改变数组的引用 **结论:**子组件可以成功动态渲染

  • 说明

Slice方法并不会修改数组,而是返回一个子数组。

解决方案:把返回的子数组赋值给数组

this.fatherMessage = this.fatherMessage.slice(4, 8)

代码:

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
    <title>Document</title>
    <style>
        #father {
            display: flex;
            justify-items: center;
            flex-direction: column;
        }
        
        .button {
            width: 200px;
        }
    </style>
</head>

<body>
    <div id="father">
        <son-component :message="fatherMessage"></son-component>
        <button class="button" @click="handleButtonAddClick"> 新增一个数值</button>
        <button class="button" @click="handleButtonChangeClick"> 改变一个数值</button>
        <button class="button" @click="handleButtonSpliceClick"> 用splice方法切数值</button>
        <button class="button" @click="handleButtonSliceClick"> 用slice方法切数值</button>
        <button class="button" @click="handleButtonChangeEmptyClick"> 改变数组的引用</button>
    </div>
    <script>
        Vue.component("son-component", {

            template: `<div id="son" ><p>{{this.message}}</p></div>`,
            props: {
                message: {

                }
            }
        })
        new Vue({
            el: '#father',
            data() {
                return {
                    fatherMessage: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
                }
            },
            methods: {
                handleButtonAddClick() {
                    this.fatherMessage.push(2333)
                },
                handleButtonChangeClick() {
                    this.fatherMessage[2] = 333
                },
                handleButtonSpliceClick() {
                    this.fatherMessage.splice(5, 1)
                },
                handleButtonSliceClick() {
                    this.fatherMessage.slice(6, 8)
                },
                handleButtonChangeEmptyClick() {
                    this.fatherMessage = [9, 8, 7, 6, 5, 4, 3, 2, 1]
                }
            }
        })
    </script>
</body>

</html>

二.子向父传值

  • 测试选题

    • 子组件通过$emit()向父组件传值
    • 子组件通过父组件传来的prop(基本类型)传值
    • 子组件通过父组件向子组件传递函数,子组件修改参数传值
    • 通过总线方式传值
    • 通过父组件prop传来的对象,子组件修改对象value传值
  • **目的:验证 子向父传值共有几种方式 **

测试一 通过$emit()传值

  • 结论:子可以将值传给父组件,并且可以完成动态渲染
<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
    <title>Document</title>
    <style>
        #father {
            display: flex;
            justify-items: center;
            flex-direction: column;
        }
        
        .button {
            width: 200px;
        }
    </style>
</head>

<body>
    <div id="father">
        {{this.fatherMessage}}
        <son-component @thorwfather="thorwfather">

        </son-component>


    </div>
    <script>
        Vue.component("son-component", {

            template: `<button class="button" @click="handleClick"> 子组件传值(1)</button>`,
            props: {
                message: {

                }
            },
            data() {
                return {
                    sonMessage: "子组件传来的值"
                }
            },
            methods: {
                handleClick() {
                    this.$emit("thorwfather", this.sonMessage)
                }


            }
        })
        new Vue({
            el: '#father',
            data() {
                return {
                    fatherMessage: "父组件的初值"
                }
            },
            methods: {
                thorwfather(data) {
                    this.fatherMessage = data
                }
            }
        })
    </script>
</body>

</html>

测试二 修改父组件传来的prop

  • 结论:无法传值并且无法动态渲染

  • 原因:所有的 prop 都使得其父子 prop 之间形成了一个单向下行绑定:父级 prop 的更新会向下流动到子组件中,但是反过来则不行。这样会防止从子组件意外改变父级组件的状态,从而导致你的应用的数据流向难以理解。

  • 报错信息:Avoid mutating a prop directly since the value will be overwritten whenever the parent component re-renders. Instead, use a data or computed property based on the prop’s value. Prop being mutated: "message"

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
    <title>Document</title>
    <style>
        #father {
            display: flex;
            justify-items: center;
            flex-direction: column;
        }       
        .button {
            width: 200px;
        }
    </style>
</head>
<body>
    <div id="father">
        <son-component :message="fatherMessage"></son-component>
        {{fatherMessage}}
    </div>
    <script>
        Vue.component("son-component", {
            template: `<div id="son" ><button class="button" @click="handleButtonChangeClick"> 修改父组件传来的props值</button> </div>`,
            props: {
                message: {
                }
            },
            methods: {
                handleButtonChangeClick() {
                    this.message = "子组件改变的值"
                }
            }
        })
        new Vue({
            el: '#father',
            data() {
                return {
                    fatherMessage: "父组件传来的值"
                }
            },
            methods: {}
        })
    </script>
</body>
</html>

测试三 通过父组件传来函数并传参完成传值

  • 结论:父组件可以接收到值并且可以动态渲染

  • 备注:prop不止可以传递data里面的数据,mathods里面的方法也可以传递

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
    <title>Document</title>
    <style>
        #father {
            display: flex;
            justify-items: center;
            flex-direction: column;
        }     
        .button {
            width: 200px;
        }
    </style>
</head>
<body>
    <div id="father">
        {{reversedMessage}}
        <son-component :message="fatherFunction"></son-component>
    </div>
    <script>
        Vue.component("son-component", {
            template: `<div id="son" ><button class="button" @click="handleButtonChangeClick"> 修改父组件传来的props值</button> </div>`,
            props: {
                message: {
                    type: Function,
                }
            },
            data() {
                return {
                    son: "子组件传来的值"
                }
            },
            methods: {
                handleButtonChangeClick() {
                    this.message(this.son)
                }
            }
        })
        new Vue({
            el: '#father',
            data() {
                return {
                    fatherMessage: "父组件的值",
                }
            },
            computed: {
                reversedMessage() {
                    return this.fatherMessage
                }
            },
            methods: {
                fatherFunction(data) {
                    this.fatherMessage = data
                }
            }
        })
    </script>
</body>
</html>

测试四 总线的方式传值

  • 结论:可以完成传值并动态渲染
<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
    <title>Document</title>
    <style>
        #father {
            display: flex;
            justify-items: center;
            flex-direction: column;
        }
        
        .button {
            width: 200px;
        }
    </style>
</head>

<body>
    <div id="father">
        {{fatherMessage}}
        <son-component></son-component>
    </div>
    <script>
        var eventBus = new Vue()
        Vue.component("son-component", {
            template: `<div id="son" ><button class="button" @click="handleButtonChangeClick"> 修改父组件传来的props值</button> </div>`,
            data() {
                return {
                    son: "子组件传来的值"
                }
            },
            methods: {
                handleButtonChangeClick() {
                    eventBus.$emit("zongxian", this.son)
                }
            }
        })
        new Vue({
            el: '#father',
            data() {
                return {
                    fatherMessage: "父组件的值",
                }
            },
            created() {
                eventBus.$on("zongxian", (data) => {
                    this.fatherMessage = data
                })
            }
        })
    </script>
</body>

</html>

测试五 通过父组件传来的对象进行传值

  • 结论:可以传值并动态渲染
<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
    <title>Document</title>
    <style>
        #father {
            display: flex;
            justify-items: center;
            flex-direction: column;
        }
        
        .button {
            width: 200px;
        }
    </style>
</head>

<body>
    <div id="father">
        <son-component :message="fatherMessage"></son-component>
        {{fatherMessage}}
    </div>
    <script>
        Vue.component("son-component", {
            template: `<div id="son" ><button class="button" @click="handleButtonChangeClick"> 修改父组件传来的props值</button> </div>`,
            props: {
                message: {}
            },
            methods: {
                handleButtonChangeClick() {
                    this.message.city = "北京"
                }
            }
        })
        new Vue({
            el: '#father',
            data() {
                return {
                    fatherMessage: {
                        city: "杭州"
                    }
                }
            },
            methods: {}
        })
    </script>
</body>

</html>
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值