Vue2.X学习(一)Vue组件通信

一、前言

组件是Vue.js的核心功能之一,而组件实例的作用域是相互独立的,这就意味着不同组件之间的数据无法相互引用。组件间通信就显得至关重要。

组件间的通信分为三种:

  1. 父组件向子组件通信
  2. 子组件向父组件通信
  3. 非父子组件通信
本文主要从以上三种情况简述Vue组件间的通信方法。

二、父组件向子组件通信

父组件通过属性的方式向子组件传递数据,子组件通过props接收父组件传过来的数据。

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<div id="example">
    <child msg="hello"></child>
</div>


</body>
<script src="vue.js"></script>
<script>
    Vue.component('child',{
        props:['msg'],
        template:'<span>{{msg}}</span>'
    });
    new Vue({
        el:'#example'
    })
</script>
</html>复制代码

文档结构:


注意:父组件可以通过属性的方式向子组件传递参数,但是子组件绝对不能直接修改父组件传递过来的数据(单向数据流)。因为对于父组件传递过来的引用数据,子组件若直接修改会对其他组件造成影响。

例:错误写法

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<div id="example">
    <counter :count="3"></counter>
    <counter :count="2"></counter>
</div>
</body>
<script src="vue.js"></script>
<script>
    Vue.component('counter',{
        props:['count'],
        template:'<div @click="handleClick">{{count}}</div>',
        methods:{
            handleClick: function(){
                this.count++
            }
        }
    });
    new Vue({
        el:'#example',
    })
</script>
</html>复制代码

当点击子组件时,报错!


正确的做法:我们可以在子组件接收父组件传递过来的数据时,将它复制一份(即通过子组件的data函数的实现,返回一个对象),然后修改子组件复制过来的数据。

例:正确写法:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<div id="example">
    <counter :count="3"></counter>
    <counter :count="2"></counter>
</div>
</body>
<script src="vue.js"></script>
<script>
    Vue.component('counter',{
        props:['count'],
        //通过子组件的data函数复制一份数据
        data:function(){
            //返回一个对象
            return {
                number:this.count
            }
        },
        //之后都使用复制的数据
        template:'<div @click="handleClick">{{number}}</div>',
        methods:{
            handleClick: function(){
                this.number++
            }
        }
    });
    new Vue({
        el:'#example',
    })
</script>
</html>复制代码

这时再点击子组件时不报错的。


三、子组件向父组件通信

1、在子组件上创建一个按钮,绑定一个点击事件。

2、在响应该点击事件的函数中使用$emit来触发一个自定义事件,并传递一个参数。

3、在父组件的子标签中监听该自定义事件,并添加一个响应该事件的函数。

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
    <div id="app">
        <p>总数:{{total}}</p>
        <my-component @increase="handleGetTotal" @reduce="handleGetTotal"></my-component>
    </div>
</body>
<script src="vue.js"></script>
<script>
    Vue.component('my-component',{
        //1、在子组件中创建一个按钮,给按钮绑定一个点击事件
        template:'<div><button @click="handleIncrease">+1</button>
                       <button @click="handleReduce">-1</button></div>',
        data:function(){
            return {
                counter:0
            }
        },
        methods:{
            handleIncrease:function(){
                this.counter++;
                //2、在响应该点击事件的函数中使用$emit来触发一个自定义事件,并传递一个参数
                this.$emit('increase',this.counter)
            },
            handleReduce:function(){
                this.counter--;
                this.$emit('reduce',this.counter);
            }
        }
    });
    var app = new Vue({
        el:"#app",
        data:{
            total:0
        },
        methods:{
            //3、在父组件中的子标签中监听该自定义组件并添加一个响应事件的处理函数
            handleGetTotal:function(total){
                this.total = total;
            }
        }
    })
</script>
</html>复制代码

点击+号时,总数+1,点击-号时,总数减1。


总结:无论子组件向父组件传值,还是父组件向子组件传值,他们都有一个共同点就是中间介质,子向父的中间介质是自定义事件,父向子的介质是props中的属性。

