Изучение исходного кода моего Element-ui --- <el-alert>

Vue.js
Изучение исходного кода моего Element-ui --- <el-alert>

Автор: Гораций
Введение: изучение исходного кода My Element-ui, постоянное обновление время от времени ~
ps: новичок Xiaobai, если есть ошибки, укажите~

Сейчас автор учится на третьем курсе и собирается пройти стажировку. Когда я недавно изучал Vue, я чувствовал, что многому научился, но существенного прогресса не было. Я чувствовал, что достиг узкого места, но мне казалось, что я еще не достиг уровня, когда я могу глубоко копаться в исходном коде Vue.Skill, поэтому я планирую начать анализировать исходный код Element-ui, я надеюсь, что смогу использовать это, чтобы углубиться во Vue, и я начну изучение исходного кода Vue позже.

Поскольку автор давно не изучал исходный код Element-ui, эта статья начнется с<el-alert>Этот компонент начинается, и каждая деталь будет вычленена как можно больше с небольшого ракурса, поэтому большому парню это может показаться очень простым, и статья может не подойти большому парню, чтобы его съесть~

написать впереди

Анализ исходного кода Element-ui автора не будет касаться его стиля css, здесь я скачал Element-ui в проекте, только ввел его стиль, а остальное написал сам, а потом ввел компоненты на свою страницу. .

Я больше сосредоточусь на синтаксисе Vue, стиле кода и его маленьких хитростях, чтобы лучше укрепить свои навыки Vue и JS и создать буфер для деконструкции исходного кода Vue в будущем~

<el-alert>

Посмотрите на эффект, прежде чем начать

效果图
<el-alert>визуализация

По сути, компонентный дизайн требует возможности повторного использования.<el-alert>Можно сказать, что компоненты обладают хорошей производительностью повторного использования и могут применяться к большинству сценариев подсказок сообщений. Далее, давайте разберем его исходный код и используем исходный код, чтобы закрепить некоторые знания о Vue.

структурный дизайн

Компоненты имеют общую структуру.Благодаря динамической привязке, слотам и другим грамматикам Vue тысячи людей могут добиться эффекта повторного использования компонентов.Давайте сначала проанализируем его шаблонную структуру.

<template>
  <div>
    <!-- ElAlert -->
    <transition name="el-alert-fade">
      <div
        class="el-alert"
        :class="[ typeClass, center ? 'is-center' : '', 'is-' + effect ]"
        v-show="visible"
        >
        <i class="el-alert__icon" :class="[ iconClass, isBigIcon ]" v-if="showIcon"></i>
        <div class="el-alert__content">
          <span class="el-alert__title" :class="[ isBoldTitle ]" v-if="title || $slots.title">
            <!-- {{title}} -->
            <!-- 属性和具名插槽两种方式显示 -->
            <slot name="title">{{title}}</slot>
          </span>
          <!-- 通过 slot:default 显示 description -->
          <p class="el-alert__description" v-if="$slots.default && !description"><slot></slot></p>
          <!-- 通过属性显示 description -->
          <p class="el-alert__description" v-if="!$slots.default && description">{{ description }}</p>
          <!-- <p class="el-alert__description" v-if="description || $slots.default">{{ description }}</p> -->
          <!-- 关闭按钮 -->
          <i class="el-alert__closebtn" :class="{ 'is-customed' : closeText!== '', 'el-icon-close': closeText === '' }" v-show="closable" @click="close()">{{ closeText }}</i>
        </div>  
      </div>
    </transition>
  </div>
</template>

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

стиль кода

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

Второе - это соглашение об именовании имени класса, которое максимально понятно.CSS в исходном коде Element-ui использует соглашение об именовании БЭМ --- Block (блок), Element (элемент), Modifier (модификатор) , что помогает нам лучше понять, что делает каждое имя класса.

имя динамического класса

Здесь используются более динамические имена классов.Обычно мы можем писать динамические имена классов и использовать их напрямую.:class=""Такая форма, но вот несколько мест, которые могут немного сбить с толку новичков, например:

:class="[ typeClass, center ? 'is-center' : '', 'is-' + effect ]"
:class="[ isBoldTitle ]" v-if="title || $slots.title"

Имена динамических классов в этих двух местах используют [] и {}, потому что несколько имен динамических классов должны быть связаны, и может потребоваться изменить и отформатировать имя класса в соответствии с соглашением об именах, используя [] и {} Эти вещи можно сделать за один раз, что удобнее. Это может использоваться немного реже, когда мы обычно пишем демо и в других ситуациях, поэтому я также упомяну об этом.

Есть еще одно умное использование имен динамических классов в Element-ui, о котором я расскажу позже.

Предлагает различные варианты

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

<span class="el-alert__title" :class="[ isBoldTitle ]" v-if="title || $slots.title">
  <!-- 属性和具名插槽两种方式显示 -->
  <slot name="title">{{title}}</slot>
</span>
<!-- 通过 slot:default 显示 description -->
<p class="el-alert__description" v-if="$slots.default && !description"><slot></slot></p>
<!-- 通过属性显示 description -->
<p class="el-alert__description" v-if="!$slots.default && description">{{ description }}</p>

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

