Vue 组件间传参最佳实践

栏目: 编程语言 · 发布时间: 5年前

内容简介:1.1.1通过绑定 props 将父组件的数据关联到子组件,并修饰 .sync 或者用 v-model 同步来自子组件的数据变化1.1.2绑定 listener 事件监听器,当子组件状态或者数据发生变化时,触发事件并将数据传递到父组件$listeners 和 $attrs 两者表面层都是一个意思,$attrs 是向下传递数据,$listeners 是向下传递方法,通过手动去调用 $listeners 对象里的方法,原理就是 $emit 监听事件,$listeners 也可以看成一个包裹监听事件的一个对象。

1.父子组件间的数据传递

1.1从父组件获取子组件的数据

1.1.1通过绑定 props 将父组件的数据关联到子组件,并修饰 .sync 或者用 v-model 同步来自子组件的数据变化

//使用.sync :

//父组件
<template>
  <div class="home">
   <my-dialog :show.sync="valueChild"/>
   <button @click="changeValue">toggle</button>
  </div>
</template>
<script>
import myDialog from '@/components/myDialog.vue'

export default {
  name: 'home',
  components: {
    myDialog
  },
  data(){
    return{
       valueChild:true,
    }
  },
   methods:{
      changeValue(){
          this.valueChild = !this.valueChild
      }
    }
}
</script>

//子组件
<template>
  <div>
    <div>myDialog</div>
    <div v-if="show">
      <p>默认初始值是{{show}},所以是显示的</p>
      <button @click.stop="closeDiv">关闭</button>
    </div>
  </div>
</template>
<script>
export default {
  props:['show'],
  methods:{
    closeDiv(){
      this.$emit('update:show',false)
    }
  }
}
</script>
// v-model :

//父组件:
<template>
  <div class="home">
    <myDialog v-model="show"></myDialog>
    <button @click="toggle">Toggle</button>
  </div>
</template>
<script>
  import myDialog from '@/components/myDialog.vue'

  export default {
    name: 'home',
    components: {
      myDialog
    },
    data() {
      return {
        show: false
      }
    },
    methods: {
      toggle() {
        this.show = !this.show
      }
    }
  }
</script>

//子组件:
<template>
  <div>
    <div v-if="value" class="modal">
      {{value}}
      <button @click="close">x</button>
    </div>
  </div>
</template>
<script>
  export default {
    props: ['value'],
    methods: {
      close() {
        this.$emit('input', false)
      }
    }
  }
</script>

1.1.2绑定 listener 事件监听器,当子组件状态或者数据发生变化时,触发事件并将数据传递到父组件

$listeners 和 $attrs 两者表面层都是一个意思,$attrs 是向下传递数据,$listeners 是向下传递方法,通过手动去调用 $listeners 对象里的方法,原理就是 $emit 监听事件,$listeners 也可以看成一个包裹监听事件的一个对象。

// 父组件:
<template>
  <div class="home">
    {{firstMsg}}
    <myDialog v-on:changeData="changeData" v-on:another='another'></myDialog>
  </div>
</template>
<script>
  import myDialog from '@/components/myDialog.vue'

  export default {
    name: 'home',
    components: {
      myDialog
    },
    data() {
      return {
        firstMsg: '父组件'
      }
    },
    methods: {
      changeData(params) {
        this.firstMsg = params
      },
      another() {
        alert(2)
      }
    }
  }
</script>

//子组件:
<template>
  <div>
    <p @click="$emit('another')">子组件</p>
    <other v-on="$listeners"/>
  </div>
</template>
<script>
  import other from '@/components/other.vue'
  export default {
    props: ['value'],
    components:{
      other
    },
    created () {
     // eslint-disable-next-line no-console
     console.log(this.$listeners)
   }
  }
</script>

//孙子组件:
<template>
  <div>
    <p @click='$listeners.changeData("change")'>孙子组件</p>
  </div>
</template>

<script>
export default {
  name: 'demo',
  created () {
      // eslint-disable-next-line no-console
      console.log(this.$listeners)
  },
}
</script>

1.2从子组件获取父组件的数据

1.2.1 获取 props 或者 $attrs 传下来的数据

//父组件:
<template>
  <div class="home">
    <myDialog :foo="foo" :boo="boo" :coo="coo" :doo="doo" title="前端工匠"></myDialog>
  </div>
</template>
<script>
  import myDialog from '@/components/myDialog.vue'

  export default {
    name: 'home',
    components: {
      myDialog
    },
    data() {
      return {
        foo: "Javascript",
        boo: "Html",
        coo: "CSS",
        doo: "Vue"
      }
    },
    methods: {
      changeData(params) {
        this.firstMsg = params
      },
      another() {
        alert(2)
      }
    }
  }
</script>

//子组件:
<template>
  <div>
    <p>foo:{{foo}}</p>
    <p>子组件的$attrs: {{ $attrs }}</p>
    <other v-bind="$attrs" />
  </div>
