Vue源码解析十
Posted 干饭男孩喵喵喵
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Vue源码解析十相关的知识,希望对你有一定的参考价值。
function renderMixin(Vue){
// 向Vue.prototype上挂载属性方法
installRenderHelpers(Vue.prototype)
...
}
复制代码
render-static
// 渲染静态DOM
export function renderStatic(index,isInFor){
// 获取/初始化静态树
const cached = this._staticTrees || (this._staticTrees = [])
let tree = cached[index]
// 如果静态树存在或者没有v-for则直接复用
if(tree && !isInFor){
return tree
}
// 否则根据渲染方法重新渲染
tree = cached[index] = this.$options.staticRenderFns[index].call(this._renderProxy,null,this)
// 并标记key
markStatic(tree,`__static__${index}`,false)
return tree
}
复制代码
render-list
// 根据val值和render方法生成VNodeList
export function renderList(val,render){
let ret,i,l,keys,key
if(Array.isArray(val) || typeof val === 'string'){
ret = new Array(val.length)
for(i = 0,l = ret.length; i < l; i ++){
ret[i] = render(val[i],i)
}
}else if(typeof val === 'number'){
ret = new Array(val)
for(i = 0; i < val; i ++){
ret[i] = render(i+1,i)
}
}else if(isObject(val)){
if(hasSymbol && val[Symbol.iterator]){
ret = []
const iterator = val[Symbol.iterator]()
let result = iterator.next()
while(!result.done){
ret.push(render(result.value,ret.length))
result = iterator.next()
}
}else{
keys = Object.keys(val)
ret = new Array(keys.length)
for(i = 0,l = keys.length; i < l; i ++){
key = keys[i]
ret[i] = render(val[key],key,i)
}
}
}
if(!isDef(ret)){
ret = []
}
ret._isVList = true
return ret
}
复制代码
render-slot
export function renderSlot(name,fallback,props,bindObject){
// 获取插槽
const scopedSlotFn = this.$scopedSlot[name]
let nodes
// 根据插槽是否存在是否有传入的属性,生成vnode
if(scopedSlotFn){
props = props || {}
if(bindObject){
if(process.env.NODE_ENV !== 'production' && !isObject(bindObject)){
warn('slot v-bind without argument expect an object',this)
}
props = extend(extend({},bindObject),props)
nodes = scopedSlotFn(props) || fallback
}
}else{
nodes = this.$slots[name] || fallback
}
const target = props && props.slot
// 判断插槽是否有插槽,如果存在则根据插槽生成vnode
if(target){
return this.$createElement('template',{slot:target},nodes)
}else{
return nodes
}
}
复制代码
resolve-filter
// 解析filter
export function resolveFilter(id){
return resolveAssets(this.$options,'filter',id,true) || identity
}
复制代码
resolve-scoped-slots
export function resolveScopedSlots(fns,res,hasDynamicKeys,contentHashKey){
// 解析传入的插槽
res = res || { $stable: !hasDynamicKeys }
for(let i = 0; i < fns.length; i ++){
const slot = fns[i]
if(Array.isArray(slot)){
resolveScopedSlots(slot)
}else if(slot){
if(slot.proxy){
slot.fn.proxy = true
}
res[slot.key] = slot.fn
}
}
if(contentHashKey){
res.$key = contentHashKey
}
}
复制代码
render-slot
export function resolveSlots(children,context){
if(!children || !children.lenth){
return {}
}
const slots = {}
for(let i = 0, l = children.length; i < l; i ++){
const child = children[i]
const data = child.data
// 如果child作为Vue的插槽被解析,则移除它的slot属性
if(data && data.attrs && data.attrs.slot){
delete data.attrs.slot
}
if((child.context === context || child.fnContext === context) && data && data.slot !== null){
const name = data.slot
const slot = (slots[name] || (slots[name] = []))
if(child.tag === 'template'){
slot.push.apply(slot,child.children || [])
}else{
slot.push(child)
}
}else{
(slots.default || (slots.default = [])).push(child)
}
}
for(const name in slots){
if(slots[name].every(isWhitespace)){
delet slots[name]
}
}
return slots
}
复制代码
check-keycodes
// 反正最后就是返回是否匹配
export function checkKeyCodes(eventKeyCode,key,builtInKeyCode,eventKeyName,builtInKeyName){
const mappedKeyCode = config.keyCodes[key] || builtInKeyCode
if(builtKeyName && eventKeyName && !config.keyCodes[key]){
return isKeyNotMatch(builtInKetName,eventKeyName)
}else if(mappedKeyCode){
return isKeyNotMatch(mappedKeyCode,eventKeyCode)
}else if(eventKeyName){
return hyphenate(eventKeyName) !== key
}
}
复制代码
bind-object-props
// 绑定属性对象
export function bindObjectProps(data,tag,value,asProp,isSync){
if(value){
if(!isObject(value)){
process.env.NODE_ENV !== 'production' && warn('v-bind without argument expects an Object or Array value',this)
}else{
if(Array.isArray(value)){
value = toObject(value)
}
let hash
for( const key in value){
if(key === 'class' || key === 'style' || isReserverAttribute(key)){
hash = data
}else{
const type = data.attrs && data.attrs.type
hash = asProp || config.mustUseProp(tag,type,key) ? data.domProps || (data.domProps = {}) : data.attrs || (data.attrs = {})
}
const camelizedKey = camelize(key)
const hyphenatedKey = hyphenate(key)
if(!(camelizedKey in hash) && !(hyphenatedKey in hash)){
hash[key] = value[key]
// .sync修饰符, $emit(update:key),接收数据更改
if(isSync){
const on = data.on || (data.on = {})
on[`update:${key}`] = function($event){
value[key] = $event
}
}
}
}
}
}
return data
}
复制代码
bind-object-listeners
export function bindObjectListeners(data,value){
// 绑定对象监听器
if(value){
if(!isPlainObject(value)){
process.env.NODE_ENV !== 'production' && warn('v-on without argument expects an Object value', this)
}else{
const on = data.on = data.on ? extend({},data.on) : {}
for( const key in value){
const existing = on[key]
const ours = value[key]
on[key] = existing ? [].concat(existing,ours) : ours
}
}
}
return data
}
复制代码
bind-dynamic-keys
// 绑定动态key
export function bindDynamicKeys(baseObj,values){
for(let i = 0; i < values.length; i += 2){
const key = values[i]
if(typeof key === 'string' && key){
baseObj[values[i]] = values[i + 1]
}else if(process.env.NODE_ENV !== 'production' && key !== '' && key !== null){
warn(`Invalid value for dynamic directive argument (expected string or null):${key},`,this)
}
}
return baseObj
}
以上是关于Vue源码解析十的主要内容,如果未能解决你的问题,请参考以下文章