1. Селектор действия глубины ( >>> )
Строго говоря, это должна быть функция vue-loader. "vue-загрузчик": "^12.2.0"
При разработке проекта, если бизнес является более сложным, особенно на Тайване или на страницах функций B-стороны, неизбежно будут использоваться сторонние библиотеки компонентов, эти продукты иногда думают, что некоторые пользовательские компоненты области пользовательского интерфейса. Если эти компоненты используются в рамках CSS, родительский компонент сторонних компонентов, стиль которых вы хотите настроить, создает больше проблем.
Селектор действия по глубине (оператор >>>) может вам помочь.
<template>
<div>
<h1 class="child-title">
如果你希望 scoped 样式中的一个选择器能够作用得“更深”,例如影响子组件,你可以使用 >>> 操作
</h1>
</div>
</template>
<script>
export default {
name: 'child',
data() {
return {}
}
}
</script>
<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped>
.child-title {
font-size: 12px;
}
</style>
В дочернем компоненте выше.child-titleОбласть CSS устанавливает размер шрифта 12 пикселей, и теперь я хочу настроить его в родительском компоненте на размер 20 пикселей и красный цвет.
<template>
<div>
<child class="parent-custom"></child>
</div>
</template>
<script>
import Child from './child'
export default {
name: 'parent',
components: {
Child
},
data() {
return {}
}
}
</script>
<style>
.parent-custom >>> .child-title {
font-size:20px;
color: red;
}
</style>
Эффект должным образом должным образом. Но не радуйтесь раньше времени, обратите внимание, что в приведенном выше стиле используется чистый синтаксис css, если грамматика меньше, вы можете получить сообщение об ошибке в веб-пакете.
<style lang="less">
.parent-custom {
>>> .child-title {
font-size:20px;
color: red;
}
}
</style>
ERROR in ./~/css-loader!./~/vue-loader/lib/style-compiler?{"vue":true,"id":"data-v-960c5412","scoped":false,"hasInlineConfig":false}!./~/postcss-loader!./~/less-loader!./~/vue-loader/lib/selector.js?type=styles&index=0!./src/components/parent.vue
Module build failed: Unrecognised input
@ /src/components/parent.vue (line 22, column 6)
near lines:
.parent-custom {
>>> .child-title {
font-size:20px;
Решение состоит в том, чтобы использовать менее выходящие (лопаты) и переменную интерполяцию (переменная интерполяция)
<style lang="less">
@deep: ~'>>>';
.parent-custom {
@{deep} .child-title {
font-size:20px;
color: red;
}
}
</style>
2.4.0 Новый
Все мы знаем, что если мы передаем три реквизита a, b и c при использовании подкомпонентов, а подкомпонентыpropsПараметр объявляет только a и b, тогда c будет отображаться в корневом элементе дочернего компонента как пользовательский атрибут html после рендеринга.
Если вы этого не хотите, вы можете установить элемент конфигурации подкомпонентаinheritAttrs:falseКорневой элемент будет намного чище.
<script>
export default {
name: 'child',
props: ['a','b'],
inheritAttrs: false
}
</script>
$attrsа также$listeners
Первый взглядvm.$attrs
vm.$attrs
Тип: {[KEY: String]: String}
только чтение
Содержит привязки свойств (кроме класса и стиля), которые не распознаются (и не получаются) как свойства в родительской области. Когда компонент не объявляет никаких реквизитов, все привязки родительской области (кроме класса и стиля) включаются сюда и могут быть переданы внутренним компонентам через v-bind="$attrs" - очень полезно при создании высокоуровневых компонентов.
Его можно свести к двум пунктам:
vm.$attrsЭто встроенное свойство компонента, а значением являются все значения, переданные родительским компонентом.propне объявленный компонентом вprop(кроме класса и стиля).
Или перед примерами дочерних компонентов
// parent.vue
<template>
<div>
<child
class="parent-custom"
a="a"
b="b"
c="c">
</child>
</div>
</template>
// child.vue
<script>
export default {
name: 'child',
props: ['a','b'],
inheritAttrs: false,
mounted() {
// 控制台输出:
// child:$attrs: {c: "c"}
console.log('child:$attrs:', this.$attrs)
}
}
</script>
Компоненты могут использоваться в своих собственных подкомпонентах.v-bind='attrs', а затем передать значение своим дочерним компонентам. То есть дочерний компонент будетattrsзначение, переданное вpropразберитесь с этим, соблюдая при этом правила пункта 1.
// parent.vue
<template>
<div>
<child
a="a"
b="b"
c="c">
</child>
</div>
</template>
// child.vue
<template>
<div>
<grand-child
v-bind="$attrs"
d="d">
</grand-child>
</div>
</template>
<script>
export default {
name: 'child',
props: ['a','b'],
inheritAttrs: false
}
</script>
// grandchild.vue
<script>
export default {
name: 'grandchild',
props: [],
// props: ['c'],
inheritAttrs: false,
mounted() {
// 控制台输出:
// grandchild:$attrs: {d: "d", c: "c"}
console.log('grandchild:$attrs:', this.$attrs)
// 如果props: ['c']
// 控制台输出:
// grandchild:$attrs: {d: "d"}
}
}
</script>
vm.$listeners
Тип: { [ключ: строка]: функция | массив }
только чтение
Содержит прослушиватель событий v-on из родительской области (без декоратора .native). Его можно передать во внутренние компоненты через v-on=”$listeners” — очень полезно при создании компонентов более высокого уровня.
Его можно свести к двум пунктам:
vm.$listenersявляется встроенным свойством компонента, а его значением является родительский компонент (исключая.nativeдекоратор) прослушиватель событий v-on.Компоненты могут использоваться в своих собственных подкомпонентах.
v-on='$listeners', а затем передать значение своим дочерним компонентам. Если дочерний компонент уже привязанlistenerСлушатель с таким же именем, две функции прослушивателя будут выполняться в пути.
// parent.vue
<template>
<div>
<child @update="onParentUpdate"></child>
</div>
</template>
<script>
export default {
name: 'parent',
components: {
Child
},
methods: {
onParentUpdate() {
console.log('parent.vue:onParentUpdate')
}
}
}
</script>
// child.vue
<template>
<div>
<grand-child
@update="onChildUpdate"
v-on="$listeners">
</grand-child>
</div>
</template>
<script>
export default {
name: 'child',
components: {
GrandChild
},
methods:{
onChildUpdate() {
console.log('child.vue:onChildUpdate')
}
}
}
</script>
// grandchild.vue
<script>
export default {
name: 'grandchild',
mounted() {
// 控制台输出:
// grandchild:$listeners: {update: ƒ}
console.log('grandchild:$listeners:',this.$listeners);
// 控制台输出:
// child.vue:onChildUpdate
// parent.vue:onParentUpdate
this.$listeners.update()
}
}
</script>
3. Параметры компонента обеспечивают/вводят
2.2.0 NEW
Эту пару опций необходимо использовать вместе, чтобы позволить компоненту-предку внедрить зависимость во все его потомки, независимо от того, насколько глубока иерархия компонентов, и она всегда будет действовать, пока устанавливаются отношения восходящего и нисходящего потоков.
//parent.vue
<template>
<div>
<child></child>
</div>
</template>
<script>
export default {
name: 'parent',
provide: {
data: 'I am parent.vue'
},
components: {
Child
}
}
</script>
// child.vue
<template>
<div>
<grand-child></grand-child>
</div>
</template>
<script>
export default {
name: 'child',
components: {
GrandChild
}
}
</script>
// grandchild.vue
<script>
export default {
name: 'grandchild',
inject: ['data'],
mounted() {
// 控制台输出:
// grandchild:inject: I am parent.vue
console.log('grandchild:inject:',this.data);
}
}
</script>
provide 选项应该是一个对象或返回一个对象的函数。 Этот объект содержит свойства, которые можно внедрить в его потомков.
Параметр INJECT должен быть строковым массивом или объектом, представляющим имя локального имени привязки, а Value — ключом к значению Value.
В версии 2.5.0+, когда параметр inject является объектом, вы также можете указать from для представления исходного атрибута и по умолчанию указать значение по умолчанию (если это не примитивное значение, следует использовать фабричный метод).
const Child = {
inject: {
foo: {
from: 'bar',
default: 'foo'
//default: () => [1, 2, 3]
}
}
}
В-четвертых, прицел слот слот-прицел
2.1.0 Новый
В версии 2.5.0+ slot-scope больше не ограничивается элементами шаблона, а может использоваться для любого элемента или компонента внутри слота.
Подробная документация по слотам с ограниченной областью действия. В следующем примере показан сценарий приложения.
Страница списка и страница редактирования отображают одни и те же данные, единственное отличие состоит в том, что разные страницы имеют разную логику обработки данных. Одно и то же отображение данных может быть извлечено в компонент, а различные места могут быть реализованы с помощью слотов области видимости.
// data-show.vue
<template>
<div>
<ul>
<li v-for="item in list">
<span>{{item.title}}</span>
<slot v-bind:item="item">
</slot>
</li>
</ul>
</div>
</template>
// list.vue
<template>
<p>列表页</p>
<data-show :list="list">
<template slot-scope="slotProps">
<span v-if="slotProps.item.complete">✓</span>
<span v-else>x</span>
</template>
</data-show>
</template>
// edit.vue
<template>
<p>编辑页</p>
<data-show :list="list">
<template slot-scope="slotProps">
<a v-if="slotProps.item.complete">查看</a>
<a v-else>修改</a>
</template>
</data-show>
</template>
Пять, захват ошибок Vue
Настройте errorHandler глобально
С 2.2.0 этот крюк будет захватывать крючок жизненного цикла компонента по ошибке.
Начиная с версии 2.4.0, этот хук будет захватывать обработку пользовательских событий Vue внутри ошибки функции.
Более подробное описание можно найти в документации errorHandler.
Ошибка хука жизненного цикла.
2.5.0+ Новый
Более подробное описание можно найти в документации errorCaptured
Если вы знакомы с реагированием, вы обнаружите, что он очень похож на концепцию границ ошибок, и он на самом деле используется.
Vue.component('ErrorBoundary', {
data: () => ({ error: null }),
errorCaptured (err, vm, info) {
this.error = `${err.stack}\n\nfound in ${info} of component`
return false
},
render (h) {
if (this.error) {
return h('pre', { style: { color: 'red' }}, this.error)
}
// ignoring edge cases for the sake of demonstration
return this.$slots.default[0]
}
})
<error-boundary>
<another-component/>
</error-boundary>
Следует подчеркнуть, что errorCaptured не фиксирует собственные ошибки и асинхронные ошибки (например, ошибки, генерируемые сетевыми запросами, событиями мыши и т. д.).
In 2.5 we introduce the new errorCaptured hook. A component with this hook captures all errors (excluding those fired in async callbacks) from its child component tree (excluding itself).