Несколько советов, как сделать проекты Vue более плавными

JavaScript Vue.js

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

в разработкеVueВо время процесса мы часто сталкиваемся с некоторыми такими проблемами, а затем быть пойманным в течение длительного времени и т. Д. И т. Д. Сегодня Xiaobian организует несколько фактических боевых очков навыков, которые будут использоваться в проекте, надеясь помочь вам усердно работать. Правила рек и озер, первая похвала, дело постоянно.

Читайте наши последние хитыVueСтатьи по теме, я Zijun, увидимся каждый понедельник

Практические навыки, Vue тоже умеет так писать2700+ лайков

Абсолютно сухой материал~! Изучите эти советы Vue, вы сможете уйти с работы пораньше и встречаться с богиней1200+ лайков

Я настраиваю Vue в проекте так1100+ лайков

Впереди высокая энергия, это последняя волна боевых навыков Vue, это бесполезно и потрясающе.1000+ лайков

Научись пользоваться Vue JSX, машина старых крестных твоя700+ лайков

Смотрите заработало! Перечитывая руководство по стилю vue 2.0, я сформулировал эти ключевые правила.150+ лайков

Данные не отвечают, это может быть проблема с использованием

На днях друг прислал мне кусок кода и сказалVueимеютbug, он четко написал не проблема, почему данные не отвечают, так и должно бытьVueизbug? Я чувствую, что он более силен, чем Ю Юйси, и не может позволить себе забраться высоко, поэтому игнорирую его. Но это правда, что иногда мы сталкиваемся с невосприимчивостью данных во время разработки, так что же нам делать? Например следующий код:

<template>
  <div>
    <div>
      <span>用户名: {{ userInfo.name }}</span>
      <span>用户性别: {{ userInfo.sex }}</span>
      <span v-if="userInfo.officialAccount">
        公众号: {{ userInfo.officialAccount }}
      </span>
    </div>
    <button @click="handleAddOfficialAccount">添加公众号</button>
  </div>
</template>
<script>
export default {
  data() {
    return {
      userInfo: {
        name: '子君',
        sex: '男'
      }
    }
  },
  methods: {
    // 在这里添加用户的公众号
    handleAddOfficialAccount() {
      this.userInfo.officialAccount = '前端有的玩'
    }
  }
}
</script>

В приведенном выше коде мы хотим добавить атрибут общедоступной учетной записи к информации о пользователе, но черезthis.userInfo.officialAccount = '前端有的玩'После добавления не вступает в силу, почему так?

Это потому, что вVueВнутренне ответ данных выполняется с использованиемObject.definePrototypeслушать каждый ключ объектаgetter,setterМетоды для достижения, но этот метод может слушать только существующее свойство, новое свойство не слушает, но я просто хочу слушать, Сяо Бянь, вы должны сказать это. Следующая небольшая серия предлагает четыре пути, если есть больше способов приветствовать раздел комментариев ниже, чтобы сказать мне.

1. Поместите атрибуты, которые должны были быть добавлены заранее, вdataопределено в

Например, в публичном аккаунте выше я могуuserInfoОн определен внутри, поэтому это не новый атрибут, например следующий

data() {
    return {
      userInfo: {
        name: '子君',
        sex: '男',
        // 我先提前定义好
        officialAccount: ''
      }
    }
  }

2. Замените напрямуюuserInfo

Хотя нельзя датьuserInfoДобавьте новые свойства внутри, но посколькуuserInfoОн уже определен, поэтому я изменяю его напрямуюuserInfoЗначение недостаточно, поэтому его также можно записать следующим образом

this.userInfo = {
  // 将原来的userInfo 通过扩展运算法复制到新的对象里面
  ...this.userInfo,
  // 添加新属性
  officialAccount: '前端有的玩'
}

3. ИспользуйтеVue.set

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

Определение метода Vue.set

/**
* target 要修改的对象
* prpertyName 要添加的属性名称
* value 要添加的属性值
*/
Vue.set( target, propertyName, value )

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

import Vue from 'vue'

// 在这里添加用户的公众号
handleAddOfficialAccount() {
  Vue.set(this.userInfo,'officialAccount', '前端有的玩')
}