Кто-то мог видеть мой код с комментарием после отображения описания:

<!-- <p class="el-alert__description" v-if="description || $slots.default">{{ description }}</p> -->

Этот код — то, что я сделал, когда увидел управление отображением заголовка только с одним суждением v-if, поэтому я хочу попробовать это сам и использовать только одно v-if для достижения эффекта,К сожалению, это утверждение не может дать желаемого эффекта, потому что слот описания является слотом по умолчанию, о котором нельзя судить по $slots.default, но его можно добиться, если изменить его на следующий формат:

<p class="el-alert__description" v-if="description || $slots.description"><slot name="description">{{ description }}</slot></p>

Хотя эффект может быть достигнут таким образом, вы добавили именованный слот. Должностные лица Element-ui должны иметь свои собственные соображения, чтобы не делать этого.

Вот исправление:
Автор сказал выше, что я хочу попробовать описание, которое не может быть достигнуто только с одним v-if.После руководства большого парня в области комментариев я обнаружил, что забыл поставить v-if снаружи {{ описание }}.<slot>На самом деле метки могут быть реализованы с помощью v-if:

<p class="el-alert__description" v-if="description || $slots.default"><slot>{{ description }}</slot></p>

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

Причина, по которой я не удалил вышеприведенный абзац напрямую, заключается в том, что я хотел обнажить свои собственные проблемы и предостеречь себя, чтобы в будущем быть более осторожным и осторожным, и не совершать в будущем тех же ошибок. Добро пожаловать, чтобы контролировать вместе ~

дизайн данных

Ознакомившись со структурой, давайте посмотрим на оформление раздела данных и методов. Старые правила, давайте сначала посмотрим на код:

<script>
// 常量 
const TYPE_CLASS_MAP = { 'success': 'el-icon-success', 'warning': 'el-icon-warning', 'error': 'el-icon-error' } export default { name: 'ElAlert', props: { type: { // 类型
type: String, default: 'info' // 默认值 }, title: { // 标题
type: String, default: '' }, description: { type: String, default: '' }, center: Boolean, effect: { // 提供的主题
type: String, default: 'light', validator: function(value) { // 验证 effect 的值必须二选一 // 其中之一
return ['light', 'dark'].indexOf(value) !== -1; } }, showIcon: Boolean, closeText: { type: String, default: '' }, closable: { type: Boolean, default: true } }, data() { return { visible: true } }, computed: { // 计算属性 typeClass() { return `el-alert--${ this.type }` }, iconClass() { return TYPE_CLASS_MAP[this.type] || 'el-icon-info' }, isBigIcon() { return this.desciption || this.$slots.default ? 'is-big' : '' }, isBoldTitle() { return this.description || this.$slots.default ? 'is-bold' : '' } }, methods: { close() { this.visible = false; // 给父组件传递一个 close 方法,便于在用户关闭提示的时候进行一些操作
this.$emit('close') } } } </script>

имя вычисляемого вычислительного класса

Давайте заполним пробел в имени динамического класса, оставленный ранее.Есть четыре имени класса, которые динамически определяются вычисляемым свойством:
typeClass,iconClass,isBigIcon,isBoldTitle
Сценарии использования вычисляемых свойств примерно следующие:

  1. Данные зависят от нескольких данных
  2. Другие данные должны быть обработаны JS перед отображением

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

Умный дизайн данных

Данные здесь имеют умный дизайн, и это константы.

// 常量 
const TYPE_CLASS_MAP = {
  'success': 'el-icon-success',
  'warning': 'el-icon-warning',
  'error': 'el-icon-error'
}

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

реквизит получает проверку

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

  1. Заявленный тип для проверки
  2. Объявите метод проверки для проверки

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

дизайн метода

methods: {
  close() {
    this.visible = false;
    // 给父组件传递一个 close 方法,便于在用户关闭提示的时候进行一些操作
    this.$emit('close')
  }
}

Здесь также устанавливается свойство visible в источнике данных, чтобы пользователь мог закрыть компонент окна подсказки. Дизайн этого метода также очень всеобъемлющий.Когда вы нажимаете «Закрыть», используйте $emit, чтобы отправить событие закрытия родительскому компоненту, и родительский компонент может связать событие через @close, чтобы реализовать некоторые бизнес-операции, когда пользователь закрывает приглашение. . . .

Примечания

При написании компонентов Element-ui самостоятельно, если вы используете его в App.vue, как я, вы должны обратить внимание на удаление стиля #app, иначе возникнут конфликты стилей и стили не будут отображаться правильно.

напиши в конце

Как говорится, программисты, которые не читают исходный код, не являются хорошими программистами.Если вы чувствуете, что достигли стадии узкого места, просмотр исходного кода является хорошим выбором. Эта статья может быть относительно базовой для многих людей, и техническое содержание не очень высокое, но я продолжу изучать исходный код Elment-ui и накоплю больше очков знаний, чтобы я мог улучшить себя. . Я буду продолжать обновлять эту серию. Если вы считаете, что это полезно для вас, пожалуйста, поставьте лайк и напишите мне в комментариях~

Я записал все свои учебные записи на свой гитхаб и буду продолжать их обновлять.Заинтересованные друзья могут посмотреть~
github