【vue源码】深度理解v-for

栏目: 编程语言 · 发布时间: 5年前

内容简介:最近在阅读element源码的,但是element内部有很多isDef是isDefined的缩写,反过来就是isUndefined,反正就是看它是不是undefined

最近在阅读element源码的,但是element内部有很多 this._l 方法, element 源码里面也找不到,查了一下,原来是vue的内部渲染列表的方法

源码位置 ,代码不长,可以一读

三个 工具 函数

isDef

isDef是isDefined的缩写,反过来就是isUndefined,反正就是看它是不是undefined

function isDef (v) {
  return v !== undefined && v !== null
}
复制代码

isObject

isObject,主要区分原始值和对象

function isObject (obj) {
  return obj !== null && typeof obj === 'object'
}
复制代码

hasSymbol

用来判断当前宿主环境是否支持原生 Symbol 和 Reflect.ownKeys。首先判断 Symbol 和 Reflect 是否存在,并使用 isNative 函数保证 Symbol 与 Reflect.ownKeys 全部是原生定义

var hasSymbol =
  typeof Symbol !== 'undefined' && isNative(Symbol) &&
  typeof Reflect !== 'undefined' && isNative(Reflect.ownKeys);

/* 判断是否是内置方法 */
function isNative (Ctor) {
  return typeof Ctor === 'function' && /native code/.test(Ctor.toString())
}
复制代码

renderList

src/core/instance/render-helpers/index.js 的installRenderHelpers方法中,renderList方法复制给了 target._l ,即 this._l = renderList

代码逻辑很清晰,分四种情况(你可以把val看作被v-for的那个值)

val 为 Array,或者 String

ret = new Array(val.length)
for (i = 0, l = val.length; i < l; i++) {
  ret[i] = render(val[i], i)
}
复制代码

val 为 number

竟然还支持 number !!

ret = new Array(val)
for (i = 0; i < val; i++) {
    ret[i] = render(i + 1, i)
}
复制代码

val 为 Object

  • 支持Symbol,且含有迭代器的情况

Symbol.iterator 为每一个对象定义了默认的迭代器,内置类型中,Array,String,Map,Set,TypedArray而Object没有

所以为了能够使用迭代器,我们可以自己定义一个迭代器,示例代码:

const obj = {
  age: 1,
  name: 'liu',
  [Symbol.iterator]: function*() {
    let properties = Object.keys(this)
    for (let i of properties) {
      yield [i, this[i]]
    }
  }
}

const res = obj[Symbol.iterator]()
console.log('res', res.next())
复制代码

所以,如果你有自定义列表顺序的需求的话,可以自定义一个迭代器,定义遍历的值的顺序

ret = []
const iterator: Iterator<any> = val[Symbol.iterator]()
let result = iterator.next()
while (!result.done) {
    ret.push(render(result.value, ret.length))
    result = iterator.next()
}
复制代码
  • 不支持Symbol的情况

这种情况比较简单,通过Object.key生成对象的属性数组,然后遍历一下

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)
}
复制代码

val 没有被定义的情况

返回一个空数组

if (!isDef(ret)) {
    ret = []
}
复制代码

PS: 虽然我觉得这种异常情况应该置于最前,属于个人编码习惯,问题不大

总结

  • v-for 可以对数字,字符串进行遍历
  • 可以自定义对象的迭代器,实现自定义列表顺序
  • TypeArray 是有迭代器的,即v-for可以渲染类数组
  • v-for 里面做了异常处理,所以当你传入了不属于Array,String,Number,Object的值时,v-for渲染一个空数组

源代码

import { isObject, isDef, hasSymbol } from 'core/util/index'

/**
 * Runtime helper for rendering v-for lists.
 */
export function renderList (
  val: any,
  render: (
    val: any,
    keyOrIndex: string | number,
    index?: number
  ) => VNode
): ?Array<VNode> {
  let ret: ?Array<VNode>, i, l, keys, key
  if (Array.isArray(val) || typeof val === 'string') {
    ret = new Array(val.length)
    for (i = 0, l = val.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: Iterator<any> = 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: any)._isVList = true
  return ret
}
复制代码

以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

新机器的灵魂

新机器的灵魂

Tracy Kidder / 龚益、高宏志 / 机械工业出版社华章公司 / 2011-10 / 45.00元

计算机从1981年开始发生巨大的变化。《新机器的灵魂》完整地记录下了当时一家公司齐心协力把一种新的小型计算机推向市场的过程中所发生的一系列戏剧性的、充满戏剧色彩的、激动人心的故事。 本书以美国通用数据公司研制鹰电子计算机的全过程为主线,对美国计算机工业的发展和管理中鲜为人知的侧面,作了条理清晰、颇具诗情画意的描述。 你想知道一代新型计算机怎样诞生,精明干练而又富于幽默感的工程技术人员怎......一起来看看 《新机器的灵魂》 这本书的介绍吧!

图片转BASE64编码
图片转BASE64编码

在线图片转Base64编码工具

html转js在线工具
html转js在线工具

html转js在线工具

HEX HSV 转换工具
HEX HSV 转换工具

HEX HSV 互换工具