Общеизвестные лазейки в практике vue 001

внешний интерфейс JavaScript Vue.js Babel

предисловие

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

Рекомендуемое время чтения: 15-25 минут


Для получения более интересного контента, пожалуйста, обратите внимание на мою домашнюю страницу Nuggets илиКосмический блог Дхармы Бинга

Вопросы-Ответы

Характерные стили или события для стилей пользовательского интерфейса в циклах for

  • Оценка определенных полей данных в пользовательском интерфейсе (также называемая методом модели данных)

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

<li v-for="item of list" :key="item.id" :class="item.status?'color':''" @click="changeColor(item.id)">{{item.name}}</li>
return {
list:[
{id:1,status:true,name:1111},
{id:2,status:true,name:222}]
}
methods:{
    changeColor(id){
        this.list.map((item)=>{
            if(item.id==id){
            item.status=!item.status;
            }
            return item;
        })
    }
}
  • Передайте соответствующие параметры и источник события, вы можете сделать соответствующие выводы и изменить класс

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

<li v-for="item of list" :key="item.id"  @click="changeColor($event)">{{item.name}}</li>
return {
list:[
{id:1,name:1111},
{id:2,name:222}]
}
changeColor(e){
			let el=e.target;
            if(el.classList.contains("color")){
                el.classList.remove("color")
            }else{
                el.classList.add("color")
            }
}

Использование методов вычисляемых свойств

Описание проблемы: Если ваше вычисляемое свойство зависит от части данных, а поле, соответствующее вашим данным, не объявлено в данных, а объявлено и присвоено при запросе интерфейса, то при запросе интерфейса, хотя данные изменилось, расчет Значение свойства не обновляется.

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

Проблема с порядком выполнения события

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

решение:

1 Обычный план: Нужно, чтобы события щелчка стали @mousedown.prevent, первое сделает щелчки лучше, чем выполнение размытия, последнее предотвратит выполнение размытия.

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

Компоненты изменения параметров маршрута не обновляются

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

Решение: часы слушают роутер

 watch: {
 // 方法1
  '$route' (to, from) { //监听路由是否变化
    if(this.$route.params.articleId){// 判断条件1  判断传递值的变化
      //获取文章数据
    }
  }
  //方法2
  '$route'(to, from) {
    if (to.path == "/page") {    /// 判断条件2  监听路由名 监听你从什么路由跳转过来的
       this.message = this.$route.query.msg     
    }
  }
}

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

Описание проблемы: Использование традиционной функции в таймерах или других асинхронных функциях приводит к тому, что this не указывает на экземпляр vue. Основная причина заключается в проблеме, на которую указывает this. Подробнее см. в моей статье "Magic this".

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

Таймер все еще работает после уничтожения компонента

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

Решение: Уничтожить таймеры или какие-нибудь анимированные js в жизненном цикле уничтожения компонентов

//组件销毁前执行的钩子函数,跟其他生命周期钩子函数的用法相同。
beforeDestroy(){
     //我通常是把setInterval()定时器赋值给this实例,然后就可以像下面这么停止。
    clearInterval(this.intervalId);
},

Регистр имени компонента не соответствует импортированному регистру, что приводит к ошибке

Описание проблемы:

This can lead to unexpected behavior when compiling on a filesystem with other case-semantic.
Use equal casing. Compare these module identifiers:

Решение: Необходимо строго соблюдать капитализацию компонентов, чтобы избежать низкоуровневых ошибок

Динамически добавленный дом не имеет стиля

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

Решения: 1 Когда добавленная часть стиля не слишком велика, и она динамически загружается, ее можно установить на неограниченную

2 Поместите стиль для добавления части dom в тег стиля без области действия.

3 Для добавляемой части при необходимости можно написать еще один компонент vue для разбивки страницы

Расширение : Стили других фреймворков пользовательского интерфейса, представленных в проекте, должны быть незакрытыми, если вы хотите переопределить изменения.Если вы хотите переопределить весь проект, вы можете определить customer-element.scss в src/styles, чтобы переопределить стили переопределения.

