建网站公司 优帮云,Wordpress内存占用高,佛山网站建设策划,重庆梁平网站建设哪家便宜一、使用背景
最近公司需要搭建一个新项目#xff0c;用于做官网。因为作为官网#xff0c;首先项目不算大#xff0c;一共只有十来个页面#xff0c;并且想要用户体验感很好#xff0c;所以最终选定以 Vue 作为技术栈。
虽然 Vue3 #xff08;中文官网#xff09;刚问…一、使用背景
最近公司需要搭建一个新项目用于做官网。因为作为官网首先项目不算大一共只有十来个页面并且想要用户体验感很好所以最终选定以 Vue 作为技术栈。
虽然 Vue3 中文官网刚问世不久但是如果采用VUE2 搭建项目以后可能会面临 Vue 版本升级问题从 Vue2 跨度到 Vue3 有很多不兼容的变更并且时代在发展使用新技术会更加具有 可维护可扩展性。
二、项目搭建
这里我使用的是 vue cli4 进行项目搭建
三、devtools
Vue.js devtools 没办法调试vue3的项目官方也提供了升级版的devtoolsvue 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-cnexport default (app) {app.use(ElementPlus, { locale })
}// main.js
import installElementPlus from ./plugins/elementconst app createApp(App)
installElementPlus(app)// 使用
templateel-button按钮/el-button
/template2、 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 函数式组件的同学应该会发现他们及其类似。
1Setup
setup作为组合式api的入口点所有的函数都可以被放置在setup里进行书写需要被setup外部使用的参数通过 return 暴露出去 setup接收两个参数props、context。
props接受父组件传递而来的参数当然这些参数也是响应式的。值得注意的是在setup里使用 props时必须在props里定义的变量 才可被setup的props所接收到在setup里获取props的变量时不可使用es6的解构方法因为它会消除 prop 的响应性如果需要解构 prop并保留响应式可以使用 setup 函数中的 toRefs 函数。 context 暴露三个组件的 property: attrsAttribute、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生命周期钩子 3Provide / 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的一些新特性的使用。
1reactive
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 是为传入对象创建一个响应式的副本不改变原始对象当我们直接改变原始对象时原始对象不会是响应式的。
2readonly readonly获取一个对象 (响应式或纯对象) 或 ref 并返回原始代理的只读代理const state reactive({ count: 0 })
const copy readonly(state)// error
copy.count3ref
此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 方法。 如果大家有什么理解可以评论告诉我。
4computed
computed的使用很简单,本质上和vue2没有什么太大的区别
5watch
等同于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)})6watchEffect
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-modelpageTitle /!-- 等同于: --
ChildComponent :valuepageTitle inputpageTitle $event /// Vue3
ChildComponent v-modelpageTitle /!-- 等同于: --
ChildComponent :modelValuepageTitle update:modelValuepageTitle $event /在Vue2中我们想要改变v-model传下来的值需要model选项去改变。
// parentComponent
ChildComponent v-modelpageTitle /// ChildComponent
export default {model: {prop: title,event: change},props: {// 这将允许 value 属性用于其他用途value: String,// 使用 title 代替 value 作为 model 的 proptitle: {type: String,default: Default title}}
}// 或者
ChildComponent :titlepageTitle update:titlepageTitle $event /
// 或者
ChildComponent :title.syncpageTitle /// 子组件
this.$emit(update:title, 新title)在Vue3中移除了v-bind .sync 修饰符以上功能简写为
ChildComponent v-model:titlepageTitle /
// 等同于
ChildComponent :titlepageTitle update:titlepageTitle $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 vueexport 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/useListFetchsetup() {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 vueexport 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/useListFetchsetup() {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时一些相对变化比较重要的地方。