vue2源码-十七、Vue组件间传值的方式及之间区别
Vue组件间传值的方式及之间区别
通过
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)上通过
$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 }ref:父组件在使用子组件的时候设置
ref
使用
<Children ref="foo" /> this.$refs.foo // 获取子组件实例,通过子组件实例我们就能拿到对应的数据
EventBus:兄弟组件传值
$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>

浙公网安备 33010602011771号