Краткое изложение опыта разработки спецификации Vue (часть)

Vue.js

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

Не существует абсолютно оптимального решения для стандартов кодирования команды, стандартов git и т. д., поэтому будьте чисты в своем сердце.没有银弹Норма состоит в том, чтобы позволить команде униформу, улучшить чтение кода, снизить стоимость обслуживания кода, эта статья записана в некоторых проектахcode reviewСпецификации обычно встречаются в , только для справки

JS-часть

Данные, не связанные с рендерингом

vueсерединаdataПо умолчанию данные будут двусторонними.Если большое количество данных, не относящихся к рендерингу, непосредственноdata, производительность, потребляемая двусторонней привязкой данных, будет потрачена впустую, и эти данные, не относящиеся к рендерингу, будут извлечены и сопоставлены.Object.freezeобрабатывать

tableсерединаcolumnsДанные могут быть извлечены отдельно из внешнегоjsфайл в качестве файла конфигурации, его также можно использовать в текущем.vueОпределить определение константы в файлеcolumnsданные, поскольку они фиксированы и в любом случае не изменяются, их следует использоватьObject.freezeОбтекание может не только повысить производительность, но и извлечь фиксированные данные.Эта операция также рекомендуется для фиксированных данных в начале некоторых раскрывающихся списков.

const columnList = Object.freeze([
  { title: '姓名', key: 'name', align: 'center' },
  { title: '性别', key: 'gender', align: 'center' }
])

Следует отметить, что Object.freeze() замораживает значение. В это время ссылка на переменную все еще может быть заменена, и этот синтаксис может использоваться для гарантии того, что данные не изменятся. Если вы хотите изменить и взаимодействовать с данными он не подходит.Используйте замороженный.

Modalкоробка управления

Обычно на странице много всплывающих окон с различными функциями. Если для каждого всплывающего окна задана соответствующая переменная для управления его отображением, количество переменных будет избыточным, и именование будет затруднено. Вы можете использовать переменную для управления та же страница. все вModalОтображение пули

Например, есть триModalвыскакивать

// bad
// 每一个数据控制对应的Modal展示与隐藏
new Vue({
    data() {
        return {
            modal1: false,
            modal2: false,
            modal3: false,
        }
    }
})

// good
// 当modalType为对应的值时 展示其对应的弹框
new Vue({
    data() {
        return {
            modalType: '' // modalType值为 modal1,modal2,modal3
        }
    }
})

debounceиспользовать

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

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

<Select :remote-method="remoteMethod">
    <Option v-for="item in temoteList" :value="item.value" :key="item.id">{{item.label}}</Option>
</Select>
import {debounce} from 'lodash'

methods:{
    remoteMethod: debounce(function (query) {
        // to do ...
       // this 的指向没有问题
    }, 200),
}

картина

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

  • Проблема сжатия изображения, если изображение не должно отображаться в высоком качестве, оно должно соответствоватькомпрессияиметь дело с

  • Выбор формата изображения для разных бизнес-сценариев

    • Формат JPG подходит для представления цветных изображений.Изображения в формате JPG часто появляются в виде больших фоновых изображений, карусельных изображений или баннеров и т. д.
    • Логотипы, простые и контрастные изображения или фоны, требуется прозрачность и т. д.
    • Объедините небольшие изображения, которые обычно используются и имеют низкую частоту изменения, в изображение спрайта, для тех, которые меняются чаще и реже.6KBфотографииbase64иметь дело с
    • В зависимости от количества изображений проекта и распределения пользовательских моделей проекта рассмотрите возможность принятияwebpОбработка изображения

Параметры передачи компонента маршрута

использовать в компоненте$routeЭто делает его тесно связанным с соответствующим маршрутом, поэтому компонент можно использовать только на некоторых конкретных URL-адресах, что ограничивает его гибкость.

использоватьpropsРазделение компонентов и маршрутов:

заменить$routeсвязь

const User = {
  template: '<div>User {{ $route.params.id }}</div>'
}
const router = new VueRouter({
  routes: [
    { path: '/user/:id', component: User }
  ]
})

пройти черезpropsразъединение

Это позволяет использовать компонент где угодно, что упрощает его повторное использование и тестирование.

const User = {
  props: ['id'],
  template: '<div>User {{ id }}</div>'
}
const router = new VueRouter({
  routes: [
    { path: '/user/:id', component: User, props: true },

    // 对于包含命名视图的路由,你必须分别为每个命名视图添加 `props` 选项:
    {
      path: '/user/:id',
      components: { default: User, sidebar: Sidebar },
      props: { default: true, sidebar: false }
    }
  ]
})

Ссылаться на:Параметры передачи компонента маршрута

Жизненный цикл Vue

