在新项目中使用 Vue3 使用总结

一、使用背景

最近公司需要搭建一个新项目,用于做官网。因为作为官网,首先项目不算大,一共只有十来个页面,并且想要用户体验感很好,所以最终选定以 Vue 作为技术栈。

虽然 Vue3 (中文官网)刚问世不久,但是如果采用VUE2 搭建项目,以后可能会面临 Vue 版本升级问题,从 Vue2 跨度到 Vue3 有很多不兼容的变更,并且时代在发展,使用新技术会更加具有 可维护可扩展性。

二、项目搭建

这里我使用的是 vue cli4 进行项目搭建
在这里插入图片描述

三、devtools

Vue.js devtools 没办法调试vue3的项目,官方也提供了升级版的devtools:vue devtools beta
在这里插入图片描述

四、安装依赖

安装一些常用依赖,值得注意的是Vue3的某些插件与Vue2并不相同。

特别说明:

1、element-plus

这是基于 Vue 3.0 的桌面端组件库。

如何全局使用element-plus:

// plugins/element.js
import ElementPlus from 'element-plus'
import 'element-plus/lib/theme-chalk/index.css'
import 'dayjs/locale/zh-cn'
import locale from 'element-plus/lib/locale/lang/zh-cn'export default (app) => {app.use(ElementPlus, { locale })
}// main.js
import installElementPlus from './plugins/element'const app = createApp(App)
installElementPlus(app)// 使用
<template><el-button>按钮</el-button>
</template>

2、 axios

值得注意的是,在Vue2中通过 new Vue()创建Vue实例,并没有app的概念,但是在Vue3中,引入了createApp。所以axios的y引用方式有所差异。具体内容参照:Vue3 安装axios使用报错:Uncaught TypeError: Cannot read property ‘use‘ of undefined。

如何使用axios:

