vue3 项目实践总结

news/2025/1/16 3:44:02/

一、挂载全局变量

1.1 main.js 中挂载

// 引入全局变量
import api from '@/api';const app = createApp(App);// 挂载全局变量
app.config.globalProperties.$API = api;app.use(store).use(router).use(ElementPlus).use(Vant).mount('#app');

1.2 组件中获取

  • 方法一 推荐使用proxy
    1. 使用 ctx ,经过测试后,打包到dist以后,ctx下面的值是拿不到的,即只能在开发环境使用。所以。推荐使用proxy

    2. proxy, ctx可直接访问全局变量,但无法像globalProperties这样查看有哪些数据,只是一个Proxy对象。

    3. 如果想要通过 proxy, ctx 访问当前组件的变量,需要在onBeforeMount 和 mounted生命周期中,即在组件挂载之后才可访问,否则访问不了;

    4. 注意:在vue3中,created相关的生命周期已经被废弃,由setup()代替

import { getCurrentInstance, onMounted } from 'vue';   // 需要调用vue3内置的方法
setup(props, context) {// 直接解构出 proxy 和 ctxconst { proxy, ctx } = getCurrentInstance();// 使用方法1 : 如果想要通过 proxy, ctx 访问当前组件的变量,需要在onBeforeMount 和 mounted生命周期中    onMounted(() => {console.log('----ctx', ctx['当前组件的data变量']);console.log('----proxy', proxy['当前组件的data变量']);});// 使用方法2 :直接调用全局变量,但此时无法访问当前组件的变量proxy.$API.xxx   // 调用具体的方法
}

在这里插入图片描述在这里插入图片描述

  • 方法二 麻烦但详细
import { getCurrentInstance } from 'vue';   // 需要调用vue3内置的方法
setup(props, context) {// 这样获取可以获取到所有的全局变量,包含UI组件库获取其他方法注入的。并且可以想象的查看有哪些数据const { appContext: { config: { globalProperties } } } = getCurrentInstance();globalProperties.$API.xxx   // 调用具体的方法
}

在这里插入图片描述

1.3 全局挂载 store 和 router

在第九章中阐述了怎么在页面中去使用storerouter,但在实际项目开发中,storerouter 的使用频率是很高的,每个组件(页面)都去这么引入/调用,会显得很麻烦。

1. 挂载到window上

但是你要忍受它的全局污染

2. 挂载到全局上

在我的实际开发中,总会有几个东西会挂载到全局变量上:比如 ajax 或者APImoment等,再将 storerouter 挂载上去,使用成本对于我来说并没有增加多少。

  • main.js
const app = createApp(App);// 将store、router挂载到全局变量上
import { useStore } from "vuex";
import { useRoute } from "vue-router";
app.config.globalProperties.$store = useStore();
app.config.globalProperties.$router = useRoute();app.use(router).use(store).mount('#app')
  • 组件(页面)中
