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>

通过 key 管理状态open in new window

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>
Last Updated 2024/3/14 09:51:53