Но каждый раз, когда вы используетеsetметод, такжеVueВводить его очень хлопотно, поэтому для простоты,Vueбудет сноваsetметод монтируется наVueнаходится в цепочке прототипов, т.е.Vue.prototype.$set = Vue.set, так что вVueМожет использоваться непосредственно внутри компонентаthis.$setзаменятьVue.set

this.$set(this.userInfo,'officialAccount', '前端有的玩')

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

4. Используйте$forceUpdate

я думаю$forceUpdateСуществование , заставляет многих фронтенд-разработчиков перестать обращать внимание на принцип двусторонней привязки данных, потому что неважно когда, я все равно его модифицируюdataПосле этого позвоните$forceUpdateпозволитVueповторный рендеринг компонентов,bugне будет. Но на самом деле этот метод не рекомендуется, потому что он приведет к большому ненужному потреблению производительности.

особый способ для массивов

На самом деле не только объекты, но и массивы могут не отвечать после модификации данных, например следующий код

<template>
  <div>
    <ul>
      <li v-for="item in list" :key="item">
        {{ item }}
      </li>
    </ul>
    <button @click="handleChangeName">修改名称</button>
  </div>
</template>
<script>
export default {
  data() {
    return {
      list: ['张三', '李四']
    }
  },
  methods: {
    // 修改用户名称
    handleChangeName() {
      this.list[0] = '王五'
    }
  }
}
</script>

Приведенный выше код надеется изменить имя Чжан Саня на Ван Ву. На самом деле это изменение не вступает в силу. Это потому, чтоVueСледующие измененные массивы не могут быть обнаружены:

  1. Когда вы используете индекс для прямой установки элемента, например:this.list[index] = newValue
  2. изменить массивlengthсвойства, такие как:this.list.length = 0

Итак, в приведенном выше примереthis.list[0] = '王五'Ответ данных не может быть запущен, так что мне делать? как упоминалось вышеVue.setа также$forceUpdateможет решить эту проблему, напримерVue.setможно написать так

Vue.set(this.list,0,'王五')

Помимо этих методов,VueМетоды мутации также предусмотрены для массивов

При работе с массивами мы обычно используем множество методов, предоставляемых данными, напримерpush,pop,spliceподожди, вVueОтвет данных можно вызвать, вызвав методы, указанные выше в массиве, чтобы изменить значение массива.Например, приведенный выше код можно изменить на следующий код, чтобы вызвать ответ данных

this.list.splice(0,1,'王五')

На самом деле, еслиVueполагаться только наgetterа такжеsetter, невозможно сделать это в вызове массиваpush,popОтвет данных запускается, когда метод ожидает, поэтомуVueНа самом деле он делает это, перехватывая эти методы и видоизменяя их, обертывая их.

VueМутация-оболочка для следующих методов массива:

  • push
  • pop
  • shift
  • unshift
  • splice
  • sort
  • reverse

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

var original = arrayProto[method];
  def(arrayMethods, method, function mutator () {
    // 将 arguments 转换为数组
    var args = [], len = arguments.length;
    while ( len-- ) args[ len ] = arguments[ len ];
    var result = original.apply(this, args);
    // 这儿的用法同dependArray(value),就是为了取得dep
    var ob = this.__ob__;
    var inserted;
    switch (method) {
      case 'push':
      case 'unshift':
        inserted = args;
        break
      case 'splice':
        inserted = args.slice(2);
        break
    }
    // 如果有新的数据插入,则插入的数据也要进行一个响应式
    if (inserted) { ob.observeArray(inserted); }
   // 通知依赖进行更新
    ob.dep.notify();
    return result
  });

форматирование текста,filterпроще

использоватьfilterУпрощенная логика

Я хочу отображать временную метку какyyyy-MM-DD HH:mm:ssЧто насчет формата? Нужно ли форматировать дату в коде перед ее отображением в шаблоне? как ниже

<template>
  <div>
    {{ dateStr }}
    <ul>
      <li v-for="(item, index) in getList" :key="index">
        {{ item.date }}
      </li>
    </ul>
  </div>