<template><span> {{ count }} </span><!-- 下面这种vue2的旧写法,依旧可用,但是可能编辑器会报警告;并且$store并不需要在组件中return处理,它是挂载到每个实例上的--><span>{{ $store.state.count }}</span>
</template>
<script>import { getCurrentInstance, computed, ref } from 'vue';export default {name: 'Home',setup() {const { proxy } = getCurrentInstance();// 使用storeconst count = computed(() => proxy.$store.state.count);const handleSkip = () => {// 使用routerproxy.$router.push('/about');}return {count: ref(count),handleSkip}}}
</script>
3. 使用Provide & Inject => 不推荐,使用成本较高

注意:使用 Provide & Inject 最好配置 readonly 或者 shallowRef ,限制 孙子组件修改一级组件的数据。避免造成数据混乱。

  • app.vue
<script setup>
import { useStore } from "vuex";
import { useRoute } from "vue-router";import { provide } from "vue";// 组合式的API provide 没有提供批量方法,只能每个变量写一句
provide("store", useStore());
provide("router", useRoute());
</script>
  • 组件(页面)中
<script setup>
import { inject } from "vue";// 使用 inject 获取到 store 和 router
const store = inject("store");
const router = inject("router");console.log('=====>>>>', store.state);
console.log('=====>>>>', router);
</script>

注意 : inject()只能放在setup()生命周期里运行,即不能放在别的周期里运行,也不能放在事件周期里运行。

个人理解:只能在同步代码中使用,不能再异步代码中使用,所以,一般先在setup()周期中取值。

放在 setTimeout 或者 Promise.then() 是不可以的,但是下面这种用法是可以的:

function xx() {console.log(inject("abc"))
}
xx()

二、封装 getCurrentInstance

在上一章的 挂载全局变量 中有提到:想要获取全局变量,一般都是从getCurrentInstance() 解构出 proxyglobalProperties,但是:

  • 解构出的 proxy ,包含所有的全局变量,但是 是Proxy对象,不能清楚的在控制台查看
  • globalProperties 里面全部的全局变量,并且不是Proxy对象,可以在控制台清楚查看

而每个组件里面都去解构一次 globalProperties 是很繁琐的,所以,我们可以封装一下,实现步骤如下:

  1. 新建文件 hooks / useCurrentInstance.ts
import { ComponentInternalInstance, getCurrentInstance } from 'vue'
export default function useCurrentInstance() {// 如果解构出 proxy ,里面也包含所有的全局变量,但是 是Proxy对象,不能清楚的在控制台查看const { appContext } = getCurrentInstance() as ComponentInternalInstance;// 这里有全部的全局变量,并且不是Proxy对象,可以在控制台清楚查看const globalProperties = appContext.config.globalProperties;return {globalProperties}
}
  1. 组件中使用
// 先引入
import useCurrentInstance from '@/hooks/useCurrentInstance';// 再使用
export default {setup() {const { globalProperties } = useCurrentInstance();// 这里面的全局变量可以清楚的在控制台去查看console.log('-------globalProperties', globalProperties)}
}

注意 :不能再封装文件里面直接调用函数并直接导出全局变量,会报错!!

三、vue3中使用ref

// ------------ 官网实例 ------------
<template> <div ref="root">This is a root element</div>
</template><script>// 引入ref APIimport { ref, onMounted } from 'vue'export default {setup() {const root = ref(null)onMounted(() => {// DOM 元素将在初始渲染后分配给 refconsole.log(root.value) // <div>This is a root element</div>})return {root   // 暴露出来的变量名必须和template 里面ref的值相同}}}
</script>// ------------ 实际使用 ------------
<template>// publish 是一个子组件<publish ref="pubRef"></publish><div @click="handleAddPublish">点击</div>
</template><script lang="ts">// 引入ref APIimport { ref } from 'vue'export default {setup() {const root = ref(); // 如果是在 ts 环境下,不能传入null作为参数,否则root.value将提示结果为null, 不能调用子组件的方法;在js环境可以传nullconst handleAddPublish = () => {root.value.init();  // init 是子组件return出来的一个方法};return {handleAddPublish,pubRef: root   // 暴露出来的变量名必须和template 里面ref的值相同}}}
</script>

四、vue3中的nextTick

// nextTick: 将回调推迟到下一个DOM更新周期之后执行,在更改了一些数据以等待DOM更新后立即使用它。import { nextTick } from 'vue'
setup() {const changeMessage = newMessage => {nextTick(()=>{// to do list...})};return {changeMessage         }
}

五、详解单文件组件<script setup>

<script setup> 是在单文件组件(SFC)中使用组合式 API 的编译时语法糖。相比于普通的 <script> 语法,它具有更多优势。详情请阅读官方文档

  1. 基本语法
// 将 setup 属性添加到 script 标签上即可
<script setup>console.log('hello script setup')
</script>

setup里面的代码会被编译成组件 setup() 函数的内容。这意味着与普通的 <script> 只在组件被首次引入的时候执行一次不同,<script setup> 中的代码会在每次组件实例被创建的时候执行并且自带 return 功能,所有在里面声明的变量、函数都能在模板中直接使用!

  1. 使用 props、emit、useContext

    vue3中如果想要获取 props、emit、attr等参数,需要从setup(props, context) 的参数里面获取,但<script setup> 省略了这一步,所以获取方式也需要修改:

   <template><p>{{type[0]}}</p><button @click="emit('setData', Number.parseInt(Math.random() * 10))">添加数据</button></template><script setup>import { defineEmit, defineProps } from 'vue' // 这两个方法其实无需导入,他们是<script setup>里的编译器宏,会自动编译// 获取props => 注意:props不能结构,会失去响应式效果const props = defineProps({list: {type: Array,default: () => []}})// 获取emit   const emit = defineEmit(['deleteData', 'setData'])// 获取slots、attrs 等其他组件const { slots , attrs } = useContext()</script>
  1. 自动注册指令与组件
<template><!-- 使用指令 --><div v-click-outside /><!-- 使用组件 --><MyComponent />
</template><script setup>// 指令导入后即可直接使用, 无需注册import { directive as clickOutside } from 'v-click-outside';// 组件导入后也可直接使用, 无需注册import MyComponent from './MyComponent.vue'
</script>

<script setup> 是在单文件组件 (SFC) 中使用组合式 API 的编译时语法糖。相比于普通的



文章仅为本人学习过程的一个记录,仅供参考,如有问题,欢迎指出!


http://www.ppmy.cn/news/103301.html

相关文章

obs基础之 obs 29 新版编译

目录 一、相关资料 1、总文档 2、29 API 文档 3、编译文档 二、自动编译 1、下载vs2022

Power BI Embedded自动缩放容量,为公司每个月节省上万元

哎&#xff0c;不知道今年行情怎么就这样了&#xff0c;大厂一边大批毕业生&#xff0c;一边大量招人。难道是今年的新人便宜&#xff1f;就连道哥&#xff08;吴翰清&#xff0c;阿里P10&#xff0c;中国顶级黑客&#xff09;都从阿里离职了&#xff0c;当年年少不懂学计算机&…

公网SSH远程访问家中的树莓派[无公网IP]

文章目录 前言如何通过 SSH 连接到树莓派步骤1. 在 Raspberry Pi 上启用 SSH步骤2. 查找树莓派的 IP 地址步骤3. SSH 到你的树莓派步骤 4. 在任何地点访问家中的树莓派4.1 安装 Cpolar内网穿透4.2 cpolar进行token认证4.3 配置cpolar服务开机自启动4.4 查看映射到公网的隧道地址…

消防安全知识答题活动小程序v4.1.0

消防安全知识答题活动小程序v4.1.0 v4.1.0 1&#xff09;支持多选题 .wxml <checkbox-group class"checkbox-group" bindchange"checkboxChange"><label class"checkbox" wx:for"{{questionList[index].option}}" wx:for…

深入浅出Vite:如何开发一个Vite插件

说到自定义的能力&#xff0c;大家肯定很容易想到插件机制&#xff0c;利用一个插件来扩展构建工具自身的能力。在学习了 Vite 的插件机制后&#xff0c;我们接下来利用已掌握的Vite插件开发的基本知识来实战Vite插件的开发工作。 一、插件示例 Vite 插件与 Rollup 插件结构类…

帕累托改进和帕累托最优、卡尔多-希克斯改进

根据目标个数&#xff0c;分为单目标规划&#xff0c;以及多目标规划。多目标的规划是去找折中的解集合&#xff0c;既pareto最优解集合。对优化目标超过3个以上的&#xff0c;称之为超多目标优化问题。 帕累托改进描述的就是在没有人变得不好的前提下让有些人更好的过程。帕累…

​​​​Linux Shell 实现一键部署Oracle21 zip包方式

oracle前言 Oracle开发的关系数据库产品因性能卓越而闻名&#xff0c;Oracle数据库产品为财富排行榜上的前1000家公司所采用&#xff0c;许多大型网站也选用了Oracle系统&#xff0c;是世界最好的数据库产品。此外&#xff0c;Oracle公司还开发其他应用程序和软件。同时&#…

renshenmisdf

要制作一个人生模拟器&#xff0c;首先需要设计游戏的基本框架&#xff0c;并构思游戏的玩法&#xff0c;规则和内容。 然后&#xff0c;在C中实现这个框架并添加游戏所需的各种类、函数和变量。其中&#xff0c;有几个关键的方面需要考虑&#xff1a; 模拟生命周期&#xff1a…