【学习前端第六十一课】vue组件化开发(二)

数据流的单向性

先来看个例子

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    <div id="app">
        <h2>我是{{father}},我有一个儿子叫做{{son}}</h2>
        <son :son-name="son"></son>
    </div>
    <template id="temp1">
        <div class="box">
            <h3>我是儿子,我叫{{sonName}}</h3>
        </div>
    </template>
</body>
<script src="js/vue.js"></script>
<script>
    var son = {
        template:"#temp1",
        props:["sonName"]
    }

    new Vue({
        el:"#app",
        data:{            
                father:"baba",
                son:"erzi"
            },
            components:{
                son
            }       
    })
</script>
</html>

在上面的案例中,我们向子组件传递了一个数据 :son-name=“son” , 子组件拿到后就渲染在了页面上,所以数据是由父组件传递给子组件的

现在有两个问题

1、父级组件如果改变了son这个数据,子级是否会改变?

2、子级能不能改变父级传递的son?

结论一:父级改变,子级也会改变
<div id="app">
    <h2>我是{{father}},我有一个儿子叫做{{son}}</h2>
    <button type="button" @click="son='girl'">改父级</button>
    <son :son-name="son"></son>
</div>

结论二:子级不能改变父级传递过来的数据,并且还会带一个报错,因为破坏了数据的统一性

<template id="temp1">
    <div class="box">
        <h3>我是儿子,我叫{{sonName}}</h3>
        <button type="button" @click="sonName='mama'">改子级</button>
    </div>
</template>

在上面的两个结论中,我们可以到数据流是一个单方向的,只能由父到子,不能由子到父

破坏数据流的单向性

在某些场合我们要做一个数据流的改变,这个我们就需要去破坏数据流的单向性,从而能够让数据互传,这个时候用下面两种方式

1、利用对象的堆栈原理

vue在进行组件传值的时候使用的是浅拷贝,如果我们要传递数据只能传递一些基础数据类型,数据传递之后是相互不影响的,如果向让两个数据之间有相互之间的影响,我们使用对象来完成

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    <div id="app">
        <h2>我是{{father}},我有一个儿子叫做{{obj.son}}</h2>
        <button type="button" @click="obj.son='girl'">改父级</button>
        <son :bbb="obj"></son>
    </div>
    <template id="temp1">
        <div class="box">
            <h3>我是儿子,我叫{{bbb.son}}</h3>
            <button type="button" @click="bbb.son='mama'">改子级</button>
        </div>
    </template>
</body>
<script src="js/vue.js"></script>
<script>
    var son = {
        template:"#temp1",
        props:["bbb"]
    }

    new Vue({
        el:"#app",
        data:{            
                father:"baba",
                obj:{
                    son:"erzi"
                }
                
            },
            components:{
                son
            }       
    })
</script>
</html>
2、通过vue官方提供的方法–自定义事件
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    <div id="app">
        <h2>我是{{father}},我有一个儿子叫做{{mySonName}}</h2>
        <!-- 在父组件当中调用子组件son,同时传值tanme:mySonName
        在父组件中监听自定义事件dadchangemyname -->
        <son :tname="mySonName" @dadchangemyname="changeSonName"></son>
    </div>
    <template id="temp1">
        <div class="box">
            <h3>我是儿子,我叫{{tname}}</h3>
            <!-- 在子组件的按钮上绑定一个点击事件,执行childChangeName,
                当该方法被执行会触发一个自定义事件dadchangemyname -->
            <button type="button" @click="childChangeName">改子级</button>
        </div>
    </template>
</body>
<script src="js/vue.js"></script>
<script>
    var son = {
        template:"#temp1",
        //接收父组件传递过来的tname属性,他的值是"son"
        props:["tname"],
        methods:{
            childChangeName(){
                //触发一个自定义事件
                this.$emit("dadchangemyname","xinerzi");
            }
        }
    }

    new Vue({
        el:"#app",
        data:{            
                father:"baba",
                mySonName:"son",
                obj:{
                    son:"erzi"
                }
                
            },
            methods:{
                changeSonName(newName){
                    this.mySonName = newName;
                }
            },
            components:{
                son
            }       
    })
</script>
</html>

在子组件的内部触发了一个自定义事件,然后这个自定义事件通过 this.$emit(“事件名”,“参数”),掉调用这个组件的时候,我们可以使用@自定义事件去监听

自定义事件

在上面的案例中,我们去破坏了数据流的单向性的时候使用了自定义事件,其实在vue开发里面,自定义事件使用是非常频繁的,我们先把刚才的自定义流程整理

子组件 $emit() 自定义事件 ----> 父组件监控这个@自定义事件 —> 父组件调用方法执行

自定义事件案例
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    <div id="app">
        <my-button @abc="aaa"></my-button>
    </div>
    <template id="temp1">
        <button type="button" @click="innerClick($event)">{{text}}</button>
    </template>
</body>

<script src="js/vue.js"></script>
<script>
    let myButton = {
        template:"#temp1",
        props:{
            text:{
                type:String,
                //props主要是用来接收传递过来的值,但是如果再props当中声明的属性没有接收到值
                //我们可以给他设置一个默认值来使用
                default: () => "按钮"
            }
        },
        methods:{
            innerClick(event){
                this.$emit("abc",event);
            }
        }
    }
    new Vue({
        el:"#app",
        data:{

        },
        components:{
            myButton
        },
        methods:{
            aaa(){
                alert("hello world");
                console.log(event);
            }
        }
    })
</script>
</html>
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值