Vue父子组件间的数据交互原理

一、环境准备

  该项目需要使用vue,对于Vue的安装方式,这里选择采用npm 安装vue。然后在html中引入并使用vue。

  • 首先在新建文件夹下进行npm初始化
npm init

  npm是包管理工具,初始化时会在当前文件夹下产生一个package.json文件,该文件用来描述当前项目的依赖。
在这里插入图片描述
  可以顺序输入当前项目的名字(不能包含大写字母、中文、特殊字符)、项目的版本号、项目描述、项目入口点、测试命令、git仓库地址、关键字、作者、协议(可写MIT,开源协议)。最后回车之后会根据刚刚输入的内容生成相应的package.json文件。
在这里插入图片描述
在这里插入图片描述
注意该json文件内不能写注释

  • 其次,使用npm安装vue,默认下载最新版本
npm install vue

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
  如果删除了node_modules文件夹,只需要执行npm install即可依据package.json文件中的dependencies属性将项目所依赖的模块重新安装。通常在将项目打包上传到git仓库时,可以选择在.gitignore文件中将node_modules文件夹下的文件忽略上传,以提高上传和下载的速度。只要package.json文件存在,其他人就可以在本地轻易的把依赖项安装回来,持续开发。

  • 最终,在html文件中引入vue
<script src="./node_modules/vue/dist/vue.js"></script>

二、数据交互

1. 父传子

  父组件通过props将属性值传递给子组件。

  • 子组件在props中声明一个属性(变量),用于接收父组件传过来的值
  • 父组件给子组件的行间属性绑定数据,该数据属于父组件
    实例:
<!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">
    <title>父子组件间的数据交互</title>
</head>
<body>
    <div id="app">
        父亲:儿子本月生活费{{money}}<child :my-Money='money'></child>
    </div>
</body>
<script src="./node_modules/vue/dist/vue.js"></script>
<script>
    let vm = new Vue({
        el:'#app',
        data:{
            money:1500
        },
        components:{
            child:{
                props:['myMoney'],
                template:`<div>儿子:我收到{{myMoney}}元生活费</div>`
            }
        }

    });
</script>
</html>

在这里插入图片描述
  上述实例中,在子组件child中,props属性中定义的是myMoney属性。但是由于HTML特性是不区分大小写,所以父组件在传递数据时,将驼峰法转换成了短横线隔开。myMoney转换成my-money。

2. 子传父

  注意父子组件通过props属性传递值,但props是单向绑定的,父组件的属性变化时,将变化传导给子组件,但是反过来不会。这是为了防止子组件无意间修改了父组件的状态,来避免应用的数据流变得难以理解。 子组件要给父组件传递消息可以通过$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">
    <title>父子组件间的数据交互</title>
</head>
<body>
    <div id="app">
        父亲:儿子本月生活费{{money}}<child :my-Money='money'></child>
    </div>
</body>
<script src="./node_modules/vue/dist/vue.js"></script>
<script>
    let vm = new Vue({
        el:'#app',
        data:{
            money:1500
        },
        components:{
            child:{
                props:['myMoney'],
                template:`<div>儿子:我收到{{myMoney}}元生活费  <button @click="myMoney=2000">生活费不够</button></div>`
            }
        }

    });
</script>
</html>

在这里插入图片描述
  在上述实例中,父组件将自身变量money的值传递给子组件child的myMoney属性,child组件更改了传递过来的值,将myMoney的值更改为2000,自身视图跟着刷新。但是父组件并没有受到子组件这一操作的影响,父组件的money值维持不变,视图没有更新。同时,应当注意到控制台会产生警告,表示子组件这一操作并没有影响到父组件,操作不合法。
  由于父子组件之间的单向数据流,子组件不能像父组件一样通过属性去影响对方。正确的做法应当是,子组件不直接更改父组件传递过来的值,而是通知父组件需要更改值,由父组件更改,才能通过单向数据流同时刷新父子组件的视图。具体实践如下:

  • 首先在父组件中给子组件绑定上自定义事件,同时定义触发自定义事件时会执行的事件处理方法。
  • 在子组件上触发自定义事件,调用父组件的方法,并给父组件的方法传递参数。
    实例:
<!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">
    <title>父子组件间的数据交互</title>
</head>
<body>
    <div id="app">
        父亲:儿子本月生活费{{money}}<!-- v-on:parent-child意为给child组件绑定parent-child事件,其值为方法名。该事件被触发时会调用doSomething方法 -->
        <child :my-Money='money' v-on:parent-child="doSomething"></child>
    </div>
</body>
<script src="./node_modules/vue/dist/vue.js"></script>
<script>
    let vm = new Vue({
        el:'#app',
        data:{
            money:1500
        },
        methods:{
            doSomething(val){
                console.log(val);
                //父组件接收到参数后,更新自身数据
                this.money=val;
            }
        },
        components:{
            child:{
                props:['myMoney'],
                methods:{
                    getMessage(){
                        //子组件触发自身绑定的parent-child事件,并给即将调用的父组件方法doSomething传递参数
                        this.$emit('parent-child',2000);
                    }
                },
                template:`<div>儿子:我收到{{myMoney}}元生活费 <button @click="getMessage">生活费不够</button></div>`
            }
        }

    });
</script>
</html>

在这里插入图片描述
实际上子传父采用的方式就是应用了发布-订阅模式。有兴趣可以了解一下发布-订阅模式的原理,主要与this.$on() 以及this.$emit()有关。
== 注意:在js中,对象和数组都是引用类型,指向同一个内存空间,如果props是一个对象或者数组,在子组件内部改变它就会影响父组件的状态。==

发布了45 篇原创文章 · 获赞 15 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/baidu_41327283/article/details/104052910