Vue3 的基础使用

news/2024/11/28 17:50:29/文章来源:https://www.cnblogs.com/JOOQSS/p/18574854

Vue3 的基础使用

npm init vue@latest

ref

赋值一个新的对象,那么响应式也会存在
shallowRef 只保留最顶层的响应式更新

reactive

赋值一个新的对象,失去响应性
直接访问对象中的属性,当访问到某个响应式数组(Map这样的原生集合类型)中的 ref元素时,不会解包
shallowReactive 只保留最顶层的响应式更新

ref 检测及转换

isRef 用来判断某个值是不是一个 ref 对象
isRef(name)

unref 如果参数是 ref 对象 返回 .value 如果不是 原样返回

toRef 基于响应式对象上的一个属性来创建一个 ref,如果你更改两者其中一个,另外一个也会响应式的更新

const friend = reactive({ name: 'coder', age: 15 })
const ageRef = toRef(friend, 'age')

toRefs 将一个响应式对象转换为普通对象,每个属性都是指向源对象相应属性的 ref

const friend = reactive({ name: 'coder', age: 15 })
const obj = toRefs(friend)
console.log(obj.age.value)
console.log(obj.name.value)

isReactive 用于检测是不是通过 reactive 或者 shallowReactive 创建的代理对象

isReadonly 用于判断值是不是一个只读对象

处理 reactive 响应式变更

let user = reactive([])
const res = [{ id: 1, name: 'aaa'}, { id: 2, name: 'bbb' }]
  1. 利用数组的变更方法
user.push(...res)
  1. 利用对象的属性
const user = reactive({user: []
})
user.user = res
  1. 利用 ref 来处理
const user = ref([])
user.value = res

作用域插槽

<h1>子组件</h1>
<slot :data="1"></slot>
<slot name="content" :data="2"></slot><!-- 默认插槽 -->
<h1>父组件</h1>  
<Child v-slot="slotProps">{{ slotProps.data }}
</Child><!-- 具名插槽 -->
<h1>父组件</h1>  
<Child><template v-slot:content="slotProps">{{ slotProps.data }}</template>
</Child><!-- 兼有 -->
<h1>父组件</h1>  
<Child><template v-slot:default="slotProps">{{ slotProps.data }}</template><template v-slot:content="slotProps">{{ slotProps.data }}</template>
</Child>

路由

设置路由的历史记录方式
hash: https://xxxxx/#/path,createWebHashHistory(),hash 后面不会发送到服务端,不利于抓包和搜索引擎优化
html5:https://xxxxx/path (推荐)
import.meta.env.BASE_URL: 基础路径
'/' localhost:5174/about
'/code' localhost:5174/code/about

const router = createRouter({history: createWebHistory(import.meta.env.BASE_URL),routes: []
})

routes

routes: [{path: "/",components: {Top,default: Home},},{path: "/",// 通过 path 重定向 homeredirect: "/home",redirect: {// 通过 name 重定向 homename: "home",},},{path: "/home",name: "home",component: Home,},{path: "/about",component: About,children: [// 为了解决父路由点击过去没有显示子路由的内容{path: "",component: AboutIntroduce,},{path: "",redirect: "/profile/p1",redirect: {name: "p1",},},{path: "p1",name: "p1",component: P1,},{path: "product",component: AboutProduct,}],// sensitive: true, // 大小写敏感// strict: true, // 限制末尾不带 /},{// /xxxxx/sssd/sdsdsd/sdsd/sdsd// /xxxpath: "/:pathMatch(.*)*",component: NotFound,},],sensitive: true,strict: true,
});
export default router;

RouterLink

<p>App.vue</p>
<!-- to:切换到不同的页面 string / object -->
<RouterLink to="/about">about</RouterLink>
<RouterLink :to="{ path: '/about' }">about</RouterLink>
<!-- replace:替换当前的页面 然后跳转到下一页 -->
<RouterLink to="/about" replace>about</RouterLink>
<!-- active-class:添加活跃态的样式  -->
<!-- exact-active-class 精准匹配到这个路由的时候才显示样式类  active-class 模糊匹配就会给  -->
<RouterLink to="/about" active-class="red">about</RouterLink>
<RouterLink to="/about" exact-active-class="red">about</RouterLink>
<!-- custom:渲染出自定义的内容 -->
<RouterLink to="/about" custom v-slot="linkProps"><button @click="linkProps.navigate">about</button>
</RouterLink>
<!-- 残障人士 -->
<RouterLink to="/about" aria-current-value="page">About</RouterLink><RouterView name="Top"></RouterView>
<RouterView></RouterView>

