Как один из трех интерфейсных фреймворков, vue является обязательным навыком для фронтенд-разработчиков. Так как же систематически изучать и осваивать vue? С этой целью я сделал простое резюме системы системы знаний.Пожалуйста, потерпите меня и исправьте мои недостатки.Если вам это нравится, вы можете поставить большой палец вверх! В этой статье в основном описываются некоторые практические навыки разработки Vue.
связанное предложение
Мониторинг жизненного цикла компонентов
Например, есть родительский компонент Parent и дочерний компонент Child.Если родительский компонент слушает монтирование дочернего компонента, он выполняет некоторую логическую обработку.Традиционный метод записи может быть следующим:
// Parent.vue
<Child @mounted="doSomething"/>
// Child.vue
mounted() {
this.$emit("mounted");
}
Кроме того, есть особенно простой способ, дочерний компонент не нуждается ни в какой обработке, просто нужно слушать через @hook при обращении к родительскому компоненту, код выглядит следующим образом:
<Child @hook:mounted="doSomething" />
<Child @hook:updated="doSomething" />
Конечно, можно прослушивать не только смонтированные, но и другие события жизненного цикла, такие как создание, обновление и т. д.
Первоначальное выполнение часов происходит немедленно.
Наблюдайте и реагируйте на изменения данных в экземплярах Vue. Подобно обратному вызову мониторинга для некоторых данных, обратный вызов будет выполняться для последующих операций при каждом изменении отслеживаемых данных.
Но при просмотре переменной она не будет выполняться при инициализации, как в следующем примере, вам нужно один раз вызвать ее вручную при ее создании.
created() {
this.getList();
},
watch: {
keyWord: 'getList',
}
Вышеприведенный подход можно использовать, но это очень хлопотно.Мы можем добавить атрибут немедленно, чтобы он срабатывал автоматически во время инициализации (не нужно писать created для вызова), и тогда приведенный выше код можно упростить до:
watch: {
keyWord: {
handler: 'getList',
immediate: true
}
}
часы имеют три параметра
-
handler
: значение которого является функцией обратного вызова. То есть функция, которая должна выполняться при обнаружении изменения -
deep
: Его значение истинно или ложно; подтверждает, следует ли внимательно слушать. -
immediate
: его значение истинно или ложно, подтверждая, следует ли выполнять функцию обработчика с текущим начальным значением.
Компоненты изменения параметров маршрута не обновляются
такой жеpath
Параметры маршрутизации меняются при переходе страницы, но у компонента нет соответствующего обновления.
Причина: В основном потому, что параметры сбора данных записаны вcreated
илиmounted
В функции хука маршрутизации при изменении параметров маршрутизации этот жизненный цикл не будет выполняться повторно.
Решение 1:watch
слушать маршрут
watch: {
// 方法1 //监听路由是否变化
'$route' (to, from) {
if(to.query.id !== from.query.id){
this.id = to.query.id;
this.init();//重新加载数据
}
}
}
//方法 2 设置路径变化时的处理函数
watch: {
'$route': {
handler: 'init',
immediate: true
}
}
Решение 2: Для достижения этого эффекта вы можете датьrouter-view
добавить другойkey
, так что даже если это общедоступный компонент, при изменении URL-адреса компонент будет воссоздан.
<router-view :key="$route.fullpath"></router-view>
Отложенная загрузка маршрута
3 способа реализации маршрутизации загрузки по требованию (маршрутизация ленивой загрузки) в проектах Vue:
// 1、Vue异步组件技术:
{
path: '/home',
name: 'Home',
component: resolve => reqire(['path路径'], resolve)
}
// 2、es6提案的import()
const Home = () => import('path路径')
// 3、webpack提供的require.ensure()
{
path: '/home',
name: 'Home',
component: r => require.ensure([],() => r(require('path路径')), 'demo')
}
require.context()
require.context(directory,useSubdirectories,regExp)
- directory: указывает каталог, который нужно получить
- useSubdirectories: извлекать ли подкаталоги
- regExp: Регулярное выражение, соответствующее файлу, обычно имя файла.
Сценарий: если на страницу необходимо импортировать несколько компонентов, исходное письмо:
import titleCom from '@/components/home/titleCom'
import bannerCom from '@/components/home/bannerCom'
import cellCom from '@/components/home/cellCom'
components: {
titleCom, bannerCom, cellCom
}
Таким образом пишется много повторяющегося кода, который можно написать с помощью require.context
const path = require('path')
const files = require.context('@/components/home', false, /\.vue$/)
const modules = {}
files.keys().forEach(key => {
const name = path.basename(key, '.vue')
modules[name] = files(key).default || files(key)
})
components: modules
рекурсивный компонент
- Рекурсивный компонент: компонент может вызывать себя рекурсивно в пределах своего шаблона, просто задайте имя компонента для компонента.
- Однако следует отметить, что необходимо указать условие для ограничения количества, иначе будет выдано сообщение об ошибке: превышен максимальный размер стека
- Рекурсия компонентов используется для разработки некоторых независимых компонентов с определенными неизвестными иерархическими отношениями. Например: каскадные селекторы и древовидные элементы управления.
<template>
<div v-for="(item,index) in treeArr"> {{index}} <br/>
<tree :item="item.arr" v-if="item.flag"></tree>
</div>
</template>
<script>
export default {
// 必须定义name,组件内部才能递归调用
name: 'tree',
data(){
return {}
},
// 接收外部传入的值
props: {
item: {
type:Array,
default: ()=>[]
}
}
}
</script>
Очистить таймер или прослушиватель событий
Потому что некоторые страницы в проекте неизбежно будут сталкиваться с таймерами или мониторингом событий. Однако при выходе с текущей страницы, если таймер не будет очищен вовремя и разумно, это вызовет путаницу в бизнес-логике или даже зависание приложения.В это время необходимо очистить прослушиватель событий таймера, то есть жизненный цикл функция выгрузки (закрытия) страницы, сброс таймера.
methods:{
resizeFun () {
this.tableHeight = window.innerHeight - document.getElementById('table').offsetTop - 128
},
setTimer() {
this.timer = setInterval(() => { })
},
clearTimer() {//清除定时器
clearInterval(this.timer)
this.timer = null
}
},
mounted() {
this.setTimer()
window.addEventListener('resize', this.resizeFun)
},
beforeDestroy() {
window.removeEventListener('resize', this.resizeFun)
this.clearTimer()
}
пользовательский псевдоним пути
Мы также можем добавить наши собственные псевдонимы пути в базовый файл конфигурации.
resolve: {
extensions: ['.js', '.vue', '.json'],
alias: {
'vue$': 'vue/dist/vue.esm.js',
'@': resolve('src'),
'assets': resolve('src/assets')
}
}
Затем, когда мы импортируем компонент, мы можем написать:
// import YourComponent from '/src/assets/YourComponent'
import YourComponent from 'assets/YourComponent'
Это не только решает проблему слишком длинных путей, но также решает проблемы относительных путей.
Динамически изменять стиль дома
Причина: потому что стили, которые мы пишем в файле .vue, будут добавляться с ограниченной областью действия. Таким образом, стиль в шаблоне dom может вступить в силу, но окончательный стиль после того, как он вступит в силу, будет не тем именем стиля, которое мы написали, а закодированным. Например:
<template>
<div class="box">dom</div>
</template>
<style lang="scss" scoped>
.box {
background: red;
}
</style>
Vue переводит код в следующий, поэтому стиль DOM-структуры, который мы склеили в js, не подействует.
.box[data-v-11c6864c]{ background:red; }
<template>
<div class="box" data-v-11c6864c>dom</div>
</template>
Решение. Запишите стиль, который нужно изменить, в теге стиля без области действия.
Оптимизация производительности длинного списка
Мы все должны знать, что vue перехватит данные через object.defineProperty, чтобы реализовать реакцию представления на изменения данных.Однако иногда наши компоненты представляют собой чистое отображение данных, и изменений не будет.Нам не нужен vue, чтобы перехватить наши данные, в случае отображения большого объема данных это может существенно сократить время инициализации компонента.
Таким образом, мы можем заморозить объект с помощью метода object.freeze.После того, как объект будет заморожен, Vue не захватит данные.
export default {
data: () => ({
list: []
}),
async created() {
const list = await axios.get('xxxx')
this.list = Object.freeze(list)
},
methods: {
// 此处做的操作都不能改变list的值
}
}
Кроме того, следует отметить, что здесь замораживается только значение списка, а ссылка не будет заморожена.Когда нам нужны реактивные данные, мы можем переназначить список.
Распространение контента (слот)
Слот-слот также является частью HTML-шаблона для компонента, отображать этот шаблон или нет, и как его отображать, определяет родительский компонент. На самом деле, здесь указаны две основные проблемы слота: отображать ли его и как отображать.
слот по умолчанию
Существует также одиночный слот и анонимный слот.Этот тип слота не имеет определенного имени, и компонент может иметь только один слот этого типа.
<!-- 父组件 parent.vue -->
<template>
<div class="parent">
<h1>父容器</h1>
<child>
<div class="tmpl">
<span>菜单1</span>
</div>
</child>
</div>
</template>
<!-- 子组件 child.vue -->
<template>
<div class="child">
<h1>子组件</h1>
<slot></slot>
</div>
</template>
именованный слот
Анонимные слоты не имеют атрибута имени, поэтому их называют анонимными слотами. Затем к слоту добавляется атрибут имени, и он становится именованным слотом. Именованные слоты могут появляться в компоненте N раз и появляться в разных позициях, просто используйте разные атрибуты имени, чтобы различать их.
<!-- 父组件 parent.vue -->
<template>
<div class="parent">
<h1>父容器</h1>
<child>
<div class="tmpl" slot="up">
<span>菜单up-1</span>
</div>
<div class="tmpl" slot="down">
<span>菜单down-1</span>
</div>
<div class="tmpl">
<span>菜单->1</span>
</div>
</child>
</div>
</template>
<!-- 子组件 child.vue -->
<template>
<div class="child">
<!-- 具名插槽 -->
<slot name="up"></slot>
<h3>这里是子组件</h3>
<!-- 具名插槽 -->
<slot name="down"></slot>
<!-- 匿名插槽 -->
<slot></slot>
</div>
</template>
слот с прицелом
Слот с областью действия может быть слотом по умолчанию или именованным слотом.Разница в том, что слот с областью действия может привязывать данные к тегу слота, чтобы его родительский компонент мог получать данные дочернего компонента.
<!-- parent.vue -->
<template>
<div class="parent">
<h1>这是父组件</h1>
<child
>>
<template slot="default" slot-scope="slotProps">
{{ slotProps.user.name }}
</template> </child
>>
</div>
</template>
<!-- 子组件 child.vue -->
<template>
<div class="child">
<h1>这是子组件</h1>
<slot :user="user"></slot>
</div>
</template>
<script>
export default {
data() {
return {
user: {
name: '小赵'
}
}
}
}
</script>