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 中去获取数据


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

查看所有标签

猜你喜欢:

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

Head First Design Patterns

Head First Design Patterns

Elisabeth Freeman、Eric Freeman、Bert Bates、Kathy Sierra、Elisabeth Robson / O'Reilly Media / 2004-11-1 / USD 49.99

You're not alone. At any given moment, somewhere in the world someone struggles with the same software design problems you have. You know you don't want to reinvent the wheel (or worse, a flat tire),......一起来看看 《Head First Design Patterns》 这本书的介绍吧!

SHA 加密
SHA 加密

SHA 加密工具

XML、JSON 在线转换
XML、JSON 在线转换

在线XML、JSON转换工具