嵌套路由

<template><p>About.vue</p><!-- 需要按照二级路由的方式配置 /xxxx/product --><RouterLink to="/about">introduce</RouterLink><RouterLink to="/about/product">product</RouterLink><RouterView></RouterView>
</template>

路由参数

<RouterLink :to="`/user/${id}`">User</RouterLink>
<RouterLink :to="{ path: `/user/${id}`, query: { name: 'coderMonkey', age: 18 }}"
>User</RouterLink>
import { useRoute, useRouter } from 'vue-router'
import router1 from '../router';
const route = useRoute()
const router = useRouter()
console.log(route.params.id)
console.log(router === router1)
console.log(router)
<p>User</p>
<p>{{ $route.params.id }}</p>
<p>{{ $router }}</p>

编程式导航和命名式导航

{path: "/profile/:name",name: "profile",component: Profile,
},
import { useRouter } from 'vue-router'
<!-- import router from '../router'; -->
const router = useRouter()
<!-- 编程式导航 -->
// push - string
router.push('/profile/coder')
// push - object - path
router.push({path: '/profile',query: {coderName: 'coderMonkey1', coderAge: 19}
})
// push - object - name
router.push({name: 'profile',params: {name: 'coder4'},query: {coderName: 'coderMonkey2', coderAge: 20}
})
// push - replace - object - name
router.push({
// router.replace({name: 'profile',params: {name: 'coder4'},replace: true,query: {coderName: 'coderMonkey2', coderAge: 20}
})
// 没有参数 刷新
router.go()
// 正数 1 前进一页 router.forward()
router.go(1) 
// 负数 -1 返回一页 router.back()
router.go(-1)
<!-- 命名式导航 -->
<RouterLink :to="{ name: 'profile', params: { name: 'coder'},query: { coderName: 'coderMonkey', coderAge: 18 }}">Profile</RouterLink>
<RouterView></RouterView>

路由守卫

{path: "/profile/:id",component: Profile,// 路由独享的导航守卫// beforeEnter: (to, from) => {//   console.log("beforeEnter");// },beforeEnter: [(to, from) => {console.log("first");return true;},(to, from) => {console.log("second");return true;},],meta: {title: "xxxxxx-xxxxx",name: "coder",age: 18,},
},
const isLogin = true;
// 全局的导航守卫 -> 路由独享的导航守卫 -> 组件内的导航守卫 -> beforeResolve -> afterEach
// to 跳转到的那个页面 from 触发跳转的页面
router.beforeEach((to, from) => {// 默认返回 undefined 和 return true 是一样的 都会发生跳转// 不会跳转 return false / return {}if (!isLogin && to.path !== "/login") {return {path: "/login",};}// console.log("router.beforeEach", to, from);
});router.beforeResolve((to, from) => {// console.log("router.beforeResolve", to, from);console.log("router.beforeResolve", to.meta);
});router.afterEach((to, from, failure) => {if (!failure) {document.title = to.meta.title || "aaa";} else {console.log("router.afterEach", failure);}
});
import { onBeforeRouteLeave, onBeforeRouteUpdate } from "vue-router";
// 组件内的导航守卫
onBeforeRouteLeave(() => {console.log('onBeforeRouteLeave')
})onBeforeRouteUpdate(() => {console.log('onBeforeRouteUpdate')
})

KeepAlive

