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

方式主要包括
  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>
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 210,978评论 6 490
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 89,954评论 2 384
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 156,623评论 0 345
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,324评论 1 282
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,390评论 5 384
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,741评论 1 289
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,892评论 3 405
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,655评论 0 266
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,104评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,451评论 2 325
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,569评论 1 340
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,254评论 4 328
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,834评论 3 312
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,725评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,950评论 1 264
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,260评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,446评论 2 348