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

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

查看所有标签

猜你喜欢:

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

C专家编程

C专家编程

Peter Van Der Linden / 徐波 / 人民邮电出版社 / 2008-2 / 45.00元

《C专家编程》展示了最优秀的C程序员所使用的编码技巧,并专门开辟了一章对C++的基础知识进行了介绍。 书中C的历史、语言特性、声明、数组、指针、链接、运行时、内存以及如何进一步学习C++等问题进行了细致的讲解和深入的分析。全书撷取几十个实例进行讲解,对C程序员具有非常高的实用价值。 本书可以帮助有一定经验的C程序员成为C编程方面的专家,对于具备相当的C语言基础的程序员,本书可以帮助他们......一起来看看 《C专家编程》 这本书的介绍吧!

CSS 压缩/解压工具
CSS 压缩/解压工具

在线压缩/解压 CSS 代码

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

在线图片转Base64编码工具

HSV CMYK 转换工具
HSV CMYK 转换工具

HSV CMYK互换工具