<template><p>App</p><RouterLink to="/">Home</RouterLink><RouterLink to="/profile">Profile</RouterLink><RouterLink to="/about">About</RouterLink><RouterView v-slot="{ Component }"><!-- include: 用于缓存组件 --><!-- string include="About,Profile" --><!-- reg :include="/About|Profile/" --><!-- array :include="['About', 'Profile']" --><!-- exclude 用于不缓存的组件 --><!-- string reg array --><!-- max 最多缓存两个组件 --><!-- https://devtools.vuejs.org/guide/installation.html --><KeepAlive :max="1"><component :is="Component" /></KeepAlive></RouterView>
</template>
<script setup>
import { onActivated, onDeactivated, onMounted, onUnmounted, ref } from 'vue';
onActivated(() => {console.log('活跃')
})
onDeactivated(() => {console.log('失活')
})
</script>
<template><p>Profile</p>
</template>

Pinia

/stores/user.js

import { defineStore } from "pinia";
import { computed, ref } from "vue";export const useUserStore = defineStore("user", () => {const name = ref("coderMonkey");const age = ref(18);const doubleAge = computed(() => age.value * 2);const changeAge = () => age.value++;const multipleCount = computed(() => (multiple) => count.value * (multiple || 1));const getUser = async () => {const { data } = await axios.get("/api/info");console.log(data);}return {}
})

页面上使用

<script setup>
import { storeToRefs } from 'pinia';
import { useUserStore } from './stores/user'const userStore = useUserStore()
// 切记
const { name, age } = storeToRefs(userStore)
const { changeAge, getUser } = userStore
// 访问数据 store.xxx
console.log(userStore.name)// 修改数据 store.xxx = 'xxx'
const handleClick = () => {// 修改数据 1 store.xxx = 'xxx'userStore.name += '1'userStore.age += 1// 修改数据 2-1 store.$patch({})// userStore.$patch({//   name: 'aaa',//   age: 100// })// 修改数据 2-2 store.$patch((state) => {})// userStore.$patch((state) => {//   state.name = 'bbb'//   state.age = 999// })
}// 重置
// 插件的使用 pinia
// pinia.use 
const reset = () => {console.log('reset')// userStore.$reset()
}// 订阅 store 的变化
userStore.$subscribe((mutation, state) => {console.log('mutation, state', mutation, state)
}, {detached: true
})userStore.$onAction(({ after, args, name, onError, store }) => {console.log('args', args)console.log('name', name)console.log('store', store)after(() => {console.log('after')})onError(() => {console.log('err')})
})
</script><template><!-- 访问数据 --><p>{{ userStore.name }}</p><p>{{ userStore.age }}</p><p>{{ userStore.doubleAge }}</p><p>{{ name }}</p><p>{{ age }}</p><!-- <button @click="userStore.changeAge(1, $event)">store changeAge</button> --><button @click="userStore.changeAge">store changeAge</button><button @click="handleClick">change</button><p>{{ counterStore.multipleCount(5) }}</p><button @click="counterStore.$reset">reset</button>
</template>

main.js 使用插件

import { createApp } from "vue";
import { createPinia } from "pinia";
import App from "./App.vue";const app = createApp(App);
const pinia = createPinia();pinia.use(({ store }) => {const initialStore = JSON.parse(JSON.stringify(store));store.$reset = () => {store.$patch((state) => {Object.assign(state, initialStore);});};
});app.use(pinia);
app.mount("#app");

vite proxy 配置

