Las características avanzadas vue de la prueba regular (puntos de conocimiento)
1. Modelo v personalizado
<template>
<div>
<p>vue 高级特性</p>
<hr>
<!-- 自定义 v-model -->
<p>{{name}}</p>
<CustomVModel v-model="name"/>
<MixinDemo/>
</div>
</template>
<script>
export default {
components: {
CustomVModel
},
data() {
return {
name: 'name'
}
}
}
</script>
Color selector de enlace de datos bidireccional
customVModel.vue
<template>
<!-- 例如:vue 颜色选择 -->
<input type="text"
:value="text1"
@input="$emit('change1', $event.target.value)">
<!--
1. 上面的 input 使用了 :value 而不是 v-model
2. 上面的 change1 和 model.event1 要对应起来
3. text1 属性对应起来
-->
</template>
<script>
export default {
model: {
prop: 'text1', // 对应 props text1
event: 'change1'
},
props: {
text1: String,
default() {
return ''
}
}
}
</script>
2. $ nextTick
vue es renderizado asíncrono,
Después de que los datos cambien, el DOM no se representará de inmediato,
$ nextTick se activará después de la representación DOM para obtener el último nodo DOM
<template>
<div id="app">
<ul ref="ul1">
<li v-for="(item, index) in list" :key="index">
{{item}}
</li>
</ul>
<button @click="addItem">添加一项</button>
</div>
</template>
<script>
export default {
name: 'app',
data() {
return {
list: ['a', 'b', 'c']
}
},
methods: {
addItem() {
this.list.push(`${Date.now()}`)
this.list.push(`${Date.now()}`)
this.list.push(`${Date.now()}`)
// 1. 异步渲染,$nextTick 待 DOM 渲染完再回调
// 2. 页面渲染时会将 data 的修改做整合,多次 data 修改只会渲染一次(使用一次$nextTick)
this.$nextTick(() => {
// 获取 DOM 元素
const ulElem = this.$refs.ul1
// eslint-disable-next-line
console.log( ulElem.childNodes.length )
})
}
}
}
</script>
(Defina ref = " ul1 " en el elemento DOM , entonces puede usar esto. $ Refs.ul1 para obtener el elemento DOM)
El efecto de no usar $ nextTick: haga clic una vez para generar 3, haga clic en el segundo para generar 6
Para obtener el resultado de renderizado inmediatamente después de hacer clic: use $ nextTick
3. ranura
El rol de la ranura del componente: el componente primario pasa el contenido al componente secundario (el contenido de la plantilla)
Ubicación de la ranura: ubicada en la plantilla del subcomponente
(1) Uso básico
<template>
<div>
<p>vue 高级特性</p>
<!-- slot -->
<SlotDemo :url="website.url">
{{website.title}}
</SlotDemo>
</div>
</template>
<script>
import SlotDemo from './SlotDemo'
export default {
components: {
SlotDemo
},
data() {
return {
name: '姓名',
website: {
url: 'http://imooc.com/',
title: 'imooc',
subTitle: '程序员的梦工厂'
}
}
}
}
</script>
SlotDemo.vue
<template>
<a :href="url">
<slot>
显示默认内容,即父组件没设置内容时
</slot>
</a>
</template>
<script>
export default {
props: ['url'],
data() {
return {}
}
}
</script>
(Efecto: el enlace se mostrará en forma de etiqueta y mostrará el contenido del título)
(2) Ranura de alcance
<template>
<a :href="url">
<slot :slotData="website">
{{website.subTitle}} <!-- 父组件不传内容时默认值显示 subTitle -->
</slot>
</a>
</template>
<script>
export default {
props: ['url'],
data() {
return {
website: {
url: 'http://wangEditor.com/',
title: 'wangEditor',
subTitle: '轻量级富文本编辑器'
}
}
}
}
</script>
(Si no se pasa el valor {{website.subTitle}} } , se mostrará el subtítulo predeterminado del subcomponente)
Uso : los datos de ámbito en el componente secundario permiten que el componente primario lo obtenga
<ScopedSlotDemo :url="website.url">
<template v-slot="slotProps">
{{slotProps.slotData.title}}
</template>
</ScopedSlotDemo>
Efecto: la página muestra el contenido del subcomponente wangEditor
(Pensamientos: defina el atributo dinámico slotData en el espacio, y luego defínalo en el sitio web, que contiene el título y el subtítulo. Luego use ScopedSlotDemo en el índice para definir v-slot = " slotProps " . Luego puede usar slot Props.slot DaTa Obtenga el contenido del sitio web en el componente ScopedSlotDemo, para que pueda obtener el título del sitio web)
(3) Ranura nombrada
La coincidencia de ranuras con nombre basada en el contenido, ningún nombre coincidirá de manera predeterminada
Cuando el componente principal pasa el contenido al componente secundario, debe corresponder al buen nombre
4. Componentes dinámicos y componentes asincrónicos.
(1) Componentes dinámicos
Uso: : is = " nombre-componente "
Escenas que deben renderizarse dinámicamente en función de los datos. Es decir, el tipo de componente no está determinado. (Generalmente, se determina el tipo de componente)
Escenario de uso de ejemplo: página de detalles de noticias. (La posición o el tipo del componente es incierto. Es decir, no sabe qué tipo de componente representar, solo los datos. Debe determinar el tipo de componente en función de los datos, luego debe usar el componente dinámico)
<template>
<div>
<p>vue 高级特性</p>
<!-- 动态组件 -->
<!-- <component :is="NextTickName"/> -->
<div v-for="(index, value) in newsData" :key="index">
<component :is="value.type"></component>
</div>
</div>
</template>
<script>
export default {
data() {
return {
name: 'name',
// NextTickName: "NextTick",
newsData: {
1: {type: 'text'},
2: {type: 'text'},
3: {type: 'image'},
}
}
}
}
</script>
(Render basado en los componentes adquiridos (texto, imagen))
(2) componentes asincrónicos
Función de importación
Cargue componentes grandes a pedido y de forma asincrónica
(Cada vez que lo usa, lo carga en cualquier momento. Si no lo usa, nunca se cargará. Es adecuado para componentes más grandes y complejos, lo que optimizará el rendimiento)
Use la declaración import SlotDemo from './SlotDemo' para cargar sincrónicamente
<!-- 异步组件 -->
<FormDemo v-if="showFormDemo"/>
<button @click="showFormDemo = true">show form demo</button>
// 然后在components里面写
components: {
FormDemo: () => import('../BaseUse/FormDemo'),
}
Efecto: FormDemo no se cargará cuando no haya clic, se cargará y se representará después de hacer clic
5. mantener vivo
Componente de caché
Cambio frecuente, no es necesario repetir el renderizado
Vue optimización de rendimiento común
KeepAlive.Vue presenta tres componentes KeepAliveAtageA, KeepAliveAtageB, KeepAliveAtageC son tres botones
Haga clic en el efecto BC a su vez:
No use mantener vivo |
Use keepalive |
Un montado Un destruido B montado B destruido C montado C destruido Un montado |
Un creado B creado C creado |
<KeepAliveStageA v-if = "state === 'A'" /> <KeepAliveStageB v-if = "state === 'B'" /> <KeepAliveStageC v-if = "state === 'C'" />
|
<keep-alive> <! - tab 切换 -> <KeepAliveStageA v-if = "state === 'A'" /> <KeepAliveStageB v-if = "state === 'B'" /> <KeepAliveStageC v-if = "state === 'C'" /> </keep-alive> |
La diferencia entre usar keep-alive y v-show:
v-show está controlado por CSS nativo (uso: las etiquetas son relativamente simples)
Keepalive es la representación de objetos JS a nivel de marco vue (caso de uso: cambio de componentes complejos con cambio de nivel o tabulación)
<template>
<div>
<button @click="changeState('A')">A</button>
<button @click="changeState('B')">B</button>
<button @click="changeState('C')">C</button>
<keep-alive> <!-- tab 切换 -->
<KeepAliveStageA v-if="state === 'A'"/> <!-- v-show -->
<KeepAliveStageB v-if="state === 'B'"/>
<KeepAliveStageC v-if="state === 'C'"/>
</keep-alive>
</div>
</template>
<script>
import KeepAliveStageA from './KeepAliveStateA'
import KeepAliveStageB from './KeepAliveStateB'
import KeepAliveStageC from './KeepAliveStateC'
export default {
components: {
KeepAliveStageA,
KeepAliveStageB,
KeepAliveStageC
},
data() {
return {
state: 'A'
}
},
methods: {
changeState(state) {
this.state = state
}
}
}
</script>
keepAliveStateA.vue
<template>
<p>state A</p>
</template>
<script>
export default {
mounted() {
// eslint-disable-next-line
console.log('A mounted')
},
destroyed() {
// eslint-disable-next-line
console.log('A destroyed')
}
}
</script>
6. mixin
Múltiples componentes tienen la misma lógica, extraída de ellos
Mixin no es la solución perfecta, habrá problemas
La composición API propuesta por Vue 3 tiene como objetivo resolver estos problemas
(Mixin es una pieza de código js)
Problemas con Mixin
(1) La fuente de la variable es desconocida, lo que no es propicio para la lectura
(2) Múltiples mixins pueden causar conflictos de nombres
(3) Puede haber una relación de muchos a muchos entre Mixin y los componentes, con alta complejidad
<template>
<div>
<p>{{name}} {{major}} {{city}}</p>
<button @click="showName">显示姓名</button>
</div>
</template>
<script>
import myMixin from './mixin'
export default {
mixins: [myMixin], // 可以添加多个,会自动合并起来
data() {
return {
name: 'zs',
major: 'web'
}
},
methods: {
},
mounted() {
// eslint-disable-next-line
console.log('component mounted', this.name)
}
}
</script>
mixin.js
export default {
data() {
return {
city: '北京'
}
},
methods: {
showName() {
// eslint-disable-next-line
console.log(this.name)
}
},
mounted() {
// eslint-disable-next-line
console.log('mixin mounted', this.name)
}
}