предисловие
Эта статья представляет собой публичное изложение ценности вклада Криса Фрица в исходный код vue. Я чувствую, что в этом обмене есть много вещей, из которых стоит поучиться. Хотя часть контента — это то, что я делаю на работе, я все же перевожу ppt из великий бог здесь Я надеюсь, что друзья принесут некоторую помощь.
1. Эффективно используйте непосредственный атрибут часов
Это то, что я написал в проекте, а также. Например, когда есть запрос, который нужно снова инициализировать, выполнить его один раз, а затем отслеживать его изменения, многие пишут так:
created(){
this.fetchPostList()
},
watch: {
searchInputValue(){
this.fetchPostList()
}
}
Мы можем записать вышеизложенное следующим образом:
watch: {
searchInputValue:{
handler: 'fetchPostList',
immediate: true
}
}
2. Регистрации компонентов стоит поучиться
В общем случае наши компоненты записываются следующим образом:
import BaseButton from './baseButton'
import BaseIcon from './baseIcon'
import BaseInput from './baseInput'
export default {
components: {
BaseButton,
BaseIcon,
BaseInput
}
}
<BaseInput v-model="searchText" @keydown.enter="search" />
<BaseButton @click="search"> <BaseIcon name="search"/></BaseButton>
Обычно есть три шага,
Первым шагом является введение,
Второй шаг регистрации,
Третий шаг - официальное использование,
Это также самый распространенный и распространенный способ письма. Но такое написание является классическим, и многие компоненты приходится много раз вводить и прописывать, что очень раздражает.
Мы можем использовать webpack для использования метода require.context() для создания нашего собственного контекста (модуля) для автоматического динамического запроса компонентов.
Идея такова: в main.js в папке src все необходимые базовые компоненты запакованы динамически с помощью webpack.
код показывает, как показано ниже:
import Vue from 'vue'
import upperFirst from 'lodash/upperFirst'
import camelCase from 'lodash/camelCase'
// Require in a base component context
const requireComponent = require.context(
‘./components’, false, /base-[\w-]+\.vue$/
)
requireComponent.keys().forEach(fileName => {
// Get component config
const componentConfig = requireComponent(fileName)
// Get PascalCase name of component
const componentName = upperFirst(
camelCase(fileName.replace(/^\.\//, '').replace(/\.\w+$/, ''))
)
// Register component globally
Vue.component(componentName, componentConfig.default || componentConfig)
})
Таким образом, нам нужен только третий шаг для введения компонентов:
<BaseInput
v-model="searchText"
@keydown.enter="search"
/>
<BaseButton @click="search">
<BaseIcon name="search"/>
</BaseButton>
3. Оптимизируйте внедрение модулей vuex
Для vuex мы выводим хранилище следующим образом:
import auth from './modules/auth'
import posts from './modules/posts'
import comments from './modules/comments'
// ...
export default new Vuex.Store({
modules: {
auth,
posts,
comments,
// ...
}
})
Ввести много модулей, а потом зарегистрироваться в Vuex.Store~~
Упрощенный подход аналогичен описанному выше, но также использует require.context() для чтения файла, код выглядит следующим образом:
import camelCase from 'lodash/camelCase'
const requireModule = require.context('.', false, /\.js$/)
const modules = {}
requireModule.keys().forEach(fileName => {
// Don't register this file as a Vuex module
if (fileName === './index.js') return
const moduleName = camelCase(
fileName.replace(/(\.\/|\.js)/g, '')
)
modules[moduleName] = {
namespaced: true,
...requireModule(fileName),
}
})
export default modules
Итак, нам просто нужен следующий код:
import modules from './modules'
export default new Vuex.Store({
modules
})
В-четвертых, ленивая загрузка роутинга
На данный момент, что касается введения vue, я имел обыкновениеТехнические моменты и резюме рефакторинга проекта VueВ разделе также упоминалось, что компоненты могут быть динамически загружены с помощью require или import().
{
path: '/admin',
name: 'admin-dashboard',
component:require('@views/admin').default
}
или
{
path: '/admin',
name: 'admin-dashboard',
component:() => import('@views/admin')
}
Загрузить маршруты.
Пять, обновление ключевого компонента маршрутизатора
Следующая сцена действительно разбила сердца многим программистам... По умолчанию все используют Vue-router для реализации управления маршрутизацией. Предположим, мы пишем сайт блога и требуется перейти с /post-haorooms/a на /post-haorooms/b. Потом мы с удивлением обнаружили, что данные не обновились после того, как страница перескочила? ! Причина в том, что vue-router «интеллектуально» находит, что это один и тот же компонент, а потом решает повторно использовать этот компонент, поэтому метод, который вы написали в созданной функции, вообще не выполняется. Обычное решение состоит в том, чтобы прослушивать изменения в $route для инициализации данных следующим образом:
data() {
return {
loading: false,
error: null,
post: null
}
},
watch: {
'$route': {
handler: 'resetData',
immediate: true
}
},
methods: {
resetData() {
this.loading = false
this.error = null
this.post = null
this.getPost(this.$route.params.id)
},
getPost(id){
}
}
Ошибка исправлена, но писать это каждый раз слишком некрасиво, верно? Придерживаясь принципа лениться, если можно лениться, мы надеемся написать такой код:
data() {
return {
loading: false,
error: null,
post: null
}
},
created () {
this.getPost(this.$route.params.id)
},
methods () {
getPost(postId) {
// ...
}
}
Решение: добавьте уникальный ключ в router-view, чтобы даже если это общедоступный компонент, при изменении URL-адреса компонент создавался заново.
<router-view :key="$route.fullpath"></router-view>
Примечание: по моему личному опыту, это обычно используется в подмаршрутах, чтобы можно было избежать большого количества перерисовок.Если этот атрибут добавить в корневую директорию app.vue, то каждый раз, когда вы нажимаете, чтобы изменить адрес, он будет перерисован, что не стоит потерь!
Шесть, единственный корневой элемент компонента
Сценарий следующий:
(Emitted value instead of an instance of Error)
Error compiling template:
<div></div>
<div></div>
- Component template should contain exactly one root element.
If you are using v-if on multiple elements, use v-else-if
to chain them instead.
В шаблоне может быть только один div, а не два параллельных div, как указано выше.
Например следующий код:
<template>
<li
v-for="route in routes"
:key="route.name"
>
<router-link :to="route">
{{ route.title }}
</router-link>
</li>
</template>
сообщит об ошибке!
Мы можем использовать функцию рендеринга для рендеринга
functional: true,
render(h, { props }) {
return props.routes.map(route =>
<li key={route.name}>
<router-link to={route}>
{route.title}
</router-link>
</li>
)
}
Семь, упаковка компонентов, проблемы проникновения атрибутов событий
Когда мы пишем компоненты, нам обычно нужно передать серию реквизитов от родительского компонента к дочернему компоненту, а родительский компонент прослушивает серию событий, испускаемых дочерним компонентом. Например:
//父组件
<BaseInput
:value="value"
label="密码"
placeholder="请填写密码"
@input="handleInput"
@focus="handleFocus>
</BaseInput>
//子组件
<template>
<label>
{{ label }}
<input
:value="value"
:placeholder="placeholder"
@focus=$emit('focus', $event)"
@input="$emit('input', $event.target.value)"
>
</label>
</template>
Это не очень лаконично, многие свойства и события определяются вручную, мы можем написать так:
<input
:value="value"
v-bind="$attrs"
v-on="listeners"
>
computed: {
listeners() {
return {
...this.$listeners,
input: event =>
this.$emit('input', event.target.value)
}
}
}
$attrs содержит привязки атрибутов (кроме класса и стиля), которые не распознаются (и не получаются) как реквизиты в родительской области. Когда компонент не объявляет никаких реквизитов, все привязки родительской области включаются сюда и могут быть переданы внутренним компонентам через v-bind="$attrs" .
$listeners содержит прослушиватели событий v-on из родительской области (без декоратора .native). Его можно передать внутренним компонентам через v-on="$listeners" .