四、非父子组件传值

非父子组件的传值有两种方式:1、BUS总线    2、Vuex

1、BUS总线

思想:将事件的分发和监听单独放在一个Vue实例(Bus)中,点击事件时$emit分发一个自定义事件,并为其传递参数,然后$on去监听自定义事件,执行相应的回调函数。

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<div id="app">
    <child content="kimi"></child>
    <child content="Yang"></child>
</div>
</body>
<script src="vue.js"></script>
<script>
    //1、创建了一个名为bus的空实例   每一个Vue的实例上都有一个bus属性
    Vue.prototype.bus = new Vue();
    //定义全局组件
    Vue.component('child',{
        data:function(){
            return {
                selfContent:this.content
            }
        },
        props:{
            content:String
        },
        template:'<div @click="handleClick">{{selfContent}}</div>',
        methods:{
            handleClick:function(){
                //2、子组件去触发事件
                this.bus.$emit('change',this.selfContent)
            }
        },
        mounted:function(){
            var _this = this;
            //3、子组件去监听事件
            this.bus.$on('change',function(msg){
                _this.selfContent = msg
            })
        }

    });
    //创建一个Vue实例的app
    var app = new Vue({
        el:'#app'
    })
</script>
</html>复制代码

未点击时


点击kimi,下面的Yang变成kimi


点击Yang,上面的kimi变成Yang


2、Vuex

2.1什么是Vuex

Vuex是vue.js的状态管理器。如果没有vuex的话,当我们遇到多个视图依赖于同一状态,或者不同视图的行为需要变更同一状态,代码将会非常复杂,难以维护。所以有了Vuex,他把组件的共享状态抽取出来,以一个单例模式管理。

2.2Vuex原理

我们可以把虚线框中的内容理解为一个仓库store,Vuex实现了一个单向数据流,在全局拥有一个State存放数据,所有的共用数据都存在于state中,组件不能直接改变state中的共用数据。它需要走以下的流程:如果有一些异步操作或者是批量的同步操作,可以把这些操作放到actions里面,组件先去调用actions,actions紧接着调用mutations,mutations里面放的是一个一个同步的对state的修改,mutations再去改变state的值。组件也可以直接调用mutations来修改state中的数据。组件通过dispatch方法操作actions,组件调用mutations或者actions调用mutations时,我们都需要用一个commit的方法。


2.3简要介绍各模块在流程中的主要功能:
  • Vue Components:Vue组件。HTML页面上,负责接收用户操作等交互行为,执行dispatch方法触发对应action进行回应。
  • dispatch:操作行为触发方法,是唯一能执行action的方法。
  • actions:操作行为处理模块,由组件中的$store.dispatch('action 名称', data1)来触发。然后由commit()来触发mutation的调用 , 间接更新 state。负责处理Vue Components接收到的所有交互行为。包含同步/异步操作,支持多个同名方法,按照注册的顺序依次触发。向后台API请求的操作就在这个模块中进行,包括触发其他action以及提交mutation的操作。该模块提供了Promise的封装,以支持action的链式触发。
  • commit:状态改变提交操作方法。对mutation进行提交,是唯一能执行mutation的方法。
  • mutations:状态改变操作方法,由actions中的commit('mutation 名称')来触发。是Vuex修改state的唯一推荐方法。该方法只能进行同步操作,且方法名只能全局唯一。操作之中会有一些hook暴露出来,以进行state的监控等。
  • state:页面状态管理容器对象。集中存储Vue components中data对象的零散数据,全局唯一,以进行统一的状态管理。页面显示所需的数据从该对象中进行读取,利用Vue的细粒度数据响应机制来进行高效的状态更新。
  • getters:state对象读取方法。图中没有单独列出该模块,应该被包含在了render中,Vue Components通过该方法读取全局state对象。

后期理解源码会有更新。

参考:

Vuex框架原理与源码分析

Vue2.0学习(三)--Vue数据通信详解







  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值