vue中的组件传值

前言


出来工作有一段时间了,通过对项目不断了了解发现了一个vue的学习和项目中可谓重中之重的话题——组件传值。因为一个vue构建的项目中往往会用到非常多的公共组件,因此如何给这些组件传值就成了必须要掌握的一个技能。而在vue中组件传值无外乎分为三类:父组件->子组件,子组件->父组件,非父子关系组件传值。本文主要讨论前两种场景,文章也是出于自己的理解而写,如有不正确的地方希望大家帮忙修正。

 

父组件->子组件


传值方法:子组件声明 props 属性

实际开发场景会用到非常多的公共组件,而这些公共组件便是子组件,使用者为父组件。公共组件类似于一个方法,如果想起效果就需要给它传值,目前有2种传值方法,其原理都是基于 props 这个属性。

// 父组件app.vue
<template>
    <div>
        <tab-bar v-bind:data="appData">
            <!-- 
                这里的tab-bar是子组件 
                data这里指的是子组件会收到一个名为data的变量
                appData是父组件中的变量,存放了需要发送的数据
            -->
        <tab-bar/>
    </div>    
</template><script>
import Tabbar from "@components/TabBar"
export default {
  data() {
    return {
      appData: "父组件发给子组件的数据"
    };
  },
  components: {
      Tabbar
  }
};
</script>
// 子组件TabBar.vue
<template>
  <div id="tabBar">
    ...
  </div>
</template><script>
export default {
    data() {
        return {
            ...
        }
    },
    // 子组件中声明props,用于接收父组件传过来的数据
    props: {
        // 这里的data就是父组件v-bind的data,名字必须一样
        data: {
            type: String,
            default: () => ""
        }
    }
}
</script>

这是 props 实现父组件->子组件的一个模拟应用场景。值得一提的是,在子组件中声明的 props 内部的属性,可以看做在 data 中声明了同样名称的属性,即子组件想使用父组件传来的数据只需要 this.data 即可。

这是一个单向且动态的过程,用vue官方文档的话说:

所有的 prop 都使得其父子 prop 之间形成了一个单向下行绑定:父级 prop 的更新会向下流动到子组件中,但是反过来则不行。这样会防止从子组件意外变更父级组件的状态,从而导致你的应用的数据流向难以理解。

额外的,每次父级组件发生变更时,子组件中所有的 prop 都将会刷新为最新的值。这意味着你应该在一个子组件内部改变 prop。如果你这样做了,Vue 会在浏览器的控制台中发出警告。

 

子组件->父组件

传值方法:this.$emit()

// 子组件Swiper.vue
<template>
  <div id="swiper">
    <button v-on:click="change">发送</button>
  </div>
</template><script>
export default {
    data() {
        return {
            swiperData: "这是子组件的数据"
        }
    },
    methods: {
        hasChange() {
            // change指的是父组件会收到一个方法名为change
            // swiperData指的是发送给父组件的数据
            this.$emit("change", this.swiperData)
        }
    }    
}
</script>
// 父组件App.vue
<template>
  <div id="app">
    <!-- 
        父组件使用v-on监听
        这里的change必须要和子组件emit的第一个参数一样 
    -->
    <swiper v-on:change="fn" />
  </div>
</template>
​
​
<script>
import Swiper from "@components/Swiper"
export default {
  data() {
    return {
      ...
    };
  },
  methods: {
      fn(data) {
          console.log(data); // 这里的data就是子组件传来的数据
      }
  }
};
</script>

 

v-model的使用

最开始接触的时候只了解它能实现双向数据绑定,但是不知道它还能用来组件之间传值。

v-model 实际上是简写了 v-bindv-on,可以看成语法糖,其常用于 input,select 等表单控件。

<input type="text" v-model="data">
    
<!-- 等价于 -->
    
<input type="text" :value="data" @input="data=$event.target.value">

也就是说,v-model 会默认绑定一个叫 value 的变量,同时也会监听表单控件的变化,例如 input 的输入事件,selectchange 事件等。

// 父组件App.vue
<template>
  <div id="app">
    <a-tree v-model="data" />
  </div>
</template>
​
​
<script>
import ATree from "@components/ATree"
export default {
  data() {
    return {
      data: "父组件中的数据"
    };
  },
  methods: {
      fn(data) {
          console.log(data); // 这里的data就是子组件传来的数据
      }
  }
};
</script>
// 子组件ATree.vue
<template>
  <div id="atree">
    <select name="atree" @change="hasChange">
        <option value="0">AAA</option>
        <option value="1">BBB</option>
        <option value="2">CCC</option>
    </select>
  </div>
</template><script>
export default {
    data() {
        return {
            aTreeData: "这是子组件的数据"
        }
    },
    props: {
        value: {
            type: String,
            default: () => ""
        }
    },
    methods: {
        hasChange() {
            // change指的是父组件会收到一个变量名为msg
            // aTreeData指的是发送给父组件的数据
            this.$emit("change", this.aTreeData)
        }
    }    
}
</script>

可以看出,v-model 不光可以实现双向数据绑定,同样也可以实现父子组件直接的双向数据传递,可以说是一举两得。

具体的 v-model 使用这里就不介绍了,大家可以参考官方文档自定义组件的 v-model

 

以上都是基于工作中场景以及用法的模拟,希望对大家学习vue有帮助!

 

 

 

 

posted @ 2020-09-27 11:01  ychizzz  阅读(468)  评论(0)    收藏  举报