Vue - 通俗易懂的组件通信问题(父子传值)

父 → 子

假如,我们需要定义一个 列表组件,该组件的数据需要使用 根组件(vm)data 的数据(最外层),这就要涉及到组件通信问题。

Vue 提供了解决方案,通过 Prop 向子组件传递数据 ,便可解决该问题。

我们先来创建组件及实例化Vue,做好基础环境工作,我们 先不进行传值

<body>
  <div id="app">
      <List></List>
  </div>
</body>
// 创建列表组件(子组件)
Vue.component('List', {
  template: `<li>{{ msg }}</li>`,
  data(){
    return {
      msg: "数据"
    }
  },
})

// 实例化Vue(根组件)
let vm = new Vue({
  el: '#app',
  data: {}
})

在这里插入图片描述
不难发现,List 子组件使用的数据是自身 data 身上的数据,所以毫无疑问正常显示。

那么问题来了,List 子组件如何使用根组件(vm)身上的 data ?(下图所示)
在这里插入图片描述
你只需要在 List(子组件) 加上 props 属性,props 值是一个数组,包含了接收数据(即父组件传递给子组件的变量),任何值都可以传递(对象 / 数组 / 函数 …)

传递完成了还不行,你得 告知子组件数据传过来了,即在组件标签上绑定属性: :msg,这段话不懂没关系,看完下面的 demo 你就明白了!

当一个值传递给一个 prop attribute 的时候,它就变成了那个组件实例的一个 property。

我们重构上面的代码,让其完成传递:

<body>
  <div id="app">
  		<!-- 告知子组件 -->
  		<!-- 【:msg】接收父组件数据 -->
  		<!-- 【msg】父组件的数据 -->
       <List :msg="msg"></List>
  </div>
</body>
Vue.component('List', {

  // 接收父组件数据
  props:['msg'],
  template: `<li>{{ msg }}</li>`,
  data(){
    return {}
  },
})

// 实例化Vue
let vm = new Vue({
  el: '#app',
  data: {
    msg: "我是父组件的数据!"
  }
})

在这里插入图片描述
这样就完成了父传子的通信,需要注意的是 :msg = "msg" 不会被渲染。

子 → 父

上面我们完成了 父组件传值给子组件示例 ,下面我们基于上面的例子继续探索。

你还记得吗?每一个子组件都是一个实例(VueComponent),就像 Vue 实例一样!

子组件也同样拥有 methods / data 这些属性,除了没有 el

我们在子组件中定义一个方法(show),来查看这个实例(VueComponent):

Vue.component('List', {
  props:['msg'],
  template: `<li>{{ msg }}
              <button @click="show">点击触发</button>
            </li>`,
  data(){
    return {}
  },
  methods: {
    show(){
      console.log(this)
    }
  }
})

在这里插入图片描述
你看!接下来我们展开这个实例,并找到 $root 这个属性:
在这里插入图片描述
没错!它就是我们要找的父组件实例!挂载着父组件的所有数据!


这时你可能有疑问,这跟传递值有半毛钱关系吗?为什么不用 $emit 来监听传值?

让我们回到最初,遐想一下,我们将 父组件 的数据传递给 子组件 ,用意是什么?

是不是你 子组件 要用 父组件 的数据?如果不用为什么要传递?

上面说了,子组件$root 属性下挂载着 父组件 的所有数据!

既然能直接拿到 父组件 的所有数据,为什么还要繁琐的传递呢?

注意:组件通信的方式有很多种,这里只谈这一种方式,您视情况而定!

我们完成一个小示例(当点击按钮时,获取父组件数据)

获取成功即为通信成功!

<body>
  <div id="app">
      <List></List>
  </div>
</body>
// 子组件
Vue.component('List', {
  template: `<li>获取父组件数据:{{ msg }}
              <button @click="show">获取父组件数据</button>
            </li>`,
  data(){
    return {
        msg: ''
    }
  },
  methods: {
    show(){

      // 获取父组件数据 data-msg
      let e = this.$root.msg
      
      // 将数据赋给子组件 data-msg
      this.msg = e

    }
  }
})

// 父组件(根)
let vm = new Vue({
  el: '#app',
  data: {
    msg: "我是父组件的数据!"
  }
})

在这里插入图片描述
成功!

可以看到,我们并未使用繁琐的 props / $emit … ,而是 直接获取父组件实例,然后直接拿数据。

写在后面

记住,能拿到 data 属性上挂载的数据,就能拿到 methods 属性上挂载的方法,懂吧!

猜你喜欢

转载自blog.csdn.net/weixin_44198965/article/details/106909641