Appearance
vue技术
🚀 基础
sh
# 安装
npm create vue@latest
# 项目打包
npm run build
# 打包项目预览
npm run preview
# 响应式数据
ref、reactive
# 计算属性
computed
# 监听元素
watch(value,(new,old)=>{})
# 渲染
:class
# 双向绑定
v-model="text"
# 组件创建完成初始化生命周期
onMounted
# 全局变量,main.js挂载
app.provide('$text',"成功");
# 使用
import { inject } from "vue";
const text = inject("$text");万能的ref
- 可以获取到绑定元素的内容和方法
- 可以获取到组件实例
js
<div ref="divRef">这是一个 div 元素</div>
<script setup>
import { ref, onMounted } from 'vue'
const divRef = ref(null)
onMounted(() => {
console.log(divRef.value) // 输出: <div>这是一个 div 元素</div>
divRef.value.style.color = 'red' // 修改 div 元素的样式
// 如果divRef绑定了函数,则可以调用
})
</script>nextTick等待渲染完成
- 在 Vue 中,DOM 的更新是异步的,这意味着当你在数据变化后立即访问 DOM,可能无法获取到最新的 DOM 状态。为了确保在 DOM 更新后执行代码,可以使用
nextTick函数。
js
// 示例:理解 Vue 的异步更新机制
import { ref, nextTick } from 'vue'
const count = ref(0)
const updateCount = () => {
count.value++ // 数据更新
// 此时 DOM 还未更新
console.log('同步代码:', document.querySelector('p').textContent) // 还是旧值
nextTick(() => {
// DOM 已经更新
console.log('nextTick中:', document.querySelector('p').textContent) // 新值
})
}- 使用办法:
js
1.
const updateMessage = async () => {
// 更新数据
nextTick(() => {
console.log('DOM 已更新')
// 可以在这里进行 DOM 操作
})
}
2.(推荐)
async function updateDOM() {
// 更新数据...
await nextTick()
console.log('DOM 更新完成')
// 进行 DOM 操作
}js动态修改元素属性
- :style=""
js
<div :style="bj">这是一个 div 元素</div>
const bj = {
backgroundColor: "red", // 横线后面大写,比如:background-color等于backgroundColor
};🎯 组件
js
# 全局注册组件(main.js)
app.component('MyComponent', MyComponent)js
# 父传子————
<component value="传递数据"/>
# 子组件接收
import { defineProps } from 'vue'
const props = defineProps(['value'])
console.log(props.value)js
# 父组件调用子组件事件/父组件获取子组件的数据————
// 子组件:
const open = () => {
console.log('open')
}
const value = ref(0)
defineExpose({ open, value }) // 把方法暴露出去
// 父组件:
<component ref="show"/> // 获取子组件实例
const show = ref(null)
const open = () => {
show.value.open() // 调用子组件方法
show.value.value() // 获取子组件数据
}- 当点击子组件的事件时,会触发父组件的点击事件,从而实现子组件向父组件传递数据
js
# 子传父/子触发父事件————
// 子组件:
import { defineEmits } from "vue";
// 定义可触发的事件
<button @click="but">触发自定义事件</button>
const emit = defineEmits(["custom"]);
const but = () => {
// 触发事件并传递数据
console.log("触发事件");
const message = "子组件传递的数据";
emit("custom",message);
};
// 父组件:
<component @custom="customData"/> // 监听子组件自定义事件
const customData = (data) => {
console.log(data.message);
};🌈 插槽
- 父组件可以传递任何内容给子组件
js
// 单插槽
父组件:
<button><slot></slot></button>
子组件:
<buttonComponenst/>这里可以放任何内容</buttonComponenst>
// 多插槽
子组件:
<button><slot name="slot1"></slot></button>
父组件:
<template #slot1>
插槽1的内容放这里
</template>自定义指令
js
const custom = {
// mounted是指令被绑定到元素上时调用
mounted: (el, binding) => {
const { value } = binding.value // 获取到指令绑定的值,比如 v-custom="color"
el.XXX = "自定义指令做什么,这可以用于直接操作 DOM"
// 例:el.style.color = red
}
}
// 使用案例:<div v-custom="{ color: 'red' }"></div>
// 全局注册 v-color,动态设置文本颜色
app.directive('color', (el, binding) => {
el.style.color = binding.value
})组件切换缓存
- 在引入组件包裹KeepAlive标签,当组件切换时,组件不会被销毁,而是缓存起来
js
<KeepAlive :max="10"> // 设置最大缓存数
<component :is="activeComponent" />
</KeepAlive>✅ 路由
404页面
js
{
path: '/:pathMatch(.*)',
component: '/error',
}路由配置
js
// 嵌套路由
children: [
{ path: '/', name: 'user', component: UserHome }
]
// 路由元信息
meta: { requiresAuth: true,title:"页面名字" }
// 路由跳转
import { useRouter } from 'vue-router'
const router = useRouter();
router.push({ path: '/indexView', query: { id: 123 } });
// 路由接收
import { useRoute } from 'vue-router'
const route = useRoute();
const id = route.query.id;
// 返回一条记录
router.go(-1)路由守卫
js
// 全局前置路由
router.beforeEach((to, from, next) => { }
to:将要进入的路由
from:离开的路由
next():进入路由
next(false):中断当前导航
next('路径'):强行跳转路由说始终跳转到页面顶部
js
const router = createRouter({
scrollBehavior (to, from, savedPosition) {
return { top: 0 }
}
})nginx刷新404
js
try_files $uri $uri/ /index.html;动态添加路由
js
router.addRoute(route)
// 删除路由
// const removeRoute = router.addRoute(route)
// 后续需要移除时调用
// removeRoute()路由动效
- 根据name属性获取不同的class动效样式
js
<router-view v-slot="{ Component }">
<transition name="scale" mode="out-in">
<component :is="Component" />
</transition>
</router-view>css
/* 渐变 mode="out-in" */
.fade-enter-active,
.fade-leave-active {
transition: opacity 0.5s ease;
}
.fade-enter-from,
.fade-leave-to {
opacity: 0;
}
/* 幻灯片 */
.slide-enter-active,
.slide-leave-active {
transition: all 0.75s ease-out;
}
.slide-enter-to {
position: absolute;
right: 0;
}
.slide-enter-from {
position: absolute;
right: -100%;
}
.slide-leave-to {
position: absolute;
left: -100%;
}
.slide-leave-from {
position: absolute;
left: 0;
}
/* 缩放 mode="out-in" */
.scale-enter-active,
.scale-leave-active {
transition: all 0.5s ease;
}
.scale-enter-from,
.scale-leave-to {
opacity: 0;
transform: scale(0.9);
}
/* 组合 */
.scale-slide-enter-active,
.scale-slide-leave-active {
position: absolute;
transition: all 0.85s ease;
}
.scale-slide-enter-from {
left: -100%;
}
.scale-slide-enter-to {
left: 0%;
}
.scale-slide-leave-from {
transform: scale(1);
}
.scale-slide-leave-to {
transform: scale(0.8);
}当前选中路由css类
.router-link-active