</template>
<script>
import { format } from '@/utils/date'
export default {
  data() {
    return {
      date: Date.now(),
      list: [
        {
          date: Date.now()
        }
      ]
    }
  },
  computed: {
    dateStr() {
      return format(this.date, 'yyyy-MM-DD HH:mm:ss')
    },
    getList() {
      return this.list.map(item => {
        return {
          ...item,
          date: format(item.date, 'yyyy-MM-DD HH:mm:ss')
        }
      })
    }
  }
}
</script>

Как и в приведенном выше письме, вам нужно вызывать для каждого поля датыformat, а затем приводить через вычисляемое свойство? Рассмотрите возможность использованияVueкоторый предоставилfilterчтобы упростить

<template>
  <div>
    <!--使用过滤器-->
    {{ dateStr | formatDate }}
    <ul>
      <li v-for="(item, index) in list" :key="index">
        <!--在v-for中使用过滤器-->
        {{ item.date | formatDate }}
      </li>
    </ul>
  </div>
</template>
<script>
import { format } from '@/utils/date'
export default {
  filters: {
    formatDate(value) {
      return format(value, 'yyyy-MM-DD HH:mm:ss')
    }
  },
  data() {
    return {
      date: Date.now(),
      list: [
        {
          date: Date.now()
        }
      ]
    }
  }
}
</script>

С вышеуказанной модификацией все намного проще?

зарегистрировать глобальныйfilter

Некоторые фильтры используются очень часто, например упомянутый выше фильтр даты, который используется во многих местах. В настоящее время было бы излишним определять его в каждом используемом компоненте. Можно рассмотреть егоVue.filterЗарегистрировать глобальный фильтр

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

// filters\index.js

import Vue from 'vue'
import { format } from '@/utils/date'

Vue.filter('formatDate', value => {
  return format(value, 'yyyy-MM-DD HH:mm:ss')
})

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

<template>
  <div>
    <!--使用过滤器-->
    {{ dateStr | formatDate }}
    <ul>
      <li v-for="(item, index) in list" :key="index">
        <!--在v-for中使用过滤器-->
        {{ item.date | formatDate }}
      </li>
    </ul>
  </div>
</template>
<script>
export default {
  data() {
    return {
      date: Date.now(),
      list: [
        {
          date: Date.now()
        }
      ]
    }
  }
}
</script>

Это проще

Разработали библиотеку плагинов, давайте ее установим

используя некоторыеUIрамки, часто необходимо использоватьVue.useдля установки, например, с помощьюelement-uiИногда пишут так:

import Vue from 'vue';
import ElementUI from 'element-ui';
import 'element-ui/lib/theme-chalk/index.css';
Vue.use(ElementUI,{size: 'small'});

использовалVue.useПозже,element-uiВы можете использовать его прямо в компоненте, это потрясающе (ба, ублюдок). Далее реализуем упрощенную версиюelementДавайте посмотрим, как его установить.

К пониманиюVue.useПрименение

Vue.useэто глобальный метод, его нужно вызывать, когда выnew Vue()сделать перед запуском приложения,Vue.useПараметры следующие

/**
* plugin: 要安装的插件 如 ElementUI
* options: 插件的配置信息 如 {size: 'small'}
*/
Vue.use(plugin, options)

моделированиеelement-uiлогика установки

Подумайте об этом, используйтеVue.use(ElementUI,{size: 'small'})Что мы можем использовать позжеelement-uiчто предложить

  1. можно использовать непосредственно в компонентеelement-uiкомпоненты, больше неimport
  2. можно использовать напрямуюv-loadingинструкция
  3. пройти черезthis.$loadingотображать в компонентеloading
  4. разное...
// 这个是一个按钮组件
import Button from '@/components/button'

// loading 指令
import loadingDirective from '@/components/loading/directive'

// loading 方法
import loadingMethod from '@/components/loading'

