by yugasun from yugasun.com/post/there-ma…Эта статья может быть воспроизведена полностью, но должны быть сохранены первоначальный автор и источник.
Постельное белье с предыдущей статьей, я полагаю, что вы все дороже, новичок в разработке среднего размера упоминается о Vuejs, включая использование основных инструментов Eco-Vuejs (Vue-Router, Vuex) не является проблемой. Но в реальном процессе разработки проекта нам нужно сделать больше, чем просто работа, чтобы завершить наш бизнес-код, после завершения спроса нам также необходимо учитывать больше пост оптимизации, это фокусируется на оптимизированном уровне кода.
Вычисляемые свойства игнорируемых сеттеров
Вернемся к случаю управления состоянием из предыдущей статьи и воспользуемсяvuex
способ поделиться нашимmsg
свойства, сначала создайтеsrc/store/index.js
:
import Vue from 'vue';
import Vuex from 'vuex';
Vue.use(Vuex);
const types = {
UPDATE_MSG: 'UPDATE_MSG',
};
const mutations = {
[types.UPDATE_MSG](state, payload) {
state.msg = payload.msg;
},
};
const actions = {
[types.UPDATE_MSG]({ commit }, payload) {
commit(types.UPDATE_MSG, payload);
},
};
export default new Vuex.Store({
state: {
msg: 'Hello world',
},
mutations,
actions,
});
затем в компонентеcomp1
использовать его в:
<template>
<div class="comp1">
<h1>Component 1</h1>
<input type="text" v-model="msg">
</div>
</template>
<script>
export default {
name: 'comp1',
data() {
const msg = this.$store.state.msg;
return {
msg,
};
},
watch: {
msg(val) {
this.$store.dispatch('UPDATE_MSG', { msg: val });
},
},
};
</script>
такое же правоcomp2
Внесите те же изменения. Конечно ещеsrc/main.js
Представлен в:
import Vue from 'vue';
import App from './App';
import store from './store';
Vue.config.productionTip = false;
/* eslint-disable no-new */
new Vue({
store,
el: '#app',
template: '<App/>',
components: { App },
});
Если вы не знакомы с основами использования vuex, рекомендуется сначала прочитать официальную документацию.
Хорошо, мы достиглиmsg
является общим, и вносятся изменения вwatch
, когда поле ввода изменится, передать$store.dispatch
чтобы вызвать соответствующийUPDATE_MSG
действия Действие для модификации состояния. Но вы найдете модификациюcomp1
в поле ввода черезvue-devtools
Также см. Vuexstate.msg
Он действительно изменился, ноcomp2
Поле ввода не изменилось, конечно, это потому, что мы инициализировалиmsg
Когда это прямое присвоение переменной, а не прослушивание$store.state.msg
изменения, поэтому два компонента не могут быть синхронизированы.
Кто-то скажет это снова, добавьте ещеwatch
собственность, монитор$store.state.msg
Изменить, переназначить компонент вmsg
Нет, это можно сделать, но не слишком ли элегантен этот код для простогоmsg
для синхронизации нам нужно датьdata
Не слишком ли плохо добавлять свойства плюс два слушателя?
На самом деле это очень хорошо решается путем вычисления свойств, потому что компонент в компонентеmsg
зависит$store.state.msg
, мы определяем вычисляемые свойства напрямуюmsg
, а затем вернуть нет.
хорошо, измениcomp1
следующим образом:
<template>
<div class="comp1">
<h1>Component 1</h1>
<input type="text" v-model="msg">
</div>
</template>
<script>
export default {
name: 'comp1',
computed: {
msg() {
return this.$store.state.msg;
},
},
};
</script>
мы снова модифицируемcomp1
В поле ввода откройте консоль, будет сообщено об ошибке:
vue.esm.js?efeb:591 [Vue warn]: Computed property "msg" was assigned to but it has no setter.
...
потому что мы используемv-model
связыватьmsg
На входе при изменении поля ввода он должен срабатыватьmsg
изsetter(赋值)
операция, но вычисляемое свойство поможет мне определить его по умолчаниюgetter
, не определеноsetter
, вот почему появляется вышеуказанное сообщение об ошибке, тогда мы настраиваем его сноваsetter
Бар:
<template>
<div class="comp1">
<h1>Component 1</h1>
<input type="text" v-model="msg">
</div>
</template>
<script>
export default {
name: 'comp1',
computed: {
msg: {
get() {
return this.$store.state.msg;
},
set(val) {
this.$store.dispatch('UPDATE_MSG', { msg: val });
},
},
},
};
</script>
Как видите, мы можем простоsetter
, то есть изменитьmsg
Когда это того стоит, передайте его новое значение в нашvuex
, это не убьет двух зайцев одним выстрелом. та же параcomp2
Внесите те же изменения. Запустите проект, и вы родитесь,comp1 输入框的值
,comp2 输入框的值
а такжеstore 中的值
Достигнуто синхронизированное обновление. И по сравнению с приведенной выше схемой, количество кода также значительно упрощено~
Настраиваемые часы
Давайте сначала посмотрим на код:
// ...
watch: {
username() {
this.getUserInfo();
},
},
methods: {
getUserInfo() {
const info = {
username: 'yugasun',
site: 'yugasun.com',
};
/* eslint-disable no-console */
console.log(info);
},
},
created() {
this.getUserInfo();
},
// ...
Здесь легко понять, что когда компонент создается, он получает информацию о пользователе, затем отслеживает имя пользователя и повторно получает информацию о пользователе после его изменения.Этот сценарий очень распространен в реальной разработке. Так можно ли еще оптимизировать?
Ответ положительный.其实,我们在 Vue 实例中定义watcher
Когда свойство слушателя может быть объектом, оно содержит три свойства:deep
,immediate
,handler
, когда мы обычно определяем его непосредственно в виде функции, Vue автоматически назначит функцию обратного вызоваhandler
, а оставшиеся два значения свойства установлены вfalse
. Сцена здесь может быть использованаimmediate
свойство, установите его вtrue
при создании компонентаhandler
Обратный вызов выполняется немедленно, поэтому мы можем сохранитьcreated
Функция вызывается снова, и реализация выглядит следующим образом:
watch: {
username: {
immediate: true,
handler: 'getUserInfo',
},
},
methods: {
getUserInfo() {
const info = {
username: 'yugasun',
site: 'yugasun.com',
};
/* eslint-disable no-console */
console.log(info);
},
},
Созданная проблема не может быть вызвана изменением URL-адреса, но компонент не изменяется.
Во-первых, маршрутизация проекта по умолчанию осуществляется черезvue-routerРеализовано, а дальше наша маршрутизация похожа на следующую:
// ...
const routes = [
{
path: '/',
component: Index,
},
{
path: '/:id',
component: Index,
},
];
общие компонентыsrc/views/index.vue
код показывает, как показано ниже:
<template>
<div class="index">
<router-link :to="{path: '/1'}">挑战到第二页</router-link><br/>
<router-link v-if="$route.path === '/1'" :to="{path: '/'}">返回</router-link>
<h3>{{ username }} </h3>
</div>
</template>
<script>
export default {
name: 'Index',
data() {
return {
username: 'Loading...',
};
},
methods: {
getName() {
const id = this.$route.params.id;
// 模拟请求
setTimeout(() => {
if (id) {
this.username = 'Yuga Sun';
} else {
this.username = 'yugasun';
}
}, 300);
},
},
created() {
this.getName();
},
};
</script>
Два разных пути используют один и тот же компонентIndex
, а затем в компоненте IndexgetName
функция будет вcreated
При выполнении вы заметите, что давайте переключим маршрут на/1
, наша страница не изменилась,created
Тоже не перезапустился.
Это потому что
vue-router
Он распознает, что два маршрута используют один и тот же компонент, а затем повторно использует его, чтобы компонент не создавался заново, а затемcreated
Периодические функции естественно тоже не срабатывают.
Обычно решение состоит в том, чтобы добавитьwatcher
монитор$route
изменения, а затем повторно выполнитьgetName
функция. код показывает, как показано ниже:
watch: {
$route: {
immediate: true,
handler: 'getName',
},
},
methods: {
getName() {
const id = this.$route.params.id;
// 模拟请求
setTimeout(() => {
if (id) {
this.username = 'Yuga Sun';
} else {
this.username = 'yugasun';
}
}, 300);
},
},
хорошо, проблема решена, но что-то еще нужно изменитьindex.vue
ленивый способ?
просто дайrouter-view
добавить одинkey
свойств, так что даже для одного и того же компонента, но еслиurl
Изменено, Vuejs воссоздает компонент. мы напрямую модифицируемsrc/App.vue
серединаrouter-view
следующим образом:
<router-view :key="$route.fullPath"></router-view>
Забытые $attrs
В большинстве случаев при передаче данных от родительских компонентов к дочерним компонентам мы передаемprops
реализовано, например, в следующем примере:
<!-- 父组件中 -->
<Comp3
:value="value"
label="用户名"
id="username"
placeholder="请输入用户名"
@input="handleInput"
>
<!-- 子组件中 -->
<template>
<label>
{{ label }}
<input
:id="id"
:value="value"
:placeholder="placeholder"
@input="$emit('input', $event.target.value)"
/>
</label>
</template>
<script>
export default {
props: {
id: {
type: String,
default: 'username',
},
value: {
type: String,
default: '',
},
placeholder: {
type: String,
default: '',
},
label: {
type: String,
default: '',
},
},
}
</script>
Такой компонент первого порядка реализовать очень просто, и это не проблема, нам нужно толькоprops
напиши это вid, value, placeholder...
Такое определение свойства прекрасно. Но если подкомпонент содержит подкомпоненты, а также нужно передатьid, value, placeholder...
Шерстяная ткань? Как насчет третьего порядка, четвертого порядка...? Тогда нам нужноprops
Определение повторялось много раз, как это можно терпеть?
тогдаvm.$attrsОн готов к дебюту, давайте сначала посмотрим на официальное объяснение:
Содержит привязки свойств (кроме класса и стиля), которые не распознаются (и не получаются) как реквизиты в родительской области. Когда компонент не объявляет никаких реквизитов, все привязки родительской области (кроме класса и стиля) включаются сюда и могут быть переданы внутренним компонентам через v-bind="$attrs" -Полезно при создании высокоуровневых компонентов.
Автор также подчеркивает在创建高级别的组件时非常有用
, он должен решить проблему, которую я только что упомянул. Это не сложно, так что давайте использовать его быстро.Код модифицируется следующим образом:
<!-- 父组件中 -->
<Comp3
:value="value"
label="用户名"
id="username"
placeholder="请输入用户名"
@input="handleInput"
>
<!-- 子组件中 -->
<template>
<label>
{{ $attrs.label }}
<input
v-bind="$attrs"
@input="$emit('input', $event.target.value)"
/>
</label>
</template>
<script>
export default {
}
</script>
Разве это не выглядит намного чище, и даже если аналогичные подкомпоненты будут снова упоминаться в подкомпонентах, мы не боимся. потому что$attrs
, где не закажешь, где...
Суммировать
Конечно, практические навыки Vuejs — это гораздо больше.Это просто краткое изложение того, с чем люди столкнулись в реальной разработке, и это место, которое многие друзья склонны игнорировать. Если у вас есть лучший метод практики, пожалуйста, прокомментируйте или отправьте мне электронное письмо, чтобы обменяться и учиться вместе.