vue 源码阅读(一)

vue 源码阅读 (一)

今天围观了知乎上有一起争执,并在评论中看到如下对话:

A 说: 例如自定义组件名大写,而不是Element的前缀形式,更易于在模板中区分原生HTML标签和自定义组件。再如iView禁用input可以这么写<input disable/>, Element文档是这么写的<input :disable-true>,哪个更清晰呢?;二是详细精美的文档,早期甚至好过Element的文档。

B 说:1. 组件名支持大驼峰命名法,这个 Vue 官网里就有提, 我不知道评论者怎么会认为这是组件库的特色了,任何组件都可以这么写。 2. input 的 disable,同样 Vue 文档也有提到,只是写法不同,这也算特点?

组件命名

之前在 vue 1.0 时代,写过一篇 组件之驼峰

属性值

第二点有点意外,特意做了个实验

图片描述

官方文档写的比较隐蔽,在升级指南中有提及,看完后不是很理解,于是翻了下 vue 2.2.1 源码,主要涉及以下几处:

进入生命周期

vue/src/core/instance/init.js

export function initMixin (Vue: Class<Component>) {   Vue.prototype._init = function (options?: Object) {     ...          vm._self = vm     initLifecycle(vm)     initEvents(vm)     initRender(vm)     callHook(vm, 'beforeCreate')     initState(vm)    // <==== 初始化状态     initInjections(vm)     callHook(vm, 'created')      ...   } }

初始化状态

vue/src/core/instance/state.js

export function initState (vm: Component) {   vm._watchers = []   const opts = vm.$options   if (opts.props) initProps(vm, opts.props)  // <==== 初始化属性   if (opts.methods) initMethods(vm, opts.methods)   if (opts.data) {     initData(vm)   } else {     observe(vm._data = {}, true /* asRootData */)   }   if (opts.computed) initComputed(vm, opts.computed)   if (opts.watch) initWatch(vm, opts.watch) }
function initProps (vm: Component, propsOptions: Object) {   const propsData = vm.$options.propsData || {}   const props = vm._props = {}   // cache prop keys so that future props updates can iterate using Array   // instead of dynamic object key enumeration.   const keys = vm.$options._propKeys = []   const isRoot = !vm.$parent   // root instance props should be converted   observerState.shouldConvert = isRoot   for (const key in propsOptions) {     keys.push(key)     const value = validateProp(key, propsOptions, propsData, vm)  // 校验属性值     /* istanbul ignore else */     if (process.env.NODE_ENV !== 'production') {       if (isReservedProp[key]) {         warn(           `"${key}" is a reserved attribute and cannot be used as component prop.`,           vm         )       }       defineReactive(props, key, value, () => {         if (vm.$parent && !observerState.isSettingProps) {           warn(             `Avoid mutating a prop directly since the value will be ` +             `overwritten whenever the parent component re-renders. ` +             `Instead, use a data or computed property based on the prop's ` +             `value. Prop being mutated: "${key}"`,             vm           )         }       })     } else {       defineReactive(props, key, value)     }     // static props are already proxied on the component's prototype     // during Vue.extend(). We only need to proxy props defined at     // instantiation here.     if (!(key in vm)) {       proxy(vm, `_props`, key)     }   }   observerState.shouldConvert = true }

校验属性

vue/src/core/util/props.js

export function validateProp (   key: string,   propOptions: Object,   propsData: Object,   vm?: Component ): any {   const prop = propOptions[key]   const absent = !hasOwn(propsData, key)   let value = propsData[key]   // handle boolean props   if (isType(Boolean, prop.type)) {     if (absent && !hasOwn(prop, 'default')) {       value = false     } else if (!isType(String, prop.type) && (value === '' || value === hyphenate(key))) {       value = true     }   }   // check default value   if (value === undefined) {     value = getPropDefaultValue(vm, prop, key)     // since the default value is a fresh copy,     // make sure to observe it.     const prevShouldConvert = observerState.shouldConvert     observerState.shouldConvert = true     observe(value)     observerState.shouldConvert = prevShouldConvert   }   if (process.env.NODE_ENV !== 'production') {     assertProp(prop, key, value, vm, absent)   }   return value }

是否存在

vue/src/shared/util.js

const hasOwnProperty = Object.prototype.hasOwnProperty export function hasOwn (obj: Object, key: string): boolean {   return hasOwnProperty.call(obj, key) }

脚本宝典为你提供优质服务
脚本宝典 » vue 源码阅读(一)

发表评论

提供最优质的资源集合

立即查看 了解详情