«Учитесь на основе исходного кода» полностью разбирайтесь в параметрах Vue.

Vue.js
«Учитесь на основе исходного кода» полностью разбирайтесь в параметрах Vue.

В последнее время я пишу статьи, связанные с Vue, и если вам интересно, вы можете вернуться к тому, что я писал раньше.

Сборник авторских статей

Текст: Съешьте эту рыбу 🐟 -propsинициализация

initPropsКак это работает:

1.normalizeProps: initPropsНормализованные данные до

normalizePropsКод немного длинный, здесь перечислены только нормализованные.propТип и результат

1.1 Струны

props: ["data"]
// 规范化后
props: {
  data:{
    type: null
  }
}

1.2 Объекты

props: {
  data1: {
    type: String,
    default: ''
  }
  data2: Number,
}
// 规范化后
props: {
  data1: {
    type: String,
    default: ''
  },
  data2: {
    type: Number
  },
}

2.initProps: иметь дело сprops

Анализ исходного кода выглядит следующим образом:

function initProps (vm: Component, propsOptions: Object) {
  const propsData = vm.$options.propsData || {}
  const props = vm._props = {}
  const keys = vm.$options._propKeys = []
  const isRoot = !vm.$parent
  if (!isRoot) {
    toggleObserving(false)
  }
  for (const key in propsOptions) {
    keys.push(key)
    const value = validateProp(key, propsOptions, propsData, vm)
    if (process.env.NODE_ENV !== 'production') {
      const hyphenatedKey = hyphenate(key)
      if (isReservedAttribute(hyphenatedKey) ||
          config.isReservedAttr(hyphenatedKey)) {
        warn(
          `"${hyphenatedKey}" is a reserved attribute and cannot be used as component prop.`,
          vm
        )
      }
      defineReactive(props, key, value, () => {
        if (!isRoot && !isUpdatingChildComponent) {
          warn(
            `Avoid mutating a prop direct....`,
            vm
          )
        }
      })
    } else {
      defineReactive(props, key, value)
    }
    if (!(key in vm)) {
      proxy(vm, `_props`, key)
    }
  }
  toggleObserving(true)
}

2.1 Определение константы

 const propsData = vm.$options.propsData || {}
 const props = vm._props = {}
 const keys = vm.$options._propKeys = []
 const isRoot = !vm.$parent
  • propsData: сохраняет переданныеpropsзначение
  • props: 引用vm._props` и инициализируется как {}
  • keys: существуетvm.$optionsдобавить_propKeysАтрибуты
  • isRoot: чтобы определить, существует ли онvm.$parent, если не корневой узел

2.2 Условное суждение и цикл

if (!isRoot) {
  toggleObserving(false)
}
for (const key in propsOptions) {
  // 省略...
}
toggleObserving(true)
  • !isRoot: если текущий экземпляр не является корневым узлом, закрытьtoggleObserving
  • toggleObserving: можно понимать как переключатель для наблюдения за данными
  • for...in: траверсpropsOptions

2.2.1: ОбходpropsOptionsделать что

for (const key in propsOptions) {
  keys.push(key)
  const value = validateProp(key, propsOptions, propsData, vm)
  if (process.env.NODE_ENV !== 'production') {
      const hyphenatedKey = hyphenate(key)
      if (isReservedAttribute(hyphenatedKey) ||
          config.isReservedAttr(hyphenatedKey)) {
        warn(
          `"${hyphenatedKey}" is a reserved attribute and cannot be used as component prop.`,
          vm
        )
      }
      defineReactive(props, key, value, () => {
        if (!isRoot && !isUpdatingChildComponent) {
          warn(
            `Avoid mutating a prop directly since the value will be ` +
            `overwri  tten whenever the parent component re-renders. ` +
            `Instead, use a data or computed property based on the prop's ` +
            `value. Prop being mutated: "${key}"`,
            vm
          )
        }
      })
    } else {
      defineReactive(props, key, value)
    }
}

Сфокусируйся на:

  • propsOptionsкоторыйopts.props
  • keyкаждыйpropимя

Войдите в цикл в этой точке:

keys.push(key)
const value = validateProp(key, propsOptions, propsData, vm)
  • Будуkeyдобавить вvm.$options._propKeys
  • value: использоватьvalidatePropПроверьте, является ли это ожидаемым значением типа, а затем верните соответствующее значение свойства (или значение по умолчанию).

2.2.2: Затем введитеif...else:

Примечание здесь:

if (process.env.NODE_ENV !== 'production') {
      // 驼峰转连字符
      const hyphenatedKey = hyphenate(key)
      // 校验prop是否为内置的属性
      // 内置属性:key,ref,slot,slot-scope,is
      if (isReservedAttribute(hyphenatedKey) ||
          config.isReservedAttr(hyphenatedKey)) {
        warn(
          `"${hyphenatedKey}" is a reserved attribute and cannot be used as component prop.`,
          vm
        )
      }
      defineReactive(props, key, value, () => {
        // 子组件直接修改属性时 弹出警告
        if (!isRoot && !isUpdatingChildComponent) {
          warn(
            `Avoid mutating a prop directly since the value will be ` +
            `overwri  tten whenever the parent component re-renders. ` +
            `Instead, use a data or computed property based on the prop's ` +
            `value. Prop being mutated: "${key}"`,
            vm
          )
        }
      })
    } else {
      defineReactive(props, key, value)
    }

Наконец упрощено:

if (process.env.NODE_ENV !== 'production') {
      // 驼峰转连字符
      // 校验prop是否为内置的属性
      // 内置属性:key,ref,slot,slot-scope,is
      // 若是内置,弹出警告
      defineReactive(props, key, value, () => {
      // 子组件直接修改属性时 弹出警告
    } else {
      defineReactive(props, key, value)
    }

Вспомогательная функция:JS-операция «Узнать из исходного кода» в исходном коде Vue

2.2.3: defineReactive: окончательная обработка

defineReactive(props, key, value)

defineReactiveЭто старый знакомый, но вот небольшая заметка: ранееtoggleObserving(false), выключает переключатель наблюдения, поэтомуdefineReactiveвызыватьobserve, является недопустимым вызовом.

На этом можно сделать вывод

propsчерезdefineReactiveОпределено, хотя в настоящее время это оперативные данные, оно не имеет глубокого определения.

То есть после того, как родительский компонент передает свойства дочернему компоненту, дочерний компонент не должен повторять наблюдение.props

2.2.4 toggleObserving(true)`: Наконец, откройте переключатель наблюдения.

toggleObserving(true)

Снова откройте переключатель наблюдения, чтобы не повлиять на последующее выполнение кода.

Понимание: по сравнению с анализом исходного кода писать блог после понимания сложнее. Четко сказать что-то словами намного сложнее, чем набирать код.