vue2源码-十七、Vue组件间传值的方式及之间区别

Vue组件间传值的方式及之间区别

  1. 通过props传递:父组件传递数据给子组件

    • 使用

      // chilid,vue
      props:{  
          // 字符串形式  
       name:String // 接收的类型参数  
          // 对象形式  
       age:{    
          type:Number, // 接收的类型为数值  
          defaule:18,  // 默认值为18  
          require:true // age属性必须传递  
       }  
      }  
      // father.vue
      <Children name="jack" age=18 />  
      
    • 源码:

      vm._propKeys = []
      const props = vm.$options.props
      for (const key in props) {
        vm._propKeys.push(key)
        const value = props[key]
        const hyphenatedKey = hyphenate(key)
        defineReactive(props, key, value)
        if (!(key in vm)) {
          proxy(vm, `_props`, key)
        }
      }
      
      • 首先,通过$options.props获取到组件定义的props属性。
      • 然后通过hyphenate()方法将驼峰命名转换为连字符分割的字符串
      • 使用defineReactive()方法将每个prop对应的值变成响应式的,并且当prop对应的改变时,会触发重新渲染
      • 最后,使用proxy()方法把prop对象上的属性代理到Vue实例(props)上
  2. 通过$emit触发自定义事件:子组件传递数据给父组件。

    • 使用

      // child.vue
      this.$emit('add', good)  
      // father.vue
      <Children @add="cartAdd($event)" />  
      
    • 源码

      Vue.prototype.$emit = function (event: string): Component {
        // 获取当前实例this
        const vm: Component = this
      
        // 在非生产环境下检查事件名是否大小写正确
        if (process.env.NODE_ENV !== 'production') {
          const lowerCaseEvent = event.toLowerCase()
          if (lowerCaseEvent !== event && vm._events[lowerCaseEvent]) {
            tip(
              `Event "${lowerCaseEvent}" is emitted in component ` +
              `${formatComponentName(vm)} but the handler is registered for "${event}". ` +
              `Note that HTML attributes are case-insensitive and you cannot use ` +
              `v-on to listen to camelCase events when using in-DOM templates. ` +
              `You should probably use "${hyphenate(event)}" instead of "${event}".`
            )
          }
        }
      
        // 获取所有监听器
        let cbs = vm._events[event]
      
        // 如果有监听器,执行它们,并将事件参数传递给它们
        if (cbs) {
          // 如果监听器是数组,复制一份新数组,否则就用原来的
          cbs = Array.isArray(cbs) ? cbs.slice() : cbs
      
          // 获取除event参数之外的其他所有参数
          const args = toArray(arguments, 1)
      
          // 定义错误信息
          const info = `event handler for "${event}"`
      
          //遍历该事件所有监听器,并一个个执行
          for (let i = 0, l = cbs.length; i < l; i++) {
            invokeWithErrorHandling(cbs[i], vm, args, vm, info)
          }
        }
      
        // 返回当前Vue实例以支持链式调用
        return vm
      }
      
  3. ref:父组件在使用子组件的时候设置ref

    • 使用

      <Children ref="foo" />  
          
      this.$refs.foo  // 获取子组件实例,通过子组件实例我们就能拿到对应的数据  
      
  4. EventBus:兄弟组件传值

  5. $attrs$listeners:祖先传递给子孙

    • 使用

      // child:并未在props中声明foo  
      <p>{{$attrs.foo}}</p>  
        
      // parent  
      <HelloWorld foo="foo"/>  
      
      // 给Grandson隔代传值,communication/index.vue  
      <Child2 msg="lalala" @some-event="onSomeEvent"></Child2>  
        
      // Child2做展开  
      <Grandson v-bind="$attrs" v-on="$listeners"></Grandson>  
        
      // Grandson使⽤  
      <div @click="$emit('some-event', 'msg from grandson')">  
      {{msg}}  
      </div>  
      
posted @   楸枰~  阅读(28)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 25岁的心里话
· 闲置电脑爆改个人服务器(超详细) #公网映射 #Vmware虚拟网络编辑器
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· 零经验选手,Compose 一天开发一款小游戏!
· 一起来玩mcp_server_sqlite,让AI帮你做增删改查!!
点击右上角即可分享
微信分享提示