组件通信

2018-09-04  本文已影响0人  Cissy_fba3

1.props和emit 父子间
2.provide,inject 同级或跨级
3.vuex 同级或跨级

props和emit
image

父传子用props

Vue.component('blog-post', {
  props: ['title','key'],
  template: '<h3>{{ title }}</h3>'
})//子组件

new Vue({
  el: '#blog-post-demo',
  data: {
    posts: [
      { id: 1, title: 'My journey with Vue' },
      { id: 2, title: 'Blogging with Vue' },
      { id: 3, title: 'Why Vue is so fun' }
    ]
  }
})//根元素(父)

//html
<blog-post 
v-for="post in posts" 
v-bind:key="post.id"
v-bind:title="post.title"
></blog-post>

注意:在props中使用驼峰命名法时记得在html中换成连字符命名法

子传父用$emit()

在子组件中用 $emit()并传入事件的名字,来向父级组件触发一个事件
然后用 v-on 在父元素监听这个事件,就像监听一个原生 DOM 事件一样。

Vue.component('blog-post', {
  props: ['post'],
  template: `
    <div class="blog-post">
      <h3>{{ post.title }}</h3>
      <button v-on:click="$emit('enlarge-text')">
        Enlarge text
      </button>
      <div v-html="post.content"></div>
    </div>
  `
})
new Vue({
  el: '#blog-posts-events-demo',
  data: {
    posts: [/* ... */],
    postFontSize: 1
  }
})

//html
<blog-post
  ...
  v-on:enlarge-text="postFontSize += 0.1"
></blog-post>

emit可以发送数据,v-on监听的事件可以接收这个数据作为参数,通过 $event 访问到被抛出的这个值

组件中的button:
<button v-on:click="$emit('enlarge-text', 0.1)">
       Enlarge text
</button>

//html
<blog-post
  ...
  v-on:enlarge-text="postFontSize += $event"
></blog-post>

如果这个事件处理函数是一个方法,那么这个值将会作为第一个参数传入这个方法

<blog-post
  ...
  v-on:enlarge-text="onEnlargeText"
></blog-post>

//
methods: {
  onEnlargeText: function (enlargeAmount) {
    this.postFontSize += enlargeAmount
  }
}

注意:用$emit发送事件时最好也不要用驼峰命名法,用连字符法。

provide inject

注意:provide提供的数据是非响应式的

// 父级组件提供 'foo'
var Provider = {
  provide: {
    foo: 'bar'
  },
  // ...
}

// 子组件注入 'foo'
var Child = {
  inject: ['foo'],
  created () {
    console.log(this.foo) // => "bar"
  }
  // ...
}

要想变成响应式,在根组件中注入provide

// 根组件提供将自身提供给后代组件
export default {
  provide () {
    return {
      app: this
    }
  },
  data () {
    return {
      text: 'bar'
    }
  }
}

// 后代组件注入 'app'
<template>
    <div>{{this.app.text}}</div>
</template>
<script>
  export default {
    inject: ['app'],
    created() {
      this.app.text = 'baz' // 在模板中,显示 'baz'
    }
  }
</script>   
//出处:
//作者:格子熊
//链接:https://juejin.im/post/6844903989935341581
//来源:掘金
//著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

vue3中使用provide和inject——响应式

//根组件 app.vue中
setup(){
    const width=document.documentElement.clientWidth
    const asideVisible= ref(width<500?false:true)
    provide('abc',asideVisible)
  }
//子组件1中使用
setup(){
        const width=document.documentElement.clientWidth
        const asideVisible=inject<Ref<boolean>>('abc')
        router.afterEach(()=>{
            // console.log('路由切换了')
            if(width>500){
                asideVisible.value=true
                return
            }
            asideVisible.value=false
        })
        return{ asideVisible}
    }
//子组件2中使用
setup(){
        const asideVisible=inject<Ref<boolean>>('abc')
        const toggleVisible=()=>{
            //console.log(asideVisible.value)
            asideVisible.value=!asideVisible.value
        }
        return{ toggleVisible}
    }

provide/inject 对比vuex:Vuex 中的全局状态的每次修改是可以追踪回溯的,而 provide/inject 中变量的修改是无法控制的,换句话说,你不知道是哪个组件修改了这个全局状态。所以: provide/inject 最好用来编写组件(造轮子),其它时候特别是多人合作时都用vuex

上一篇 下一篇

猜你喜欢

热点阅读