Измените данные непосредственно в vue, вид страницы не обновляется

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

    data() { // data数据
        return {
          arr: [1,2,3],
          obj:{
              a: 1,
              b: 2
          }
        };
      },
   // 数据更新 数组视图不更新
    this.arr[0] = 'OBKoro1';
    this.arr.length = 1;
    console.log(arr);// ['OBKoro1'];
    // 数据更新 对象视图不更新
    this.obj.c = 'OBKoro1';
    delete this.obj.a;
    console.log(obj);  // {b:2,c:'OBKoro1'}

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

1 this.$set (массив/объект, который вы хотите изменить, позицию/ключ, который вы хотите изменить, какое значение вы хотите изменить)

this.$set(this.arr, 0, "OBKoro1"); // 改变数组
this.$set(this.obj, "c", "OBKoro1"); // 改变对象

2 Собственные методы массива запускают обновления представления: splice(), push(), pop(), shift(), unshift(), sort(), reverse() Рекомендуется использовать метод splice для лучшей настройки, поскольку слайсы можно удалять/добавлять в любом месте массива.

3 Замените массив Скажем: вы хотите выполнить итерацию по этому массиву/объекту, сделать что-то с каждым элементом и вызвать обновление представления.

    // 文档中的栗子: filter遍历数组,返回一个新数组,用新数组替换旧数组
    example1.items = example1.items.filter(function (item) {
      return item.message.match(/Foo/)
    })

Нужно повторять что-то бездумно

 <div v-for="n in 5">
        <span>这里会被渲染5次,渲染模板{{n}}</span>
     </div>

