Недавно я читал исходный код элемента, но есть много внутренних элементов.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 — это массив или строка
ret = new Array(val.length)
for (i = 0, l = val.length; i < l; i++) {
ret[i] = render(val[i], i)
}
Вал - это число
Он даже поддерживает номер! !
ret = new Array(val)
for (i = 0; i < val; i++) {
ret[i] = render(i + 1, i)
}
val — это объект
- Поддерживающие символы и содержащие итераторы
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()
}
- Когда символ не поддерживается
Эта ситуация относительно проста, создайте массив атрибутов объекта с помощью 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)
}
значение не определено
возвращает пустой массив
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
}