_l = this._l = this._l = this._l = this._l = this._l = this._l = this._l = this._l = this._l = this._l
Source location, code is not long, you can read
Three utility functions
isDef
IsDef is short for isDefined, which is the other way around isUndefined, just depending on whether it’s undefined
function isDef (v) {
returnv ! = =undefined&& v ! = =null
}
Copy the code
isObject
IsObject, which distinguishes original values from objects
function isObject (obj) {
returnobj ! = =null && typeof obj === 'object'
}
Copy the code
hasSymbol
Used to determine whether the current host environment supports native Symbol and reflect.ownkeys. First check whether Symbol and Reflect exist, and use isNative functions to ensure that Symbol and Reflect. OwnKeys are all native definitions
var hasSymbol =
typeof Symbol! = ='undefined' && isNative(Symbol) &&
typeof Reflect! = ='undefined' && isNative(Reflect.ownKeys);
/* Check whether it is a built-in method */
function isNative (Ctor) {
return typeof Ctor === 'function' && /native code/.test(Ctor.toString())
}
Copy the code
renderList
In the SRC /core/instance/render-helpers/index.js installRenderHelpers method, the renderList method is copied to target._l, i.e. This. _l = renderList
The logic is clear, with four cases (you can think of val as the value v-for)
Val is Array, or String
ret = new Array(val.length)
for (i = 0, l = val.length; i < l; i++) {
ret[i] = render(val[i], i)
}
Copy the code
Val for number
Support number!!
ret = new Array(val)
for (i = 0; i < val; i++) {
ret[i] = render(i + 1, i)
}
Copy the code
Val for Object
- Symbol is supported and contains iterators
Iterator defines default iterators for each Object. The built-in types are Array, String, Map, Set, TypedArray, and Object do not
So in order to be able to use iterators, we can define an iterator of our own. Example code:
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())
Copy the code
So, if you need to customize the list order, you can customize an iterator to define the order in which the values are iterated
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() }Copy the code
- Case where Symbol is not supported
In this case, it is easier to generate an array of objects’ properties from object.key and iterate through it
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)
}
Copy the code
The case where val is not defined
Returns an empty array
if(! isDef(ret)) { ret = [] }Copy the code
PS: Although I think this kind of anomaly should be put at the forefront of personal coding habits, not a problem
conclusion
- V-for can iterate over numbers and strings
- Iterators for objects can be customized to implement custom list order
- TypeArray has iterators, i.e. v-for can render class arrays
- V-for does exception handling, so when you pass in a value that is not Array, String, Number, Object, v-for renders an empty Array
The source code
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
}
Copy the code