export default {
  /**
   * Vue.use 需要插件提供一个install方法
   * @param {*} Vue Vue
   * @param {*} options 插件配置信息
   */
  install(Vue, options) {
    console.log(options)
    // 将组件通过Vue.components 进行注册
    Vue.components(Button.name, Button)

    // 注册全局指令
    Vue.directive('loading', loadingDirective)

    // 将loadingMethod 挂载到 Vue原型链上面,方便调用
    Vue.prototype.$loading = loadingMethod
  }
}

Через приведенный выше код реализована нищенская версияelement-uiплагин, вы можете тогдаmain.jsпройти внутрьVue.useПлагин установлен. У вас могут возникнуть вопросы, почему я использую этот способ записи, и я все еще могу реализовать функцию без этого способа записи. Я думаю, что у этого способа письма есть два преимущества.

  1. Стандартизация, предоставив унифицированную модель разработки, как для плагинов разработчиков, либо пользователей, есть норму для последующей деятельности.
  2. кэш плагинов,Vue.useПри установке плагина он кэшируется, то есть если плагин устанавливается несколько раз, он вступит в силу только при первой установке.

Сценарии применения подключаемых модулей

  1. Добавьте глобальный метод или свойство.
  2. Добавляйте глобальные ресурсы: директивы/фильтры/переходы и т.д.
  3. Добавьте некоторые параметры компонента через глобальные миксины.
  4. Добавьте метод экземпляра Vue, добавив их вVue.prototypeпонял выше.
  5. Библиотека, которая предоставляет собственный API, предоставляя при этом одну или несколько функций, упомянутых выше. Такие какelement-ui

Улучшите производительность рендеринга Vue, узнайте об Object.freeze

Когда экземпляр Vue создан, онdataВсе свойства объекта добавляются в Vue.Отзывчивая системасередина. Когда значение этих свойств изменяется, представление «отвечает», обновляя соответствие до нового значения. Однако на самом деле этот процесс относительно требователен к производительности, поэтому для некоторых интерфейсов, которые имеют большой объем данных, но только отображаются, нет необходимостиpropertyДобавить в отзывчивую систему, которая может улучшить производительность рендеринга, как это сделать, нужно знатьObject.freeze.

существуетVueНа официальном сайте есть такой пассаж: Единственное исключение здесь - использоватьObject.freeze(), что предотвращает изменение существующих свойств, а также означает, что система реагирования больше не можетотслеживатьРазнообразие. Что означает этот отрывок, если наши данные используютObject.freezeВы можете выпустить данные из системы реагирования, тогда как вы это сделаете?

Например, следующая таблица, поскольку это только данные рендеринга, в настоящее время мы можем передатьObject.freezeоптимизировать производительность

<template>
  <el-table :data="tableData" style="width: 100%">
    <el-table-column prop="date" label="日期" width="180" />
    <el-table-column prop="name" label="姓名" width="180" />
    <el-table-column prop="address" label="地址" />
  </el-table>
</template>
<script>
export default {
  data() {
    const data = Array(1000)
      .fill(1)
      .map((item, index) => {
        return {
          date: '2020-07-11',
          name: `子君${index}`,
          address: '大西安'
        }
      })
    return {
      // 在这里我们用了Object.freeze
      tableData: Object.freeze(data)
    }
  }
}
</script>

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

export default {
  data() {
    return {
      tableData: []
    }
  },
  created() {
    setInterval(() => {
      const data = Array(1000)
        .fill(1)
        .map((item, index) => {
          // 虽然不能冻结整个数组,但是可以冻结每一项数据
          return Object.freeze({
            date: '2020-07-11',
            name: `子君${index}`,
            address: '大西安'
          })
        })
      this.tableData = this.tableData.concat(data)
    }, 2000)
  }
}

добросовестное использованиеObject.freeze, это может значительно сэкономить производительность рендеринга, особенно для браузера IE, эффект все еще очень очевиден, поторопитесь и попробуйте.

Наконец, если вам нужно разработать мобильный проект сейчас, вы можете узнать о готовом фреймворке, скомпилированном Xiaobian.vue-vant-base, может быть, это может помочь вам

Эпилог

Не истощайте свое вдохновение и воображение, не будьте рабом своих моделей. - Винсент Ван Гог

В этой статье используетсяmdniceнабор текста