14 种组件通讯
1. props
这个就是父传子属性, props 值可以是一个数组或对象
// 数组:不建议使用 props:[] // 对象 props:{ inpVal:{ type:Number, //传入值限定类型 // type 值可为String,Number,Boolean,Array,Object,Date,Function,Symbol // type 还可以是一个自定义的构造函数,并且通过 instanceof 来进行检查确认 required: true, //是否必传 default:200, //默认值,对象或数组默认值必须从一个工厂函数获取如 default:()=>[] validator:(value) { // 这个值必须匹配下列字符串中的一个 return ['success', 'warning', 'danger'].indexOf(value) !== -1 } } }
2. $emit
这个也非常常见, 触发父组件的自定义事件, 其实就是父传子的方法
1 // 父组件 2 <home @title="title"> 3 // 子组件 4 this.$emit('title',[{title:'这是title'}])
3. vuex
vuex 是一个状态管理器,
一个独立的插件, 适合数据共享多的项目里面, 因为如果只是简单的通讯, 使用起来会比较重
1 state:定义存贮数据的仓库 ,可通过this.$store.state 或mapState访问 2 getter:获取 store 值,可认为是 store 的计算属性,可通过this.$store.getter 或 mapGetters访问 4 mutation:同步改变 store 值,为什么会设计成同步,因为mutation是直接改变 store 值, 5 vue 对操作进行了记录,如果是异步无法追踪改变.可通过mapMutations调用 6 action:异步调用函数执行mutation,进而改变 store 值,可通过 this.$dispatch或mapActions 访问 8 modules:模块,如果状态过多,可以拆分成模块,最后在入口通过...解构引入
4. $attrs 和 $listeners
2.4.0 新增 这两个是不常用的属性, 但是高级用法很常见;
$attrs 场景: 如果父传子有很多值, 那么在子组件需要定义多个
props解决: attrs 获取子传父中未在props定义的值(在 $attrs里面只会有props没有注册的属性) -> (class 和 style 除外)
1 // 父组件 2 <home title="这是标题" width="80" height="80" imgUrl="imgUrl"/> 3 4 // 子组件 5 mounted() { 6 console.log(this.$attrs) //{title: "这是标题", width: "80", height: "80", imgUrl: "imgUrl"} 7 },
1 props: { 2 width: { // 父组件的width 在子组件props中注册后, 那么在$attrs上取不到 3 type: String, 4 default: '' 5 } 6 }, 7 mounted() { 8 console.log(this.$attrs) //{title: "这是标题", height: "80", imgUrl: "imgUrl"} 9 },
$listeners 场景: 子组件需要调用父组件的方法解决: 父组件的方法可以通过 v-on="listeners" 传入内部组件 ----- 在创建更高层次的组件时非常有用
1 // 父组件 2 <home @change="change"/> 3 4 // 子组件 5 mounted() { 6 console.log(this.$listeners) //即可拿到 change 事件 7 }
$inheritAttrs
组件内未被注册的属性将作为普通html元素属性被渲染
1 // 父组件 2 <home title="这是标题" width="80" height="80" imgUrl="imgUrl"/> 3 4 // 子组件 5 mounted() { 6 console.log(this.$attrs) //{title: "这是标题", width: "80", height: "80", imgUrl: "imgUrl"} 7 }, 8 9 inheritAttrs默认值为 true,也就是父组件上的属性会显示到根组件上 10 如果设置为 false 就会隐藏
5. provide 和 inject
2.2.0 版本新增
使用场景: 以允许一个祖先组件向其所有子孙后代注入一个依赖, 不论组件层次有多深, 并在起上下游关系成立的时间里始终生效。
provide :一个对象或返回一个对象的函数
inject : 一个字符串数组,或一个对象,对象的key是本地的绑定名
1 <template> // 父组件 2 <div id="app"> 3 </div> 4 </template> 5 <script> 6 export default { 7 data () { 8 return { 9 datas: [ 10 { 11 id: 1, 12 label: '产品一' 13 }, 14 { 15 id: 1, 16 label: '产品二' 17 }, 18 { 19 id: 1, 20 label: '产品三' 21 } 22 ] 23 } 24 }, 25 provide { 26 return { 27 datas: this.datas 28 } 29 } 30 } 31 </script>
<template> // 后代组件 <div> <ul> <li v-for="(item, index) in datas" :key="index"> {{ item.label }} </li> </ul> </div> </template> <script> export default { inject: ['datas'] } </script>
注意: provide 和 inject 绑定并不是可响应的。这是刻意为之的。然而,如果你传入了一个监听的对象,那么其对象的属性还是可响应的。
响应式示例:
父组件中提供 provide() { return { map_nodeObj: { map_node: this.obj } // 提示:provide 和 inject 绑定并不是可响应的。这是刻意为之的。然而,如果你传入了一个可监听的对象,那么其对象的属性还是可响应的。 } }, 子组件中引入 inject: { map_nodeObj: { default: () => { return {map_node: '0'} } } }, 使用: this.map_nodeObj.map_node // 运行顺序 data provide created // 在这个阶段$el还未生成,在这先处理privide的逻辑,子孙组件才可以取到inject的值 mounted ...
6. $parent 和 $children
$parent:指代的父组件, 返回的是一个组件集合
用法:this.$parent (如果当前组件没有父组件,那么返回当前组件)
$children:指代的子组件,返回的是一个组件集合
用法: this.$children (如果你能清楚的知道子组件的顺序,可以使用下标来表示)
注意:(1) 组件只能有一个根节点
(2) 可以在子组件中使用this.$parent.属性值, 或者函数
(3) 在父组件中可以使用this.$children[i].属性
(4) 需要注意this的指向
7. ref 和 $refs
ref 有三种用法:
(1) ref加在普通的元素上,用this.$refs.name 获取到的是dom元素
(2) ref 加在子组件上, 用this.$refs.name 获取到的是组件实例,可以使用组件的所有方法
ref 和 v-for 在一起的情况
8. $root
$root 设置全局属性
let app = new Vue({ el: '#app', // 全局数据,在其他页面或者组建可改变 data: function () { return { s: '' } }, router, store, template: '<router-view></router-view>' }) // a.vue this.$root.s = '设置了s属性' // b.vue console.log(this.$root.s) //设置了s属性
9. .sync
从2.3.0起重新引入的 .sync 修饰符,.sync被作为一个编译时的语法糖,它会被扩展为一个自动更新父组件属性的 v-on 监听器
// 父组件 <comp :foo.sync="bar"></comp> // 编译时会被扩展为: <comp :foo="bar" @update:foo="val => bar = val"></comp> //子组件 //当子组件需要更新 foo 的值时,它需要显式地触发一个更新事件: // 所以子组件可以通过$emit 触发 update 方法改变 this.$emit('update:foo', newValue)
10. v-slot 插槽
2.6.0新增
(1) 匿名插槽
(2) 具名插槽
(3) 作用域插槽