В компонентах «родитель-потомок» освоение порядка загрузки хуков жизненного цикла, соответствующих компонентам «родитель-потомок», позволяет разработчикам делать правильные вещи в более подходящее время Этот вопрос задавали по крайней мере три раза в недавних интервью, и он все еще требует внимания.родительский компонент

<template>
  <div>
    <h3>home</h3>
    <list @hook:mounted="listMounted" />
  </div>
</template>

<script> import List from './list'

export default { name: "home", components: { List }, methods: { listMounted(){ console.log('------------ listMounted'); } }, beforeCreate() { console.log("home beforeCreate"); }, created() { console.log("home created"); }, beforeMount() { console.log("home beforeMount"); }, mounted() { console.log("home mounted"); }, beforeDestroy() { console.log("home beforeDestroy"); }, destroyed() { console.log("home destroyed"); } } </script>

Подсборка

<template>
  <div>
    list
  </div>
</template>

<script> export default { naem: "list", beforeCreate() { console.log("list beforeCreate"); }, created() { console.log("list created"); }, beforeMount() { console.log("list beforeMount"); }, mounted() { console.log("list mounted"); }, beforeDestroy() { console.log("list beforeDestroy"); }, destroyed() { console.log("list destroyed"); } } </script>

Порядок загрузки родительских и дочерних компонентов при загрузке

home beforeCreate --> home created --> home beforeMount --> list created --> list beforeMount --> list mounted

Порядок уничтожения родительских и дочерних компонентов при уничтожении

home beforeDestroy --> list beforeDestroy --> list destroyed --> home destroyed

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

emit up

// 子组件在对应的钩子中发布事件
created(){
  this.$emit('done')
}

// 父组件订阅其方发 <list @done="childDone">

hook

пройти через@hookМониторинг жизненного цикла дочерних компонентов

<list @hook:mounted="listMounted" />

Selectоптимизация

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

<!-- bad -->
<Select :remote-method="remoteMethod">
    <Option v-for="item in temoteList" :value="item.value" :key="item.id">
        {{item.label}}
    </Option>
</Select>

нужно бытьOptionsСохраняйте значение раскрывающегося списка в той же строке

<!-- good -->
<Select :remote-method="remoteMethod">
    <Option v-for="item in temoteList" :value="item.value" :key="item.id">{{item.label}}</Option>
</Select>

dataиерархия данных

dataДанные имеют иерархическую структуру данных. Не допускайте чрезмерного выравнивания или слишком глубокого вложения. Чрезмерное выравнивание приведет к конфликтам пространства имен данных, передаче и обработке параметров, а слишком глубокое вложение уровня также приведет кvueКогда данные украдены, уровень рекурсии слишком глубокий.Если уровень вложенности сумасшедший, будьте осторожны с проблемой взрыва рекурсивного стека. Более того, при слишком глубоком уровне манипулирование данными и их обработка будут неудобны, а получение данных для отказоустойчивой обработки будет громоздким. Как правило, лучше держать 2-3 слоя.

Если есть только один слой данных, он слишком плоский

{
    name: '',
    age: '',
    gender: ''
}

причинять неудобства

// 作为接口参数传递
ajax({
 this.name, this.age, this.gender
})

// 接口获取数据,批量处理
ajax().then(res => {
 const {name, age, gender} = res.data
    this.name = name
    this.age = age
    this.gender = gender
})

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

{
    person: { // 个人信息
        name: '',
        age: '',
        gender: ''
    }
}

может ориентироватьсяpersonдействовать

// 作为接口参数传递
ajax(this.person)

// 接口获取数据,批量处理
ajax().then(res => {
 const {name, age, gender} = res.data
    this.$set(this, 'person', {name, age, gender})
})

режим стратегии

Использование режима стратегии, чтобы избежать слишком многогоif elseСуждение также может заменить простую логикуswitch

const formatDemandItemType = (value) => {
    switch (value) {
        case 1:
            return '基础'
        case 2:
            return '高级'
        case 3:
            return 'VIP'
    }
}

// 策略模式
const formatDemandItemType2 = (value) => {
    const obj = {
        1: '基础',
        2: '高级',
        3: 'VIP',
    }
    
    return obj[value]
}

Деконструкция

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

const {
  naem = '',
  age = 10,
  gender = 'man'
} = res.data

// bad
this.name = name
this.age = age
this.gender = gender

// good
this.person = {
  naem,
  age,
  gender
}

единственная ответственность

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

Каждая страница будет запрашивать данные после завершения загрузки и отображать их на странице.

created() {
  this.init();
},
methods: {
  // 将全部的请求行为聚合在init函数中
  // 将每个请求单独拆分
  init() {
    this.getList1()
    this.getList2()
  },
  getList1() {
    // to do ...
  },
  getList2() {
    // to do ...
  }
}

v-bind

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