proxy: {// http://121.4.100.140:9091/info// env === prd ? /info : /api/info"/api": {target: "http://121.4.100.140:9091",changeOrigin: true,// http://121.4.100.140:9091/inforewrite: (path) => path.replace(/^\/api/, ""),},
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/842982.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

服装行业如何应对快速生产与库存管理挑战?

在服装行业,快时尚的浪潮让市场变化迅速,消费者的需求也在不断变化。而与此同时,企业面对的压力也越来越大——生产周期紧、库存管理难、设计和销售协调困难,往往导致一系列管理瓶颈。如何在如此竞争激烈的环境中提高生产效率、快速响应市场需求,同时确保库存不积压?这些…

智能佳科技—3台Aloha机械臂同发交付, 协同作战新纪元!

视频链接:https://mp.weixin.qq.com/s/JA3iaVqerm4owFYAkrYy8g近日,北京智能佳科技有限公司顺利完成三台Mobile Aloha机械臂的共同发货交付使用任务,再次展现了公司在机器人技术领域的深厚积累和卓越实力。 自2006年8月成立以来,智能佳科技始终秉持着务实创新的精神,连续四…

LiV-GS: LiDAR-Vision Integration for 3D Gaussian Splatting SLAM in Outdoor Environments

arxiv |哈工大发布 LiV-GS:户外环境中基于3D高斯泼溅的LiDAR-视觉集成SLAM系统 【LiV-GS: LiDAR-Vision Integration for 3D Gaussian Splatting SLAM in Outdoor Environments 】 LiV-GS: LiDAR-Vision Integration for 3D Gaussian Splatting SLAM in Outdoor Environments …

Drug2Cell 使用方法

Drug2Cell利用单细胞图谱和EMBL-EBI ChEMBL数据库中的1900万个药物-靶标相互作用。使用该方法能够对于基础医学的研究在后续应用上开拓思路。Drug2cell is a new computational pipeline that can predict drug targets as well as drug side effects.该软件是英国sanger研究所…

面试题精选16-Nginx的应用场景有哪些

1. Web服务器 Http配置Https配置2. 反向代理服务器 Nginx作为请求入口,客户端访问Nginx,Nginx再将请求转发到后端,最后响应给客户端,以此防止后端服务器对外暴露,提高服务器的安全性。3. 负载均衡 将Nginx作为负载均衡器,客户端访问Nginx时,Nginx采取某种策略(默认是轮…

九、Spring Boot集成Spring Security之授权概述

概要介绍授权概念及其实现流程,概要介绍Spring Security授权中的基本概念和授权种类实现技术及其适用场景目录前言一、授权概述二、用户权限三、用户授权流程三、Spring Security授权方式1、请求级别授权2、方法级别授权 前言 本文介绍什么是授权,Spring Security的授权配置有…

星期四计划

小玩一手CTF[BJDCTF2020]The mystery of ip 打开首页,三个页面,第一反应是xff伪造有思路了,但是扫目录,看源码还是要做的,避免漏掉东西(尝试后无果)try一下xff果真如此,到目前为止:一个XFF伪造3个页面(无接口参数)这种情况可以结合xff扫一下目录,然后重新看看代码,…

exam

机器学习 1、概念 机器学习:计算机模拟人进行学习,从数据中不断获取新的信息或技能以改善自身的性能 监督学习:教计算机如何去完成任务。它的数据集是有标签的,训练目标是能够给新数据(测试数据)以正确的标签(训练数据有目标数据项,用训练数据训练出目标模型) 分类问题…

Nuxt.js 应用中的 dev:ssr-logs 事件钩子

title: Nuxt.js 应用中的 dev:ssr-logs 事件钩子 date: 2024/11/28 updated: 2024/11/28 author: cmdragon excerpt: dev:ssr-logs 是一个用在服务器端渲染(SSR)中,用于输出日志的事件钩子。这个钩子会在请求周期结束时被调用,产生的参数包括日志路径与日志内容。这对于…

【开发者福音】腾讯云AI代码助手:沉浸式编程新功能——内联对话来袭!

亲爱的开发者们,你是否还在为采纳AI对话框里生成的代码,需要繁琐的复制、粘贴、插入而烦恼?是否渴望一种更自然、更直观的编程方式,让代码需求直接生成到你的编码区?告别繁琐,拥抱沉浸式编程,腾讯云AI代码助手全新推出——内联对话(Inline Chat)功能,让你的编程体验飞…

vxe-table v3 表格中使用 a- 集成 ant-design-vue 组件库的

在公司开发大型项目中,使用主流表格库 vxe-table v3 和 ant-design-vue 组件库,可以在可编辑单元格中渲染非常简单的使用更多的组件 官网:https://vxetable.cn 安装 npm install vxe-pc-ui@3.3.9 vxe-table@3.11.10 @vxe-ui/plugin-render-antd@3.0.1// ... import VxeUI f…

超好用!员工360度绩效评估互评考核表模板-附下载链接

如题,这是一套标准的员工360度评估互评考核表模板,用于线下通过纸质发放问卷做360度评估,可以根据企业的实际考核指标或行为进行调整。 当然了,简简人事也有业内专业且领先的在线360度评估考核系统,只需要少量的投入,可比线下纸质考核方式效率提升约100倍。 表格下载:员…