</template>
<script>
  import other from '@/components/other.vue'
  export default {
    components: {
      other
    },
    inheritAttrs: false, // 可以关闭自动挂载到组件根元素上的没有在props声明的属性
    props: {
      foo: String // foo作为props属性绑定
    },
    created() {
      // eslint-disable-next-line no-console
      console.log(this.$attrs);
    }
  }
</script>

//孙子组件:
<template>
  <div>
    <p>boo: {{ boo }}</p>
    <p>孙子:{{$attrs}}</p>
  </div>
</template>

<script>
  export default {
    name: 'demo',
    inheritAttrs: false,
    props: {
      boo: String
    },
    created() {
      // eslint-disable-next-line no-console
      console.log(this.$attrs);
    },
  }
</script>

2.兄弟组件间的数据传递

处于兄弟关系的组件

2.1通过 EventBus 或者 $root 去注册事件,由兄弟组件去监听事件传递过来的数据变化

2.2 在 Vuex 存放状态,并在两个组件中都监听状态变化

2.3 在父组件上绑定状态,并通过 v-model 或者 .sync 绑定到两个兄弟组件中去,以同步数据变化

3.祖孙组件间的数据传递

3.1孙组件被直接写在了祖先组件的 template 内

在 Vue 中,处于祖孙关系的组件,而且孙组件被直接写在了祖先组件的 template 内,要从祖先组件获取孙组件的数据,有以下几种方式:

3.1.1可以在模板上给孙组件绑定 ref 并通过 $refs 调用孙组件的方法获取数据

//父组件
<template>
  <div class="home">
    {{title}}
    {{text}}
    <myDialog ref="comA"></myDialog>
  </div>
</template>
<script>
  import myDialog from '@/components/myDialog.vue'

  export default {
    name: 'home',
    components: {
      myDialog
    },
    data() {
      return {
        title:'',
        text:''
      }
    },
    computed: {
    },
    mounted() {
      const comA = this.$refs.comA;
      // console.log(comA.title); // Vue.js
      this.title = comA.title
      this.text = comA.text
      comA.sayHello(); // 弹窗
    },
    methods: {}
  }
</script>

//子组件:
<template>
  <div>
    <div v-if="show">sayHello</div>
    <other ref="comB" />
  </div>
</template>
<script>
  import other from '@/components/other.vue'
  export default {
    components: {
      other
    },
    data() {
      return {
        title: 'Vue.js',
        show: false,
        text:''
      }
    },
    created() {

    },
    mounted() {
      const comB = this.$refs.comB;
      this.text = comB.text
    },
    methods: {
      sayHello() {
        this.show = true
        // window.alert('Hello');
      }
    }
  }
</script>

//孙子组件:
<template>
  <div>
  </div>
</template>

<script>
  export default {
    name: 'demo',
    data(){
      return{
        text:'c'
      }
    },
    created() {
    },
  }
</script>

3.1.2 可以在模板上给孙组件绑定 listener 获取孙组件传过来的数据

3.1.3 可以在模板上给孙组件绑定 v-model 或者 .sync 同步孙组件的数据

3.2孙组件不在祖先组件的 template 内,要从祖先组件获取孙组件的数据

3.2.1先在子组件上绑定 v-model 或者 .sync,接着再在子组件的模板上通过 v-model 或者 .sync 绑定孙组件,以同步孙组件的数据

3.2.2现在孙组件上绑定 listener,再给子组件绑定 listener,数据由事件层层上传给祖先组件

3.3孙组件在祖先组件的 template 内,要从孙组件获取祖先组件的数据

3.3.1直接在祖先组件的 template 中通过 v-bind 将数据传递到孙组件中,孙组件通过 props 或者 $attrs 进行接收

3.4孙组件不在祖先组件的 template 内,要从孙组件获取祖先组件的数据

3.4.1先在子组件上 v-bind 绑定数据,接着再在子组件上通过 v-bind 绑定孙组件,数据层层向下传递

3.4.2孙组件在 EventBus 中注册事件,监听来自祖先组件触发的事件数据

3.4.3祖先组件将数据挂到 Vuex 中,再由孙组件从 Vuex 中去获取数据


以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

网络心理学

网络心理学

玛丽•艾肯 (Mary Aiken) / 中信出版社 / 2018-8-1 / CNY 58.00

《五十度灰》如何利用恋物心理,成为全球仅次于《圣经》的畅销读物? 为什么相对于亲朋好友,你更愿意向网络陌生人敞开心扉? 上网时总感觉时间飞逝,原来是网络的时间扭曲效应? 网络游戏中埋伏了哪些“上瘾”机关,暗中操控着你的行为? 为什么科技越发达,我们就越怕死? ...... 网络空间是一个巨大的兔子洞,里面集合了新奇、刺激、喜悦、痛苦、不安等各种元素。在日复一日的......一起来看看 《网络心理学》 这本书的介绍吧!

RGB转16进制工具
RGB转16进制工具

RGB HEX 互转工具

URL 编码/解码
URL 编码/解码

URL 编码/解码

MD5 加密
MD5 加密

MD5 加密工具