например компонентtest-demoнужна кучаpropsпередача

при его использовании

<template>
  <test-demo 
    :data1="data1"
    :data2="data2"
    :data3="data3"
    ...假设还有一堆
  />
</template>

test-demoнужно получить обработку

{
	props: ['data1', 'data2', 'data3', ...]
}
// or
props: {
  modalVisible: {
    // 控制展示modal
    type: Boolean,
    default: false
  },
  data1: {
    type: String,
    default: '1'
  },
  data2: {
    type: String,
    default: '2'
  },
  data3: {
    type: String,
    default: '3'
  }
}
  • предложение

Соберите данные, необходимые подкомпонентам, централизуйте их в объекте, используйтеv-bindПередача этого объекта передается, использование дочернего компонента и нормальногоpropsТакой же

<template>
	<test-demo 
    v-bind="obj"
  />
</ template>

<script> export default { data () { return { obj: { // 将需要传递给子组件的数据收集 data1: '1', data2: '2', data3: '3' } } } } </script>

HTML-раздел

htmlзаписывать

записыватьtemplateВ шаблоне нужно ли обтекать, когда слишком много атрибутов

<template>
  <!-- 不换行 -->
  <VueButton class="icon-button go-up" icon-left="keyboard_arrow_up" v-tooltip="$t('org.vue.components.folder-explorer.toolbar.tooltips.parent-folder')" @click="openParentFolder" />

<!-- 换行 --> <VueButton class="icon-button go-up" icon-left="keyboard_arrow_up" v-tooltip="$t('org.vue.components.folder-explorer.toolbar.tooltips.parent-folder')" @click="openParentFolder" /> </template>

использование сущности

htmlПродемонстрировать<,>,&При ожидании символов вместо этого используйте сущности символов

<!-- bad -->
<div>
  > 1 & < 12
</div>
  
<!-- bad -->
<div>
  &gt; 1 &amp; &lt; 12
</div>

раздел CSS

проникновение в стиль

Очень часто модифицируют стили сторонних компонентов в процессе разработки, но из-заscopedИзоляция атрибутов стилем, возможно, потребуется удалитьscopedили начать другоеstyle. Эти методы приведут к побочным эффектам (загрязнение стиля компонента, недостаточно элегантное), а проникновение стиля вступит в силу только при использовании в препроцессоре CSS.

  • меньше использования/deep/

<style scoped lang="less">
.content /deep/ .el-button {
	 height: 60px;
}
</style>
  • использование scss::v-deep

<style scoped lang="scss">
.content ::v-deep .el-button {
  height: 60px;
}
</style>

  • использование стилуса>>>
<style scoped ang="stylus">
外层 >>> .custon-components{
  height: 60px;
}
</style>

пространство

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

После выбора значения атрибута

.custom-style { // 选择器和{ 之间空格
  margin: 0; // 属性值前
  transform: scale(1.5, 2.2); // 逗号之后增加空格
}

новая линия

а такжеhtmlТип, когда у строки много атрибутов, правильные разрывы строк могут улучшить чтение и эстетику.

.custom-style{
  // 可以在一次声明中定义一个或多个属性
  background: background-clip
    background-color
    background-image
    background-origin
    background-position
    background-repeat
    background-size;
}

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

.custom .header .title,
.other .header .title {
  color: #f0f;
}

уровень вложенности

Браузер анализируетcssКогда , он сопоставляется рекурсивно справа налево. Слишком глубокая вложенность уровней не только влияет на производительность, но также снижает читабельность стиля и обслуживание кода. Как правило, фрейм уровня контролируется на5внутри слоя

Двойные кавычки

Значения в селекторах атрибутов должны быть заключены в двойные кавычки, одинарные кавычки не допускаются и никакие кавычки не допускаются,htmlЗначение атрибута также рекомендуется использовать в двойных кавычках,jsиспользовать одинарные кавычки в

.custom-style{
	font-family: "PingFang SC", "STHeitiSC-Light";  
}

порядок собственности

Атрибуты по одному и тому же правилу при написании должны быть сгруппированы по функциям. И пишите в следующем порядке: Модель форматирования (макет, положение) > Блочная модель (размер) > Типографика (связанная с текстом) > Визуальные (визуальные эффекты), чтобы улучшить читаемость кода.

объяснять:

  • Свойства, связанные с моделью форматирования, включают в себя: положение/сверху/справа/снизу/слева/плавающее положение/отображение/переполнение и т. д.
  • К свойствам, связанным с блочной моделью, относятся: граница/поле/заполнение/ширина/высота и т. д.
  • Свойства, связанные с типографикой, включают в себя: font / line-height / text-align / word-wrap и т. д.
  • К визуальным свойствам относятся: фон/цвет/переход/стиль списка и т. д.

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

Ссылаться на