// 方式一:全局挂载  此方式不合适于 将项目里的不同模块的请求都放在相应文件里,
// 因为我们在发请求时可能无法获取到当前实例this
// plugins/axios.js
export const plugin = {install: function (app, options) {console.log(options)// 添加全局的方法app.config.globalProperties.axios = _axios;}
}// main.js
import { plugin as axios } from './plugins/axios'
const app = createApp(App)
app.use(axios)//使用:
this.$axios.post('api/Login',{card:111}).then(res => console.log(res))//方式二:直接使用
// plugins/axios.js
const _axios = axios.create(config)
export default _axios// 使用:
import axios from '@/plugins/axios'// 获取岗位类别
export function getJobCategories() {return axios.post('api/Login',{card:111})
}

3、Vue Router

Vue router4 也提供了hook钩子函数供使用。
在这里插入图片描述
在 setup里使用 router

import { useRouter } from "vue-router"
const router = useRouter()
router.push('/')

五、Vue3新特性

1、组合式API

什么是组合式API?

简单来说就是 将之前散布在vue文件里 的各个功能函数 组合 在一个函数里
在这里插入图片描述

这样会使我们的代码更加类聚,如果使用过react 函数式组件的同学应该会发现,他们及其类似。

(1)Setup

setup作为组合式api的入口点,所有的函数都可以被放置在setup里进行书写,需要被setup外部使用的参数,通过 return 暴露出去
在这里插入图片描述
setup接收两个参数:props、context

props接受父组件传递而来的参数,当然,这些参数也是响应式的。值得注意的是,在setup里使用 props时,必须在props里定义的变量 才可被setup的props所接收到,在setup里获取props的变量时,不可使用es6的解构方法,因为它会消除 prop 的响应性,如果需要解构 prop并保留响应式,可以使用 setup 函数中的 toRefs 函数。

在这里插入图片描述
context 暴露三个组件的 property: attrs(Attribute)、slots(卡槽)、emit(触发事件),context是一个普通的 JavaScript 对象,不具有响应式,可以使用es6解构语法。
在这里插入图片描述
注意⚠️

setup是在解析其它组件选项之前被调用的,所以在setup里无法准确的访问到当前组件实例:this。

想要在setup里获取当前组件实例,官方提供了一个函数:getCurrentInstance,但是getCurrentInstance只能在setup和生命钩子函数里使用

// getCurrentInstance代表全局上下文,ctx相当于Vue2的this,
// 但是特别注意ctx代替this只适用于开发阶段,等你放到服务器上运行就会出错,
// 后来查阅资料说的得用proxy替代ctx,才能在你项目正式上线版本正常运行const { ctx, proxy } = getCurrentInstance()

(2)生命周期钩子

在这里插入图片描述

(3)Provide / Inject:父子组件跨层级传输数据

// 父组件
setup () {// readonly包裹后可以在组件内引用时不被改变值。// 否则在组件内可以直接通过applyPositionId.value=***将值改变provide('applyPositionId', readonly(applyPositionId))// 函数也可传递provide('hideApplyModal', hideApplyModal)
}//子组件接收
setup() {const applyPositionId = inject('applyPositionId')const hideApplyModal = inject('hideApplyModal')// 函数调用hideApplyModal()
}

2、响应性 API

在Vue2里,我们定义在data里的数据,会被 Object.defineProperty() 数据劫持,通过观察者模式 最终成为响应式数据。
在Vue3里,实现响应式的 方式改为了 es6 新增的语法 proxy,通过对象拦截方式实现响应式,解决了vue2中的一些漏区。
关于这两点的相关知识有很多,我会新写一篇文章做相应的说明。这里主要介绍Vue3的一些新特性的使用。

(1)reactive

reactive用于为对象创建响应式状态,其作用相当于Vue 2.x 中的 Vue.observable()。为对象创建响应式状态后,就不会存在 Vue2中 修改 某个对象在data定义时没有被定义到的属性,不会存在响应式状态 的问题。

setup() {const obj = { count: 0}const state = reactive(obj)console.log(state.count)  // 0
}

官网有一句话:
在这里插入图片描述
响应式转换是“深层”的——它影响所有嵌套 property。这是什么意思呢?

当我们使用 proxy (不了解 proxy 的可以阅读:阮一峰 es6入门)做 对象拦截 时,他会劫持此对象的所有property 属性。
在这里插入图片描述
vue2使用 Vue.observable() 使一个对象可响应,被传入的对象会直接被 Vue.observable 变更为响应式。而 reactive 是为传入对象创建一个响应式的副本,不改变原始对象,当我们直接改变原始对象时,原始对象不会是响应式的。

(2)readonly

 readonly获取一个对象 (响应式或纯对象) 或 ref 并返回原始代理的只读代理const state = reactive({ count: 0 })
const copy = readonly(state)// error
copy.count++

(3)ref

此ref非彼ref,在Vue和react里,都有ref的概念。当其作用域HTML文件时,ref是React/Vue提供的用来操纵React/Vue组件实例或者DOM元素的接口。

而 响应性 API 里 ref 是 用来创建一个具有响应式且可变的 ref 对象,ref 对象具有指向 其所创建变量的.value属性。在setup里被return 出去时,会自动绑定其value值。

setup() {const count = ref(0)console.log(count.value)  // 0return {count}
}mounted() {console.log(count)  // 0
}

官网有这么一句话:
在这里插入图片描述
看了半天我也不是特别明白它是什么意思。将 ref 与 reactive 使用下来,发现他们两除了在使用方式上有所不同以外,没有什么太大的区别。高度响应式 的感念还是没有体会到。通过源码我可以看见,在使用ref为 对象创建 响应式数据时,其内部调用的也是 reactive 方法。
在这里插入图片描述
在这里插入图片描述
如果大家有什么理解,可以评论告诉我。🙏🙏

(4)computed

computed的使用很简单,本质上和vue2没有什么太大的区别
在这里插入图片描述

(5)watch

等同于vue2的this.$watch,可监听一个或多个源。当 被依赖的值 发生改变时,执行。

// 侦听一个getter
const state = reactive({ count: 0 })
watch(() => state.count,(newcount, prevCount) => {console.log('新值:', newcount)console.log('旧值:', prevCount)}
)// 直接侦听一个ref
const count = ref(0)
watch(count, (newcount, prevCount) => {console.log('新值:', newcount)console.log('旧值:', prevCount)
})// 监听多个源,使用数组形式
const fooRef = ref(0)
const barRef = ref(1)
watch([fooRef, barRef], ([newFoo, newBar], [prevFoo, prevBar]) => {console.log('新Foo值:', newFoo)console.log('旧Foo值:', prevFoo)console.log('新Bar值:', newBar)console.log('旧Bar值:', prevBar)})

(6)watchEffect

watchEffect响应式地跟踪其依赖项时立即运行一个函数,并在更改依赖项时重新运行它:意思就是页面初始化时会被立即执行一次,并在依赖项发生改变时,再次执行。熟悉React Hook 的同学会非常熟悉,他与useEffect 所实现的功能是一样的,唯一不同的是,useEffect需要我们手动传入依赖,而 watchEffect 会自动收集依赖。

const count = ref(0)watchEffect(() => console.log('value:', count.value))
// value:0setTimeout(() => {count.value++// value:1
}, 100)

