Исходя из трех основных концепций компонентов vue, напишите компонент [теорию]

Vue.js

Компонент с хорошей применимостью, у кого есть много настраиваемых элементов, а другая легко переопределить, чтобы продлить функцию

API компонента Vue состоит из трех частей — свойств, событий и слотов:

  • реквизиты позволяют внешней среде передавать данные компоненту
  • событие позволяет запускать побочные эффекты внешней среды изнутри компонента
  • слот позволяет внешней среде объединять дополнительный контент в компоненте

prop

Компонент имеет свое собственное состояние.Когда никакие связанные порпы не переданы, он использует свое собственное состояние для завершения логики рендеринга и взаимодействия;когда компонент вызывается, если есть переданные связанные реквизиты, он передает управление и родительский компонент будет управлять своим поведением

Только значение входящего компонента

  • Если компонент поддерживает двустороннюю привязку, вы можете использоватьv-modelПередайте этот параметр в компонент, чтобы уменьшить затраты памяти (в конце концов, официальный синтаксический сахар vue, белый цвет не нужен)
<my-component v-model="foo" />
  • Если компонент может работать независимо и не зависит от родительского компонента, дайте этому значению имя
<component-no-sync :childNeed="foo" />

В компонент нужно передать много значений

Например, когда компонент имеет много элементов конфигурации и если элементы конфигурации не передаются для использования элементов по умолчанию внутри компонента, наш исходный родительский компонент записывается так:

<child-component :prop1="var1" :prop2="var2" :prop="var3" ... />

Фактически, его можно использовать непосредственно в родительском компоненте.v-bind={子组件props集合}

Однако, чтобы облегчить переопределение элементов внутренней конфигурации подкомпонентов, вы можете использовать объект для сбора конфигурации вместе, но этот подход не может использовать свойства для проверки каждого типа значения в объекте.

<child-component v-model="text" :setting="{color:'bule'}" />

// 子组件内部读取配置,通过扩展运算符替换掉默认配置
const setting ={
  ...defaultSetting,
  ...this.setting
}

вычисляемое свойство

вычисляемое свойство vue по умолчанию доступно только для чтения, вы можете предоставитьsetter. Он может оптимизировать логику компонента, который я пишу, подходит для случая, когда значение, обрабатываемое родительским компонентом, и значение, обрабатываемое дочерним компонентом, совпадают.

<template>
  <el-select v-model="email">
    <el-option
      v-for="item in adminUserOptions"
      :key="item.email"
      :label="item.email"
      :value="item.email"
    />
  </el-select>
</template>
export default {
  props: {
    value: {}
  },
  computed: {
    email: {
      get() {
        return this.value
      },
      set(val) {
        this.$emit('input', val)
        this.$emit('change', val)
      }
    }
  }
}

гибкий реквизит

Мы часто видим отличные библиотеки компонентов, и входящее значение может быть либо строкой/числом, либо функцией.

НапримерElementUIизTableКомпоненты, когда вы хотите отобразить данные дерева, должны быть переданыrow-key. Посмотрите на его введение, чтобы узнать, насколько он гибкий:

row-keyРоль: данные строкиKey, чтобы оптимизироватьTableрендеринг; использованиеreserve-selectionЭто свойство требуется, когда используются данные функции и дерева отображения. Когда тип String, поддерживается многоуровневый доступ:user.info.id, но user.info[0].id не поддерживается, в этом случае используйтеFunction

Исходный код функции для обработки rowKey для генерации RowIdentity:

//https://github.com/ElemeFE/element/blob/dev/packages/table/src/util.js
export const getRowIdentity = (row, rowKey) => {
  if (!row) throw new Error('row is required when get row identity')
  // 行数据的key
  if (typeof rowKey === 'string') {
    if (rowKey.indexOf('.') < 0) {
      return row[rowKey]
    }
    // 支持多层访问:user.info.id
    let key = rowKey.split('.')
    let current = row
    for (let i = 0; i < key.length; i++) {
      current = current[key[i]]
    }
    return current
    // 通过函数自定义
    // 我处理过父和子id可能相同的情况,只好通过Function自定义
    // 不可以通过时间或者随机字符串生成ID
  } else if (typeof rowKey === 'function') {
    return rowKey.call(null, row)
  }
}

Из-за изменчивости бизнес-сценариев дизайнеру компонента сложно рассмотреть его полностью, лучше спроектировать гибкие реквизиты и определить их сами разработчики.

разное

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

мероприятие

emit/on

Читатели должны знать, как использовать emit/on, поэтому я кратко расскажу оv-modelа такжеsyncсинтаксический сахар, мы можем использовать эти синтаксические сахара, чтобы помочь нам написать краткий код (родительские компоненты могут писать меньше событий, которые прослушивают дочерние компоненты, например, вам не нужно писать @input)

v-model

Взгляните на пример кода ниже, чтобы понять это утверждение. v-model игнорирует начальное значение атрибутов value, checked и selected всех элементов формы и всегда использует данные экземпляра Vue в качестве источника данных. Вы должны объявить начальное значение в параметре данных компонента через JavaScript

<input v-model="searchText" />

<input
  v-bind:value="searchText"
  v-on:input="searchText = $event.target.value"
/>

// 当把v-model用在组件上

<custom-input
  v-bind:value="searchText"
  v-on:input="searchText = $event"
></custom-input>

Чтобы заставить его работать, внутри этого компонента<input>Обязательно: привяжите свой атрибут value к реквизиту с именем value. Когда его событие ввода запускается, новое значение выбрасывается через пользовательское событие ввода, то естьthis.$emit('input',changedValue)

пользовательская v-модель

Зачем настраивать v-модель компонента, ведь данные не соответствуют требованиям. Ваше входное значение не всегда может быть value , и ваше событие не всегда может быть входным.Документация

