vue组件通信的7种方案

2019-12-8 10:01:40 419 views

vue组件通信的7种方案

props与$emit

父传子通过props,子传父通过emit,单向数据流(可以结合.sync形成双向数据流)

案例

// 父 
<template>
  <div>
    <child @changeText="change" :text="text"></child>
  </div>
</template>

<script>
import child from "./child";
export default {
  components: {
    child
  },
  data() {
    return {
      text: "hello"
    };
  },
  methods: {
    change(data) {
      this.text = data;
    }
  }
};
</script>

<style scoped></style> 
 // 子  
<template>
    <div>
        我来自子组件{{ text }}
        <button @click="change">修改</button>
    </div>
</template>

<script>
export default {
  props: {
    text: {
      type: String,
      default: ''
    }
  },
  methods: {
    change () {
      this.$emit('changeText', 'child')
    }
  }
}
</script>

<style scoped></style>

provide/inject

https://cn.vuejs.org/v2/api/index.html#provide-inject

提示:provide 和 inject 绑定并不是可响应的。这是刻意为之的。然而,如果你传入了一个可监听的对象,那么其对象的属性还是可响应的。

案例

//  父  
<template>
    <div>
        <button @click="change">父修改</button>
        <child></child>
    </div>
</template>

<script>
import child from './child'
export default {
  components: {
    child
  },
  data () {
    return {
      arr: [
        { name: 'mike' },
        { name: 'john' },
        { name: 'sqe' },
        { name: 'dg' }
      ],
      text: 'name'
    }
  },
  provide: function () {
    return {
      arr: this.arr,
      text: this.text
    }
  },
  methods: {
    change () {
      this.arr.splice(0, 1, { name: 'mike' })
    }
  }
}
</script>

<style scoped></style>
 // 子 
 <template>
    <div>
        <div v-for="item in arr" :key="item.id">{{ item.name }}</div>
        {{ text }}
        <button @click="change">修改</button>
    </div>
</template>

<script>
export default {
  inject: ['arr', 'text'],
  methods: {
    change () {
      this.arr.splice(0, 1, { name: 'michale jackson' })
    }
  }
}
</script>

<style scoped></style>

在 2.5.0+ 的注入可以通过设置默认值使其变成可选项:

 const Child = {
  inject: {
    foo: { default: 'foo' }
  }
}

如果它需要从一个不同名字的属性注入,则使用 from 来表示其源属性:

 const Child = {
  inject: {
    foo: {
      from: 'bar',
      default: 'foo'
    }
  }
} 

与 prop 的默认值类似,你需要对非原始值使用一个工厂方法:

 const Child = {
  inject: {
    foo: {
      from: 'bar',
      default: () => [1, 2, 3]
    }
  }
} 

eventBus

原理:运用了vue实例上的$emit和$on事件来监听和触发对应的通信

新建一个 eventBus.js文件

 import Vue from 'vue';
export default new Vue(); 

组件中触发事件

 Bus.$emit("getUserName", data.username); 

组件中监听事件

 Bus.$on("getUserName", data => {
      this.userName = data;
    }); 

vuex

https://vuex.vuejs.org/zh/guide/state.html

细节不再阐述,文档讲的很详细了,这里列出一些技巧和需要注意的点。

 import Vuex from 'vuex'
const store = new Vuex.Store({ ...options }) 

需要注意的点

1.mutations是同步的,actions是异步的

2.项目较大时,state,getters,mutations和actions分文件,或者按模块来分。

3. 善于利用辅助函数mapState,mapGetters,mapActions,mapMutations 可以减少代码冗余

https://vuex.vuejs.org/zh/api/#mapstate

$attrs/$listeners

https://cn.vuejs.org/v2/api/#vm-attrs

$attrs

vm.$attrs{ [key: string]: string }

概括:$attrs就是接收父组件传值在子组件没有定义的prop属性,可以使用$attr向子组件或者更深层次的子组件传值

这里经常会结合inheritAttrs属性,该属性主要控制组件上的属性

inheritAttrs
inheritAttrs

inheritAttrs 默认为true,将会带上如上属性,设置为false将去除

$listeners

vm.$listeners { [key: string]: Function | Array<Function> }

包含了父作用域中的 (不含 .native 修饰器的) v-on 事件监听器。它可以通过 v-on="$listeners" 传入内部组件——在创建更高层次的组件时非常有用。

案例

// 父  
<template>
    <div>
        <button @click="change">父修改</button>
        <child :arr="arr" :text="text" :name="name" @change="change"></child>
    </div>
</template>

<script>
import child from './child'
export default {
  components: {
    child
  },
  data () {
    return {
      arr: [
        { name: 'mike' },
        { name: 'john' },
        { name: 'sqe' },
        { name: 'dg' }
      ],
      text: Math.floor(Math.random() * 10).toFixed(0),
      name: 'mike'
    }
  },
  created () {
    console.log(this.$data, 'father')
  },
  methods: {
    change () {
      console.log('修改')
      this.text = Math.floor(Math.random() * 10).toFixed(0)
    }
  }
}
</script>

<style scoped></style>
 // 子 
<template>
    <div>
        child {{ $attrs.text }}{{ $attrs.name }}
        <button @click="handleChange">child修改</button>
        <demo v-bind="$attrs" v-on="$listeners"></demo>
    </div>
</template>

<script>
import demo from './demo'
export default {
  components: {
    demo
  },
  props: ['arr'],
  data () {
    return {}
  },
  inheritAttrs: false,
  mounted () {
    console.log(this.$attrs, this.$listeners, 'child')
  },
  methods: {
    handleChange () {
      this.$listeners.change()
    }
  }
}
</script>

<style scoped></style>
 // 孙子 
 <template>
    <div>
        grandChild {{ $attrs.text }}{{ $attrs.name }}
        <button @click="handleChange">grandchild修改</button>
    </div>
</template>

<script>
export default {
  created () {
    console.log(this.$attrs, this.$listeners, 'grand')
  },
  methods: {
    handleChange () {
      this.$listeners.change()
    }
  }
}
</script>

<style scoped></style>
输出的数据
输出数据

 $parent/$children

vm.$parent

父实例,如果当前实例有的话

vm.$children

Array<Vue instance>

案例

// 父 
<template>
  <div class="home">
    {{father}}
    <Child/>
  </div>
</template>

<script>
import Child from '@/components/Child.vue'

export default {
  name: 'home',
  components: {
    Child
  },
  data () {
    return {
      father: 'father'
    }
  },
  mounted () {
    console.log(this.$children[0].child)  // child 
  }
}
</script>
 // 子  
<template>
  <div>{{child}}</div>
</template>

<script>
export default {
  data () {
    return {
      child: 'child'
    }
  },
  created () {
    console.log(this.$parent.father) // father
  }
}
</script>

<style scoped>
</style>

当前实例的直接子组件。需要注意 $children 并不保证顺序,也不是响应式的。如果你发现自己正在尝试使用 $children 来进行数据绑定,考虑使用一个数组配合 v-for 来生成子组件,并且使用 Array 作为真正的来源。

localStorage/sessionStorage/cookie

总结

(包含层层递进情况)

归纳总结
归纳

转载请标明出处:

https://www.suanliutudousi.com

0

No Comments

发表评论

电子邮件地址不会被公开。 必填项已用*标注

分享到微信朋友圈

打开微信,点击底部的“发现”,
使用“扫一扫”即可将网页分享至朋友圈。