(1)通过 v-bind 函数来使用 JavaScript 中的变量去渲染样式,如果这个变量是响应式数据,就可以很方便地实现样式的切换
<template>
<div>
<h1 @click="add">{{ count }}</h1>
</div>
</template>
<script setup>
import { ref } from "vue";
let count = ref(1);
let color = ref("red");
function add() {
count.value++;
color.value = Math.random() > 0.5 ? "blue" : "red";
}
</script>
<style scoped>
h1 {
color: v-bind(color);
}
</style>
(2)响应式实现原理
(3)响应式机制的进阶用法,那就是可以把一切项目中的状态和数据都封装成响应式的接口,屏蔽了浏览器的 API,对外暴露的就是普通的数据,可以极大地提高我们的开发效率。如:vueuse工具包
(4)组件封装
"★★★★★☆☆☆☆☆".slice(5 - rate, 10 - rate)
1、定义props
let props = defineProps({
value: Number
})
let rate = computed(()=>"★★★★★☆☆☆☆☆".slice(5 - props.value, 10 - props.value)
<template>
<Rate :value="score"></Rate>
</template>
<script setup>
import {ref} from 'vue'
import Rate from './components/Rate1.vue'
let score = ref(3)
</script>
2、事件
let emits = defineEmits('update-rate') // 定义emits
function onRate(num){
emits('update-rate',num)
}
<template>
<h1>你的评分是 {{score}}</h1>
<Rate :value="score" @update-rate="update"></Rate>
</template>
<script setup>
import {ref} from 'vue'
import Rate from './components/Rate1.vue'
let score = ref(3.5)
function update(num){
score.value = num
}
</script>
3、v-model
let props = defineProps({
modelValue: Number,
theme:{type:String,default:'orange'}
})
let emits = defineEmits(['update:modelValue'])
function onRate(num){
emits('update:modelValue',num)
}
<template>
<h1>你的评分是 {{score}}</h1>
<Rate v-model="score"></Rate>
</template>
(5)使用内置的 traisition 组件来控制组件的动画
<transition name="fade">
<h1 v-if="showTitle">你好 Vue 3</h1>
</transition>
标签在进入和离开的时候,会有 fade-enter-active 和 fade-leave-active 的 class,进入的开始和结束会有 fade-enter-from 和 face-enter-to 两个 class。
<style>
.fade-enter-active,
.fade-leave-active {
transition: opacity 0.5s linear;
}
.fade-enter-from,
.fade-leave-to {
opacity: 0;
}
</style>
(6)列表动画: transition-group
1、在 v-for 渲染列表的场景之下,我们使用 transition-group 组件去包裹元素,通过 tag 属性去指定渲染一个元素
2、transition-group 组件还有一个特殊之处,就是不仅可以进入和离开动画,还可以改变定位。就和之前的类名一样,这个功能新增了 v-move 类,在下面的代码中,使用 transition-group 包裹渲染的 li 元素,并且设置动画的 name 属性为 flip-list。然后我们根据 v-move 的命名规范,设置 .flip-list-move 的过渡属性,就实现了列表依次出现的效果了。
<ul v-if="todos.length">
<transition-group name="flip-list" tag="ul">
<li v-for="todo in todos" :key="todo.title">
<input type="checkbox" v-model="todo.done" />
<span :class="{ done: todo.done }"> {{ todo.title }}</span>
</li>
</transition-group>
</ul>
<style>
.flip-list-move {
transition: transform 0.8s ease;
}
.flip-list-enter-active,
.flip-list-leave-active {
transition: all 1s ease;
}
.flip-list-enter-from,
.flip-list-leave-to {
opacity: 0;
transform: translateX(30px);
}
</style>
(7) 页面切换动画
通过 transition 标签控制页面进入和离开的 class。
<router-view v-slot="{ Component }">
<transition name="route" mode="out-in">
<component :is="Component" />
</transition>
</router-view>
(8)javascript动画
1、在 Vue 的 transition 组件里,我们可以分别设置 before-enter,enter和 after-enter 三个函数来更精确地控制动画
2、在下面的代码中,我们首先定义了 animate 响应式对象来控制动画元素的显示和隐藏,并且用 transition 标签包裹动画元素。在 beforeEnter 函数中,通过 getBoundingClientRect 函数获取鼠标的点击位置,让动画元素通过 translate 属性移动到鼠标所在位置;并且在 enter 钩子中,把动画元素移动到初始位置,在 afterEnter 中,也就是动画结束后,把动画元素再隐藏起来,这样就实现了类似购物车的飞入效果
<template>
<span class="dustbin"> 🗑 </span>
<div class="animate-wrap">
<transition @before-enter="beforeEnter" @enter="enter" @after-enter="afterEnter">
<div class="animate" v-show="animate.show">📋</div>
</transition>
</div>
</template>
<script setup>
let animate = reactive({
show: false,
el: null,
});
function beforeEnter(el) {
let dom = animate.el;
let rect = dom.getBoundingClientRect();
let x = window.innerWidth - rect.left - 60;
let y = rect.top - 10;
el.style.transform = `translate(-${x}px, ${y}px)`;
}
function enter(el, done) {
document.body.offsetHeight;
el.style.transform = `translate(0,0)`;
el.addEventListener("transitionend", done);
}
function afterEnter(el) {
animate.show = false;
el.style.display = "none";
}
function removeTodo(e, i) {
animate.el = e.target;
animate.show = true;
todos.value.splice(i, 1);
}
</script>
<style>
.animate-wrap .animate {
position: fixed;
right: 10px;
top: 10px;
z-index: 100;
transition: all 0.5s linear;
}
</style>
(9) 实现业务需求的时候,也是优先使用 template,动态性要求较高的组件使用 JSX 实现。
(10)template 由于语法固定,可以在编译层面做的优化较多,比如静态标记就真正做到了按需更新;而 JSX 由于动态性太强,只能在有限的场景下做优化,虽然性能不如 template 好,但在某些动态性要求较高的场景下,JSX成了标配,这也是诸多组件库会使用 JSX 的主要原因。
(11)现在大部分前端开源项目都使用 TypeScript 构建的原因是因为每个函数的参数、返回值的类型和属性都清晰可见,这就可以极大地提高我们代码的可维护性和开发效率。
(12)Vue 2 中全部属性都挂载在 this 之上,而 this 可以说是一个黑盒子,我们完全没办法预 先知道 this 上会有什么数据,这也是为什么 Vue 2 对 TypeScript 的支持一直不太好的原因。Vue 3 全面拥抱 Composition API 之后,没有了 this 这个黑盒,对 TypeScript 的支持也比 Vue2 要好很多。