sync (синтаксический сахар двустороннего связывания)

Vue действительно удобен для разработчиков, с точки зрения разработчиков он значительно повышает эффективность разработки.

Замена двусторонней привязки событием, запускаемым в шаблоне update:myPropNamethis.$emit('update:title', newTitle), подробности см.Документация

Функция передана через реквизит

Изначально я хотел поместить его в часть prop, но лично я думаю, что это больше связано с emit/on.

Некоторые читатели могут спросить, почему события в дочернем компоненте не могут генерироваться и обрабатываться родительским компонентом? Затем передайте свойство, которое управляет дочерним компонентом.

Что я хочу сказать, это может быть, но это действительно хлопотно, но состояние внутри подкомпонента - полагаться на родительские компоненты.

Внутреннее состояние компонента, нужно ли его выставлять? Я не думаю, что это необходимо, состояние внутри компонента делает его внутри компонента

Но вы можете участвовать в поведении изменений состояния компонента, передав функцию (вы можете понимать это как хук). Например, очень полезная библиотека перетаскивания,Vue.DraggableУправляет поведением перетаскивания элемента.

Vue.DraggableВы можете передать метод перемещения, и давайте посмотрим, как он работает.

onDragMove(evt, originalEvent) {
      const onMove = this.move;
      // 如果没有传入move,那么返回true,可以移动
      if (!onMove || !this.realList) {
        return true;
      }

      const relatedContext = this.getRelatedContextFromMoveEvent(evt);
      const draggedContext = this.context;
      const futureIndex = this.computeFutureIndex(relatedContext, evt);
      Object.assign(draggedContext, { futureIndex });
      const sendEvt = Object.assign({}, evt, {
        relatedContext,
        draggedContext
      });
      // 组件行为由传入的move函数控制
      return onMove(sendEvt, originalEvent);
}

Преимущество этого в том, что внутри компонента есть свободный набор работающей логики, но я могу вмешаться, передав функцию. Я не модифицировал внутреннее состояние компонента напрямую, а запускал его через функцию (можно назвать хуком), что удобно для отладки компонента и делает поведение компонента предсказуемым

Родительский компонент напрямую манипулирует дочерним компонентом.

Таких операций немного, но из-за сложности данных и операций, когда структура данных сложная и вложенность слишком глубокая, родительскому компоненту сложно тонко контролировать данные дочернего компонента

Поэтому, если вам нужно это сделать, укажите методы, которые подкомпоненты могут вызывать в документации для использования пользователями. Использование такого компонента более хлопотно, надо смотреть документацию, если документации нет, надо смотреть исходный код

ElementUIизtreeкомпонентыПредоставляет родительским компонентам множество методов для управления дочерними компонентами.

eg:this.$refs.tree.setCheckedKeys([]);

слот

HTML <slot> elementЭто часть технологии веб-компонентов и заполнитель для пользовательских веб-компонентов.Слот в vue вдохновлен проектом спецификации веб-компонентов.Подробнее см.Документация

слот по умолчанию

Если вы можете использовать слот по умолчанию, не используйте именованный слот Я действительно не хочу использовать ваш компонент для просмотра имени вашего слота.

Раньше у нас был шаблон сайта с тремя слотами, шапкой, телом и футером, мне было очень неудобно его использовать, ничего страшного, кто знает, что использовать (может я стар, если компоненты не нужны, постарайтесь не заставить людей иметь затраты памяти).

запасной контент

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

Инкапсулируйте чужие компоненты

Иногда мы можем инкапсулировать чужие компоненты, что здесь настоятельно рекомендуется.v-bind="$attrs" 和 v-on="$listeners".vm.$attrs— это свойство, содержащее привязки свойств (кроме класса и стиля), которые не распознаются (и не получаются) как реквизиты в родительской области. Доступ к этим нераспознанным свойствам можно получить черезv-bind="$attrs"Передайте внутренний компонент. Неопознанные события могут быть пропущены черезv-on="$listeners"входящий

Например, допустим, я создаю свой компонент кнопкиmyButton, который инкапсулирует компонент el-button из element-ui (на самом деле ничего не делает), используя компонент<my-button />Когда вы можете использовать свойства EL-Button непосредственно в компоненте, они будут встроены в элемент El-Button.

<template>
  <div>
    <el-button v-bind="$attrs">导出</el-button>
  <div>
</template>
// 父组件使用
<my-button type='primary' size='mini'/>

именование компонентов

Рекомендуется следоватьофициальное руководство vue, стоит посмотреть

Когда мы создаем компонент, мы обычно называем его запись index.vue , При импорте мы можем напрямую импортировать папку компонента.

Но с этим есть проблема, когда редактируешь несколько компонентов, все записи компонентов называютсяindex.vue, легко спутать

vscode, по-видимому, знает об этой проблеме, поэтому, когда файл с таким же именем открывается, он отображает имя папки рядом с именем файла.

Как это решить, мы можем рассматривать index.js как простую запись без какой-либо логики. отвечает только за импортcomponent-name-containerтак же какexport default component-name-container

my-app
└── src
        └── components
                └── component-name
                    ├── component-name.css
                    ├── component-name-container.vue
                    └── index.js

советы (личные предпочтения)

  • template, положить<template>Элемент рассматривается как невидимый элемент-обертка, и для него используется v-if. Окончательный результат рендеринга не будет содержать<template>элемент
  • Если вы можете использовать вычисление для вычисления свойств, постарайтесь не использовать часы
  • Слишком много v-if в шаблоне сделают ваш шаблон уродливым,v-else-ifПостарайтесь не использовать его. Длинный список if else выглядит беспорядочно в шаблоне

Есть ли у вас уникальные навыки написания компонентов, дайте мне знать в разделе комментариев