Vue 内置内容
yuhuo2022-05-14开发库框架库
内置指令
v-text
文本渲染
<template>
<span v-text="msg"></span>
<!-- 等同于 -->
<span>{{msg}}</span>
</template>
<script>
export default {
data() {
return {
msg: '哈哈哈哈'
}
},
};
</script>
v-html
HTML 渲染
<template>
<p v-html="rawHtml"></p>
</template>
<script>
export default {
data() {
return {
rawHtml: '<span style="color: red">红色文本</span>'
}
},
};
</script>
v-bind
属性绑定
<template>
<!-- 单个属性 -->
<div v-bind:id="attrs.id"></div>
<!-- 简写 -->
<div :id="attrs.id"></div>
<!-- 多个属性 -->
<div v-bind="attrs"></div>
<!-- 动态参数 -->
<div v-bind:[attributeName]="attrs.id"></div>
<div :[attributeName]="attrs.id"></div>
</template>
<script>
export default {
data() {
return {
attributeName: "id",
attrs: {
id: 'container',
class: 'wrapper'
}
}
},
};
</script>
类绑定
<template>
<!-- 字符串 -->
<div :class="activeClass"></div>
<!-- 数组 -->
<div :class="[activeClass, errorClass]"></div>
<!-- 对象 -->
<div :class="{ active: classObj.active, error: classObj.error }"></div>
<div :class="classObj"></div>
<!-- 数组 + 对象 -->
<div :class="[{ active: classObj.active }, errorClass]"></div>
</template>
<script>
export default {
data() {
return {
activeClass: 'active',
errorClass: 'error',
classObj: {
active: true,
error: false
},
}
},
};
</script>
样式绑定
<template>
<!-- 对象 -->
<!-- 样式属性名推荐驼峰命名法,也支持原始写法 -->
<div :style="{ borderColor: styleObj.borderColor, 'font-size': styleObj.fontSize }"></div>
<div :style="styleObj"></div>
<!-- 数组 -->
<div :style="[styleObj, styleObj]"></div>
</template>
<script>
export default {
data() {
return {
styleObj: {
borderColor: "red",
fontSize: "30px"
}
}
},
};
</script>
style 中使用变量
<template>
<span> 有开始循环了-开端 </span>
</template>
<script setup>
import { ref } from 'vue'
const color = ref("red");
</script>
<style scoped>
span {
/* 使用 v-bind 绑定变量 */
color: v-bind('color');
}
</style>
v-on
事件绑定
<template>
<!-- 内联事件处理器:JavaScript语句 -->
<div v-on:click="count++"></div>
<!-- 简写 -->
<!-- 使用 $event 变量传入事件对象 -->
<div @click="doSomething($event)"></div>
<!-- 方法事件处理器:方法名 -->
<!-- 默认传入事件对象 -->
<div @click="doSomething"></div>
<!-- 动态参数 -->
<div v-on:[eventName]="doSomething($event)"></div>
<div @[eventName]="doSomething()"></div>
</template>
<script>
export default {
data() {
return {
count: 0,
eventName: "click",
}
},
methods: {
doSomething(event) {
console.log("doSomething");
}
},
};
</script>
事件修饰符
.stop
:调用event.stopPropagation()
,即阻止事件继续传播.prevent
:调用event.preventDefault()
,即阻止浏览器默认行为.self
:当event.target == event.currentTarget
时触发,即触发事件的是元素自身.capture
:在捕获阶段触发.once
:只触发一次.passive
:立即进行浏览器默认行为
<!-- 单个修饰符 -->
<form @submit.prevent="doSomething"></form>
<!-- 链式修饰符 -->
<a @click.stop.prevent="doSomething"></a>
<!-- 只有修饰符 -->
<form @submit.prevent></form>
按键修饰符
.enter
:Enter 键.tab
:Tab 键.delete
: Delete 键和 Backspace 键.esc
:Escape 键.space
:Space 键.up
:ArrowUp 键.down
:ArrowDown 键.left
:ArrowLeft 键.right
:ArrowRight 键- 原生键名的 kebab-case 形式,如 a~z,0~9,+-*/,f1~f12,page-down,num-lock 等
<input @keyup.enter="doSomething" />
<input @keyup.page-down="doSomething" />
系统按键修饰符
.ctrl
.alt
.shift
.meta
.exact
<!-- 按下 Alt + Enter 时触发(即使同时按下其他键也会触发) -->
<input @keyup.alt.enter="doSomething" />
<!-- 仅当按下 Alt + Enter 时触发 -->
<input @keyup.alt.enter.exact="doSomething" />
<!-- 按下 Ctrl 并点击时触发 -->
<button @click.ctrl="doSomething">按钮</button>
<!-- 仅当按下系统按键中的 Ctrl 并点击时触发 -->
<button @click.ctrl.exact="doSomething">按钮</button>
<!-- 仅当没有按下任何系统按键时触发 -->
<button @click.exact="doSomething">按钮</button>
鼠标按键修饰符
.left
.right
.middle
<!-- 按下鼠标中键时触发 -->
<input @mousedown.middle="doSomething" />
<!-- 释放鼠标左键时触发 -->
<input @mouseup.left="doSomething" />
v-model
双向绑定
<template>
<!-- 文本框,字符串类型 -->
<input v-model="message">
<!-- 文本域,字符串类型 -->
<textarea v-model="message"></textarea>
<!-- 单选框,字符串类型 -->
<input type="radio" id="chat" value="chat" v-model="like" />
<label for="chat">聊天</label>
<input type="radio" id="sleep" value="sleep" v-model="like" />
<label for="sleep">睡觉</label>
<!-- 单个复选框,布尔类型 -->
<input type="checkbox" id="sport" v-model="checked" />
<label for="sport">运动</label>
<!-- 单个复选框,字符串类型 -->
<input type="checkbox" id="movie" v-model="like" true-value="yes" false-value="no"/>
<label for="movie">电影</label>
<!-- 多个复选框,数组类型 -->
<input type="checkbox" id="book" value="book" v-model="likeList">
<label for="book">书本</label>
<input type="checkbox" id="game" value="game" v-model="likeList">
<label for="game">游戏</label>
<!-- 单选下拉框,字符串类型 -->
<select v-model="like">
<option>book</option>
<option>game</option>
</select>
<!-- 多选下拉框,数组类型 -->
<select v-model="likeList" multiple>
<option>book</option>
<option>game</option>
</select>
</template>
<script>
export default {
data() {
return {
message: "",
checked: true,
like: "",
likeList: ["book", "game"],
}
},
};
</script>
修饰符
.lazy
:在 change 事件后同步更新而不是 input.number
:自动转换为数字.trim
:自动去除两端的空格
v-if / v-else-if / v-else
条件渲染
<template>
<div v-if="type == 1">A</div>
<div v-else-if="type == 2">B</div>
<div v-else>Not A/B</div>
</template>
<script>
export default {
data() {
return {
type: 1,
},
},
};
</script>
v-show
条件显示
<template>
<p v-show="isShow"></p>
</template>
<script>
export default {
data() {
return {
isShow: true,
},
},
};
</script>
v-for
列表渲染
<template>
<!-- 遍历数组 -->
<div v-for="(item, index) in list">{{ index }} - {{ item.name }}</div>
<!-- 遍历数字 -->
<div v-for="(item, index) in 10">{{ index }} - {{ item }}</div>
<!-- 遍历对象 -->
<div v-for="(value, key, index) in obj">{{ index }} - {{ key }} - {{ value }}</div>
<!-- 变形写法: -->
<!-- 1.解构参数对象 -->
<div v-for="({ name }, index) in list"></div>
<!-- 2.省略索引/键名,省略参数括号 -->
<div v-for="item in list"></div>
<div v-for="value in obj"></div>
<div v-for="value, key in obj"></div>
<!-- 4.of替代in -->
<div v-for="(item, index) of list"></div>
<!-- 通过 key 管理状态 -->
<div v-for="(item, index) in list" :key="item.id"></div>
</template>
<script>
export default {
data() {
return {
list: [
{ id: 1, name: "张三" },
{ id: 2, name: "李四" },
{ id: 3, name: "王五" },
],
obj: {
name: "张三",
age: "18",
sex: "男"
}
}
},
};
</script>
v-pre
跳过该元素及其所有子元素的编译。
<!-- 显示原始双大括号标签及内容 -->
<span v-pre>{{ this will not be compiled }}</span>
v-once
仅渲染元素和组件一次,并跳过之后的更新。
v-cloak
用于隐藏未编译的模板,直到完成。
<template>
<div v-cloak>
{{ message }}
</div>
</template>
<style>
[v-cloak] {
display: none;
}
</style>
v-slot
具名插槽,参考 内置组件 / <Slot>。
内置组件
<Slot>
单插槽
<!-- 父组件 -->
<template>
<div class="parent">
<Child>来自父组件的内容</Child>
</div>
</template>
<script>
import Child from './Child.vue'
export default {
components: { Child },
}
</script>
<!-- 子组件 -->
<template>
<div class="child">
<Slot>默认内容</Slot>
</div>
</template>
<script>
export default {}
</script>
多插槽
<!-- 父组件 -->
<template>
<div class="parent">
<Child>
<!-- 具名插槽 -->
<template v-slot:header>
<h1>头部</h1>
</template>
<!-- 默认插槽,指令简写 -->
<template #default>
<p>主体</p>
</template>
<!-- 动态插槽名:v-slot:[slotName],#[slotName] -->
<template #[slotName]>
<p>尾部</p>
</template>
</Child>
</div>
</template>
<script>
import Child from './Child.vue'
export default {
components: { Child },
data() {
return {
slotName: "footer"
}
}
}
</script>
<!-- 子组件 -->
<template>
<div class="child">
<header>
<Slot name="header"></Slot>
</header>
<main>
<Slot></Slot>
</main>
<footer>
<Slot name="footer"></Slot>
</footer>
</div>
</template>
<script>
export default {}
</script>
<Component>
动态组件
<!-- 父组件 -->
<template>
<div class="parent">
<Component :is="currentTab"></Component>
</div>
</template>
<script>
import Child from './Child.vue'
export default {
components: { Child },
data() {
return {
// 被注册的组件名
currentTab: "Child",
// 导入的组件对象
currentTab: Child,
};
},
}
</script>
<Transition>
过渡触发条件:
- 由
v-if
所带来的条件渲染 - 由
v-show
所带来的条件显示 - 由
<component>
切换的动态组件
过渡 class:
v-enter-from
:元素插入之前添加,插入完成后的下一帧移除v-enter-active
:元素插入之前添加,过渡或动画完成之后移除v-enter-to
:元素插入完成后的下一帧添加,过渡或动画完成之后移除v-leave-from
:离开被触发时添加,下一帧移除v-leave-active
:离开被触发时添加,过渡或动画完成之后移除v-leave-to
:离开被触发时添加的下一帧添加,过渡或动画完成之后移除
配合 CSS 的 transition
<template>
<Transition>
<div class="dialog" v-show="show">
<div class="dialog_box"></div>
</div>
</Transition>
</template>
<style>
/* 设置transition */
.v-enter-active,
.v-leave-active {
transition: 0.5s;
}
/* 设置进入前和离开后的样式 */
.v-enter-from,
.v-leave-to {
opacity: 0;
}
/* 深层级过渡 */
.v-enter-active .dialog_box,
.v-leave-active .dialog_box {
transition: 0.5s;
}
.v-enter-from .dialog_box,
.v-leave-to .dialog_box{
transform: scale(0);
}
</style>
配合 CSS 的 animation
<template>
<!-- 命名过渡,类名 v-xx 改为 name-xx -->
<Transition name="bounce">
<div class="dialog" v-show="show"></div>
</Transition>
</template>
<style>
.bounce-enter-active {
animation: bounce-in 0.5s;
}
.bounce-leave-active {
animation: bounce-in 0.5s reverse;
}
@keyframes bounce-in {
0% {
transform: scale(0);
}
50% {
transform: scale(1.25);
}
100% {
transform: scale(1);
}
}
</style>
JavaScript钩子
<template>
<Transition
@before-enter="onBeforeEnter"
@enter="onEnter"
@after-enter="onAfterEnter"
@enter-cancelled="onEnterCancelled"
@before-leave="onBeforeLeave"
@leave="onLeave"
@after-leave="onAfterLeave"
@leave-cancelled="onLeaveCancelled">
<div class="dialog" v-show="show"></div>
</Transition>
</template>
<script>
export default {
methods: {
onBeforeEnter(el) {
console.log("元素插入前");
},
onEnter(el) {
console.log("元素插入后");
},
onAfterEnter(el) {
console.log("进入过渡完成");
},
onEnterCancelled(el) {
console.log("进入取消");
},
onBeforeLeave(el) {
console.log("离开过渡前");
},
onLeave(el) {
console.log("离开过渡开始");
},
onAfterLeave(el) {
console.log("离开过渡完成,元素移除");
},
onLeaveCancelled(el) {
console.log("离开取消");
},
},
}
</script>
高级配置
<!-- 自定义过渡class,可用于集成其他的第三方 CSS 动画库 -->
<Transition
enter-active-class="animate__animated animate__tada"
leave-active-class="animate__animated animate__bounceOutRight"
>...</Transition>
<!-- 默认根据css规则决定使用 transitionend 或 animationend 事件侦听器,以便知道过渡何时结束 -->
<!-- 同时使用 transition 和 animation 时,需要显式指定类型 -->
<Transition type="animation">...</Transition>
<!-- 显式指定过渡时间 -->
<Transition :duration="550">...</Transition>
<Transition :duration="{ enter: 500, leave: 800 }">...</Transition>
<!-- 初次渲染时过渡 -->
<Transition appear>...</Transition>
<!-- 过渡模式:默认进场离场同时,out-in 离场之后再进场,in-out 进场之后再离场 -->
<Transition mode="out-in">...</Transition>
<TransitionGroup>
过渡组
<template>
<button @click="addItem()">随机添加</button>
<button @click="removeItem()">随机移除</button>
<button @click="sortItem()">随机排序</button>
<!-- 过渡模式不可用 -->
<!-- 默认不会渲染包装器元素,可以通过tag来指定 -->
<TransitionGroup name="list" tag="ul">
<!-- 元素必须设定key -->
<li v-for="item in list" :key="item">{{ item }}</li>
</TransitionGroup>
</template>
<script>
export default {
data() {
return {
list: [1, 2, 3],
num: 4,
};
},
methods: {
addItem() {
return this.list.splice(this.getRoundIndex(), 0, this.num++);
},
removeItem() {
return this.list.splice(this.getRoundIndex(), 1);
},
sortItem() {
for (let i = 0; i < this.list.length; i++) {
this.list.push(...this.removeItem());
}
},
getRoundIndex() {
return Math.floor(Math.random() * this.list.length);
},
},
}
</script>
<style>
.list-move,
.list-enter-active,
.list-leave-active {
transition: all 0.5s ease;
}
.list-enter-from,
.list-leave-to {
opacity: 0;
transform: translateX(30px);
}
.list-leave-active {
position: absolute;
}
</style>
<KeepAlive>
缓存组件实例
<KeepAlive>
<component :is="view" />
</KeepAlive>
包含 include / 排除 exclude
<!-- 以英文逗号分隔的字符串 -->
<KeepAlive include="a,b">
<component :is="view" />
</KeepAlive>
<!-- 正则表达式 (需使用 `v-bind`) -->
<KeepAlive :include="/a|b/">
<component :is="view" />
</KeepAlive>
<!-- 数组 (需使用 `v-bind`) -->
<KeepAlive :include="['a', 'b']">
<component :is="view" />
</KeepAlive>
最大缓存实例数
<KeepAlive :max="10">
<component :is="view" />
</KeepAlive>
生命周期
// 不仅适用于 <KeepAlive> 缓存的根组件,也适用于缓存树中的后代组件
export default {
activated() {
// 在首次挂载、
// 以及每次从缓存中被重新插入的时候调用
},
deactivated() {
// 在从 DOM 上移除、进入缓存
// 以及组件卸载时调用
}
}
<Teleport>
传送门
<div class="main">
<!-- 追加在body中渲染,而非.main中渲染 -->
<Teleport to="body">
<div class="dialog"></div>
</Teleport>
<!-- 禁用传送门 -->
<Teleport :disabled="isMobile">
<div class="dialog"></div>
</Teleport>
</div>