六、非兼容变更

Vue3 在 Vue2上,有许多的非兼容变更,这里列举一些比较常用的属性。

1、v-model

在Vue2中的 v-model 等同于:value + input 的语法糖。
在Vue3中的 v-model 等同于:modelValue + update:modelValue。

// Vue2
<ChildComponent v-model="pageTitle" /><!-- 等同于: -->
<ChildComponent :value="pageTitle" @input="pageTitle = $event" />// Vue3
<ChildComponent v-model="pageTitle" /><!-- 等同于: -->
<ChildComponent :modelValue="pageTitle" @update:modelValue="pageTitle = $event" />

在Vue2中,我们想要改变v-model传下来的值,需要model选项去改变。

// parentComponent
<ChildComponent v-model="pageTitle" />// ChildComponent
export default {model: {prop: 'title',event: 'change'},props: {// 这将允许 `value` 属性用于其他用途value: String,// 使用 `title` 代替 `value` 作为 model 的 proptitle: {type: String,default: 'Default title'}}
}// 或者
<ChildComponent :title="pageTitle" @update:title="pageTitle = $event" />
// 或者
<ChildComponent :title.sync="pageTitle" />// 子组件
this.$emit('update:title', '新title')

在Vue3中,移除了v-bind .sync 修饰符,以上功能简写为:

<ChildComponent v-model:title="pageTitle" />
// 等同于
<ChildComponent :title="pageTitle" @update:title="pageTitle = $event" />// 子组件:
setup(props, context) {const { emit } = context || {}const onClose =() => {emit('update:pageTitle', '新title')}return {onClose,}
}

2、v-if 与 v-for

在Vue2中,v-if 与 v-for 同时作用于同一个DOM节点时,v-for 的优先级 高于 v-if 。
在Vue3中,v-if 与 v-for 同时作用于同一个DOM节点时,v-if 的优先级 高于 v-for 。
且 v-if/v-else/v-else-if 的分支中继续使用 key attribute,因为没有为条件分支提供 key 时,也会自动生成唯一的 key。

3、filters

Vue3中filters已被彻底移除,建议使用computed代替。

4、template

在Vue2中,template 里只支持一个根结点,否则会报错。
在Vue3中,template 里只支持多个根结点。

5、prop

在Vue2中,我们需要在 prop 里访问data里的字段,可以使用 this 。
在Vue3中,prop 里不再支持this。

七、自定义Hook

1、useFetch

import { reactive, toRefs } from 'vue'export default function useFetch(api, params, transformer) {if (typeof api !== 'function') {throw new TypeError('api should be type of fuction')}// 定义初始状态const state = reactive({data: null,loading: false,})// 定义查询函数const doFetch = (otherParams) => {const finalParams = {...(params || {}),...(otherParams || {})}state.loading = truereturn api(finalParams).then((data) => {state.data = typeof transformer === 'function' ? transformer(data) : datastate.loading = falsereturn data}).catch((err) => {console.log(err && err.message)state.loading = false})}// 返回状态refs和查询函数return [toRefs(state), doFetch]
}// 使用
import useListFetch from '@/hooks/useListFetch'setup() {const getdataFunc = (params) => {const { id } = params || {}return axios.get(`/xxx?id=${id}`)}const [{ data, loading: isLoading},getData,] = useListFetch(getdataFunc, {id: 10,})getData()
}

2、useListFetch

import { reactive, toRefs } from 'vue'export default function useListFetch(api, params, transformer) {if (typeof api !== 'function') {throw new TypeError('api should be type of fuction')}// 定义list初始状态const state = reactive({items: [],loading: false,isLastPage: false,})const { pageSize = 10, ...otherParams } = params || {}// 定义查询函数const doFetch = () => {const preSize = state.items.lengthconst finalParams = {...otherParams,offset: preSize,limit: pageSize,}state.loading = truereturn api(finalParams).then((data) => {if (data && Array.isArray(data)) {const newData = typeof transformer === 'function' ?  transformer(data) : dataconst newItems = [...state.items, ...newData]state.items = newItemsif (newItems.length !== preSize + pageSize) {state.isLastPage = true}}state.loading = falsereturn data}).catch((err) => {console.log(err && err.message)state.loading = false})}// 返回状态refs和查询函数return [toRefs(state), doFetch]
}// 	使用
import useListFetch from '@/hooks/useListFetch'setup() {const getListFunc = (params) => {const { offset = 0, limit = 10 } = params || {}return axios.get(`/xxx?offset=${offset}&limit=${limit}`)}const [{ items: videoList, loading: isLoading, isLastPage: isLastPage },getList,] = useListFetch(getListFunc, {pageSize: 10,})getList()
}

八、项目打包

参考文档:https://cli.vuejs.org/zh/guide/

以上就是本人在使用Vue3时一些相对变化比较重要的地方。

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

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

相关文章

2020年从架构谈起到Mesh结束

作者 | 张羽辰&#xff08;同昭&#xff09;阿里云交付专家 导读&#xff1a;如今&#xff0c;几乎所有的事情都离不开软件&#xff0c;当你开车时&#xff0c;脚踩上油门&#xff0c;实际上是车载计算机通过力度感应等计算输出功率&#xff0c;最终来控制油门&#xff0c;你从…

Mendix:低代码平台四大常见用例开发

编辑 | 宋慧 供稿 | Mendix 头图 | 付费下载于视觉中国 如今&#xff0c;低代码对很多人来讲可能已经不再是一个陌生的名词。创新的低代码开发平台实现了低级别编码的抽象化和人工流程的自动化。低代码通过可视化开发工具和可重用组件&#xff0c;缩短了定制化网络和移动应用的…

下架已上线的小程序;2.设置不允许被用户搜索到

下架已上线的小程序&#xff1a; 登录微信开发者后台【设置】-【功能设置】-【暂停服务设置】-【暂停服务】&#xff0c;如图 设置小程序不允许被用户搜索到&#xff1a; 登录微信开发者后台【设置】-【功能设置】-【隐私设置】-【关闭】&#xff0c;如图 操作过程中遇到的问题…

5G新基建边缘计算乘风破浪

2019年6月6日&#xff0c;工信部向中国电信、中国移动、中国联通、中国广电发放5G商用牌照&#xff0c;这意味着中国正式进入5G元年。一年以来&#xff0c;随着基站的建设与用户认知的提升&#xff0c;5G应用如雨后春笋般涌现。而在今年上半年频繁被提及的“新基建”中&#xf…

那些年,我在阿里当数据开发

前言&#xff1a; -更多关于数智化转型、数据中台内容请加入阿里云数据中台交流群—数智俱乐部 &#xff08;文末扫描二维码或点此加入&#xff09; -阿里云数据中台官网 https://dp.alibaba.com/index &#xff08;作者&#xff1a;数据从业者 &#xff09; 我是阿里数据部…

太白金星:我很关心分布式 Quorum NWR

来源 | 悟空聊架构责编 | 寇雪芹头图 | 下载于视觉中国先来看一段神秘的对话&#xff1a;太白金星&#xff1a;听闻老君最近在练神丹妙药&#xff0c;可否与我一讲&#xff1f;太上老君&#xff1a;老白啊&#xff0c;我最近在练六颗丹药&#xff1a;两颗延年丹、两颗健步丹、两…

mPaaS小程序技术架构深度解析

⚅ 点击观看《mPaaS 小程序新品发布会》回放 > > 随着小程序技术的愈发成熟&#xff0c;不同平台的优势和典型使用场景各有侧重&#xff0c;同时越来越多的开发者可以结合自身的业务特色&#xff0c;通过小程序作为业务载体&#xff0c;形成单一平台或多平台的协同关系。…

从javaScript数据类型开始了解垃圾回收机制

一、 javaScript数据类型 javaScript 数据类型分为&#xff1a;基本数据类型、引用数据类型 基本数据类型 分类&#xff1a;Number、String、Boolean、Null、Undefined、Symbol。 存储地址&#xff1a;栈。 引用数据类型 分类&#xff1a;Object、Array、Function。 存储地…

直播中那几秒延时到底来自哪?

7月16日&#xff0c;亚太内容分发大会上&#xff0c;阿里云高级产品运营专家俞翔受邀出席&#xff0c;并分享了基于CDN网络构建超低延时直播的场景实践。以下为演讲原文。 近几年&#xff0c;直播带货已经逐渐走进大众视野。在今年上半年受疫情原因影响&#xff0c;直播营销市…

三探云原生全景图,这次聊聊运行时层

在《俯瞰云原生&#xff0c;这便是供应层》我们介绍了云原生全景图的最底层&#xff1a;供应层&#xff0c;本文将带大家了解运行时层&#xff0c;这一层包含了容器在云原生环境中运行所需的一切。作者 | Catherine Paganini&#xff0c;Jason Morgan来源 | K8sMeetup社区头图 …

SpringCloud应用在Kubernetes上的最佳实践—开发部署

作者 | 孤弋 阿里云高级技术专家&#xff0c;负责 EDAS 的开发和用户体验优化工作。 导读&#xff1a;在上一篇文章《SpringCloud 应用在 Kubernetes 上的云上实践 - 开发篇》中讲到可以通过两个工具&#xff0c;轻松地将一个 SpringCloud 应用从初始化到本地运行。本篇文章&a…

解决谷歌浏览器 google chrome 安装插件报错:Download interrupted,不支持 .crx 文件下载

最近给 新的 macBook Pro 2020 笔记本的 chrome 浏览器安装 react developer tools 时&#xff08;翻墙情况下&#xff09;&#xff0c;安装总是不成功&#xff0c;有一个弹框提示&#xff1a;Download interrupted。 一开始我以为是第三方插件出了问题&#xff0c;于是我去安…

低代码,让人人都可以是开发者

作者&#xff1a;流水不争先 来源| 技术领导力(ID&#xff1a;jishulingdaoli)头图 | 下载于视觉中国今年2月23日&#xff0c;外国低代码平台提供商Creatio宣布获得6800万美元融资&#xff1b;2月22日&#xff0c;国内SaaS软件厂商黑湖智造宣布完成C轮近5亿元人民币融资。国内外…

秒懂云通信:选云通信到底哪家强?

原文链接 本文为云栖社区原创内容&#xff0c;未经允许不得转载。

H5 中 IOS 系统如何获取浏览器真正的内核

当我们使用 navigator.userAgent 获取 当前浏览器的用户代理&#xff0c;一般通过正则表达式 就可获取到对应的浏览器内核。但是 问题&#xff1a;在ios系统下&#xff0c;无论我们下载什么浏览器&#xff08;chrome、火狐…&#xff09;&#xff0c;其内核都是safari。 原因…

有效的云安全态势始于三个步骤

云栖号资讯&#xff1a;【点击查看更多行业资讯】 在这里您可以找到不同行业的第一手的上云资讯&#xff0c;还在等什么&#xff0c;快来&#xff01; 公共云的采用如今持续增长&#xff0c;到今年年底&#xff0c;预计将有83%的企业工作负载都在云平台中。云计算增加的灵活性和…

妥了!微服务治理的困难,用 Serverless 来解决

作者 | 王科怀&#xff08;行松&#xff09;来源 | Serverless头图 | 下载于视觉中国微服务治理面临的挑战在业务初期&#xff0c;因人手有限&#xff0c;想要快速开发并上线产品&#xff0c;很多团队使用单体的架构来开发。但是随着公司的发展&#xff0c;会不断往系统里面添加…

建网站应该选择自己建站还是在线建站?

一、什么是网站&#xff1f; 网上关于网站的定义很多&#xff0c;在此就不想重复了&#xff0c;简而言之网站就是创建者使用技术手段搭建&#xff0c;从而让访客可以通过域名访问并进行互动的互联网页面组合。 通常网站由四个部分组成&#xff1a; 1、域名&#xff1a; 也就…

SVG图片以 https 链接的方式展示在页面上,并且可继承父类的颜色大小(类似阿里巴巴iconfont)

一、背景与问题 1. 背景 在前端的项目开发过程中&#xff0c;我们经常使用到 字体图标库&#xff08;iconfont&#xff09;&#xff0c;以 ant dezign 为例。 如果在遇到图标库不存在的图标时&#xff0c;我们往往采用自定义图标的方式&#xff1a; 引入自定义的svg图&…