Использование babel-plugin-transform-runtime

  • Проблемы: этот плагин может быть совместим с большинством грамматик es6 и конвертировать их, но некоторые грамматики не могут быть преобразованы или возникают определенные проблемы.
  1. Когда компоненты загружаются асинхронно, создается избыточность кода полифилла.
  2. Полифилы для глобальных функций и методов экземпляра не поддерживаются. Глобальные функции (такие как Promise, Set, Map) не поддерживаются, а две структуры данных Set и Map не должны широко использоваться всеми, и их влияние невелико. Но влияние промисов может быть больше. Методы экземпляра (например: 'abc'.include('b'), ['1', '2', '3'].find((n) => n и т. д.) не поддерживаются, это ограничение почти отменено Новое для большинства строк и примерно половины массивов. Причина обеих проблем заключается в том, что среда выполнения babel-plugin-transform-runtime использует механизм песочницы для компиляции нашего кода (то есть: не изменяет встроенные объекты среды хоста). Поскольку асинхронные компоненты в конечном итоге компилируются в один файл, даже если одна и та же новая функция используется в нескольких компонентах (например, Object.keys()), в каждой скомпилированной копии файла полифилла будет копия новой функции. Если проект небольшой, вы можете не использовать асинхронную загрузку, но нагрузка на первый экран будет относительно большой.
  • Решение: В целом, babel-plugin-transform-runtime может удовлетворить большинству требований, но если он не соответствует требованиям, рекомендуется использовать полный babel-polyfill.
    • Во-первых, удалите из проекта среду выполнения babel-plugin-transform-runtime и удалите эту зависимость:npm un babel-plugin-transform-runtime -D,
    • Затем измените файл конфигурации babel
      // .babelrc
      {
        //...
        "plugins": [
          // - "transform-runtime"
        ]
        //...
      }
      
    • Затем установите зависимость babel-polyfill:npm i babel-polyfill -D
    • Наконец, импортируйте в файл ввода
      // src/main.js
      import 'babel-polyfill'
      

Проблема со ссылкой на импорт ES6

В ES6 импорт и экспорт модульной системы принимает ссылочный экспорт и импорт (непростой тип данных), то есть, если объект определен в модуле и экспортируется, при импорте и использовании в других модулях импортируемый фактически , это ссылка на переменную (указатель).Если вы измените свойства в объекте, это повлияет на использование других модулей.

Обычно, когда система невелика, мы можем использовать JSON.parse(JSON.stringify(str)) для простого и грубого создания нового объекта данных глубокой копии. Однако, когда имеется много компонентов и высокая степень повторного использования объектов данных, очевидно, возникнут проблемы с производительностью.В настоящее время мы можем рассмотреть возможность использования Immutable.js.

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

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

Динамическая ленивая загрузка компонентов

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

Сценарий проблемы: Тогда проблема, которую нам нужно решить: 0 webpack анализирует путь статически, и невозможно передать переменные напрямую 1 Очень неудобно каждый раз писать строку кода для загрузки компонентов.Возможна ли поддержка написания метода для загрузки компонентов? 2 Следует ли поддерживать различие между производственной средой и средой разработки, поскольку отложенная загрузка в среде разработки приведет к горячим обновлениям и более медленным обновлениям, поэтому среда разработки использует полную загрузку по умолчанию, а производственная среда использует отложенную загрузку

Решение выглядит следующим образом: 1 Путь веб-пакета использует объединение переменных, относительный путь должен быть указан заранее, а затем конкретный путь компонента передается в

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

3 Используйте process.env.NODE_ENV, чтобы определить, какой метод загрузки использовать.

код показывает, как показано ниже: В исходном файле router/index.js определите метод _import, загружающий компоненты.

// router/index.js 
const _import = require('./_import_' + process.env.NODE_ENV)

//使用时
 {
      path: '/',
      name: 'HelloWorld',
      component: _import('HelloWorld')
    },
    
// router/_import_development.js
module.exports = file => require('@/views/' + file + '.vue').default // vue-loader at least v13.0.0+

// router/_import_production.js 如果你加载的vue不是这个路径 请自定义哦
module.exports = file => () => import('@/views/' + file + '.vue')

данные в vue должны быть функцией

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

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

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

Пользовательский компонент с отношениями родительского и дочернего тегов не отображается

Сцены: при настройке компонентов часто необходимо инкапсулировать тег li под ul и тег tr\td под table в качестве пользовательских компонентов, но использование пользовательских компонентов напрямую приведет к тому, что окончательное сгенерированное местоположение будет не таким, как мы хотим. Его теги отображаются вне тега tbody.

Vue.component("row",{
  template:'<tr><td>{{content}}</td></tr>',
  data(){
    return {
      content:'this is a row'
    }
  },
})

решение: Причина в том, что html будет выполнять синтаксический анализ тегов, тег под tbody должен быть tr, и то же самое верно для других. Затем мы можем установить его дочерний тег в исходный тип тега, а затем использовать is="selfComponent" для решения этой проблемы.

<tr is="row"></tr>

расширять:

  • Не размещайте элемент контейнера, который отображает vue в html или body, в противном случае подсказка:Do not mount Vue to <html> or <body> - mount to normal elements instead.
  • Обязательно привяжите атрибут el к тегу html-шаблона при создании нового экземпляра vue.

мусор

Сцены: Хотя vue не рекомендует напрямую манипулировать DOM, в сложных сценариях нам нужно оперировать DOM, чего можно добиться с помощью ref. Например, давайте возьмем простой пример ниже, получим узел dom через ref и получим его содержимое.

решение:

<div @click="handleClick" ref="hello">hello world
  </div>
   handleClick(){
      console.log(this.$refs.hello)
    }
  • Расширенный случай: реализовать добавление счетчика Сценарий: Предположим, у нас есть два экземпляра компонента счетчика, и теперь нам нужно использовать схему ссылок, чтобы получить сумму двух счетчиков.

код показывает, как показано ниже:

  <counter ref="one" @change="handleChange"></counter>
  <counter ref="two" @change="handleChange"></counter>
  <span>{{total}}</span>
  Vue.component("counter",{
  template:"<div @click='change'>{{number}}</div>",
  data(){
  return {
   number:0}  
	},
   methods:{
       change(){
  		this.number++;
         this.$emit("change")
		}       
      }
})
//app父组件方法
  handleChange(){
      this.total=this.$refs.one.number+this.$refs.two.number
    },
  • Расширьте свои знания: Если this.$refs.name является нативным тегом, он получит узел нативного тега, а если это компонент, то получит ссылку на компонент.

  • использование vueRefDemo

Справочная документация