美文网首页让前端飞
vue组件之间数据传递和通信方式总结

vue组件之间数据传递和通信方式总结

作者: 龙旗飘扬的舰队 | 来源:发表于2019-02-15 10:36 被阅读2次
    方式主要包括
    1. ==父组件=>子组件 | 单向数据流,props==
    2. ==子组件=>父组件 | 观察者模式,即vue的自定义事件 emit 和on==
    3. ==非父子组件通信 | 中介者模式,即 中央事件总线 bus==
    4. ==父子组件通信 | 父链和子链==
    5. vuex 等状态管理库(略)

    1 父组件=>子组件,props的两个主要用法

    • 子组件把 props 的值,作为初始值(data中)保存起来,从而和父级解绑
    • 子组件需要二次处理 props 值,这时,应将其作为【计算属性】保存起来

    将prop用于子组件的data

    • 定义一个本地的 data 属性并将这个 prop 用作其初始值
    props: ['initialCounter'],
    data: function () {
      return {
        counter: this.initialCounter
      }
    }
    
    • 用 prop 的值来定义一个计算属性
    props: ['size'],
    computed: {
      normalizedSize: function () {
        return this.size.trim().toLowerCase()
      }
    }
    

    prop 是单向数据流

    • 所有的 prop 都使得其父子 prop 之间形成了一个==单向下行绑定==
      父级 prop 的更新会向下流动到子组件中,但是反过来则不行
    • ==不要在子组件中改变 prop==

    props传值:父组件=>子组件

    //静态传值
    <blog-post name="zhangkai"></blog-post>
    //动态传值
    <blog-post :name="zhangkai"></blog-post>
    <blog-post :num="42"></blog-post>
    <blog-post :ifSale="false"></blog-post>
    <blog-post :list="[1,2,3]"></blog-post>
    <blog-post :person="{name:'zhangkai',age:19}"></blog-post>
    <blog-post :person="person.name"></blog-post>
    //不带参数的 v-bind,post={id:1,title:"title"}
    <blog-post v-bind="post"></blog-post>
    //等价于
    <blog-post
      v-bind:id="post.id"
      v-bind:title="post.title"
    ></blog-post>
    

    prop检验

    详细章节见

    • <a href="https://blog.csdn.net/qq_38310712/article/details/86544800">vue prop传值default属性如何使用</a>
    • <a href="https://blog.csdn.net/qq_38310712/article/details/86544766">vue prop传值类型检验</a>

    2 子组件=>父组件

    • 原理:【观察者模式】 + 【vue自定义事件】
    • 子组件用 $emit 方法触发事件,第一个参数是自定义事件名,后续参数都是要传递的数据
    • 父组件用 v-on 定义的方法监听子组件的事件
    • 注意,add 和 reduce 是两个自定义事件,用来监听子组件的 $emit 事件
    //vue模板
    <template>
      <div class="wrap">
        <!--注意,add 和 reduce 是两个自定义事件,用来监听子组件的 $emit 事件-->
        <MyComponent v-on:add="handleTotal" v-on:reduce="handleTotal"/>
        {{total}}
      </div>
    </template>
    
    //vue script
    var MyComponent = {
      template:
        "<div>\
        <button @click='handleAdd'>+1</button>\
        <button @click='handleReduce'>-1</button>\
        </div>",
      data() {
        return {
          sum: 0
        };
      },
      methods: {
        handleAdd() {
          this.sum++;
          this.$emit("add", this.sum);
        },
        handleReduce() {
          this.sum--;
          this.$emit("reduce", this.sum);
        }
      }
    };
    export default {
      components: {
        MyComponent
      },
      data() {
        return {
          total: 0
        };
      },
      methods: {
        handleTotal(total) {
          this.total = total;
        }
      }
    };
    

    3 非父子组件通信 bus

    • 使用【中央事件总线 bus】
    • bus 其实就是一个空的Vue实例,充当中介者的作用
    • bus 通过 emit 发出信息,通过on 来监听获取,这两个方法的第一个参数必需是同一个消息名称
    • bus 对象中,可以添加 data、methods、computed 等信息
    • 协同开发中,向 bus 对象添加一些共享的信息,是非常有用的
    • 比如,token、用户昵称、邮箱信息等,只需初始化时让 bus获取一次,所有组件就都可以使用了
     //vue模板
    <template>
      <div class="wrap">
        <componentA/>
        <br>
        {{msg}}
      </div>
    </template>
    <script>
    
    //vue script
    import Vue from "vue";
    const bus = new Vue({
      data: {
        name: "",
        passport: ""
      }
    }); //一个空的Vue实例,做为【中央事件总线】
    const componentA = {
      template: "<button @click='handleEvent'>传递事件</button>",
      methods: {
        handleEvent() {
          bus.name = "gs";
          bus.$emit("on-msg", "componentA content");
        }
      }
    };
    export default {
      components: {
        componentA
      },
      data() {
        return {
          msg: ""
        };
      },
      mounted() {
        const that = this;
        bus.$on("on-msg", msg => {
          console.log(bus.name);
          that.msg = msg;
        });
      }
    };
    

    4 父子组件通信 父链和子链

    • 在子组件中,this.$parent 可以访问父组件实例
    • 在父组件中,this.children 可以访问子组件实例
    • 该方法可以向上向上无限递归,直到遇见根组件和叶子组件
    • 给子组件添加一个 ref 属性,可以帮助父组件快速找到子组件(调用方法 this.$refs.comA.msg,实际上 react 也有这样的方法),但不建议使用 ref
    • 注意,在 mounted阶段时 this.$refs 才会绑定,在 created 阶段尚未绑定
    • 另外,$refs 不是一个响性式的属性
    //注意,this.$children 一般为数组
    this.$children[0].age
    //使用 ref 属性,可以更容易找到子组件
    //<componentA ref="ageCom"/>
    this.$refs.ageCom.age;
    
    注意事项:

    不要在子组件中修改 props 的值

    • props 是对象或数组时,由于是引用类型,在子组件中修改,会影响到父组件

    重要!Prop 的大小写 (camelCase vs kebab-case)

    • 声明一个vue组件,如果使用驼峰命名法,在使用时,需要转换成短横线分隔命名
    • 因为如果不转,html解析时,会将大写字母小写化,这样变量即为undefined
    • 如下,props 一般是一个数组,也可以是一个对象(对象类型检测)
    //声明一个组件
    Vue.component('blog-post', {
      // 在 JavaScript 中是 camelCase 的
      props: ['postTitle'],
      template: '<h3>{{ postTitle }}</h3>'
    })
    //使用组件
    <blog-post post-title="hello!"></blog-post>
    

    相关文章

      网友评论

        本文标题:vue组件之间数据传递和通信方式总结

        本文链接:https://www.haomeiwen.com/subject/ophpeqtx.html