Vue2:是把JavaScript对象传入Vue实例作为data选项,Vue将遍历此对象所有的property,并使用Object.defineProperty把这些property全部转为getter/setter。Object.definePropperty是ES5的新特性,不支持IE8以及更低版本的浏览器。
1. Vue.set(this.object, key, value)
2. this.$set(this.object, key, value)
3. this.object = Object.assign({}, this.object, {key: value}) // 对象赋值多个属性时
1. Vue.set(this.arraySet, index, value)
2. this.$set(this.arraySet, index, value)
1. Vue.nextTick(() => {
vm.$el.textContent
})
2. this.$nextTick(() => {
this.$el.textContent
})
vue3:是通过组件的data函数中返回一个普通的JavaScript对象时,Vue会将该对象包裹在一个带有get和set处理程序的Proxy中,Proxy是ES6的新特性,IE浏览器不支持。
开发过程中经常运用到多模块导入:例如Vue Router路由配置文件,Vuex的状态管理文件,以及svg图标的导入,这时候就可以运用传入要搜索的目录、指示是否也应搜索子目录的标志以及匹配文件的正则表达式。
以Vuex的应用程序开发的状态管理模式为例在store文件夹下新建index.js文件和modules文件夹下的多个模块,并在index.js文件内导入
import Vue from 'vue'
import Vuex from 'vuex'
import getters from './getters'
Vue.use(Vuex)
// https://webpack.js.org/guides/dependency-management/#requirecontext
const modulesFiles = require.context('./modules', true, /\.js$/)
// you do not need `import app from './modules/app'`
// it will auto require all vuex module from modules file
const modules = modulesFiles.keys().reduce((modules, modulePath) => {
// set './app.js' => 'app'
const moduleName = modulePath.replace(/^\.\/(.*)\.\w+$/, '$1')
const value = modulesFiles(modulePath)
modules[moduleName] = value.default
return modules
}, {})
const store = new Vuex.Store({
modules,
getters
})
也是以Vuex的应用程序开发的状态管理模式为例在store文件夹下新建index.js文件和modules文件夹下的多个模块,并在index.js文件内导入,但Vite并没有require.context的方法,所以改用import.meta.globEager方法正则匹配文件名。
import getters from './getters'
const files = import.meta.globEager('./modules/*.js')
let modules = {}
for (const key in files) {
modules[key.replace(/(\.\/modules\/|\.js)/g, '')] = files[key].default
}
const debug = process.env.NODE_ENV !== 'production'
export default createStore({
getters,
modules,
strict: debug
})
项目开发中需要动态的引入文件且文件较多时可以运用此方法,避免了文件删除新增是还要手动的导入或者删除,以免报错,是代码更加的灵活高级便于维护。
由于Vue的项目重构,Vue Router出了新的版本,接下来通过vue-router 3.0.6版本和vue-router 4.0.14版本两个不同的版本分析动态加载路由配置。
1、首先就是安装vue-router插件。
npm install [email protected] --save
npm install [email protected] --save
2、在src文件夹下新建router文件夹和文件夹下新建index.js文件以及import.js文件
index.js文件配置初始化路由
import Vue from 'vue'
import Router from 'vue-router'
import Layout from '@/layout'
Vue.use(Router)
export const constantRoutes = [
{
path: '/login',
component: () => import('@/views/login'),
hidden: true
},
{
path: '/redirect',
component: Layout,
hidden: true,
children: [{
path: '/redirect/:path*',
component: () => import('@/views/redirect/index')
}]
},
{
path: '',
redirect: '/home',
component: Layout,
hidden: true,
children: [
{
path: 'home',
name: 'home',
component: () => import('@/views/home/index'),
meta: {
title: '平台介绍',
icon: 'dashboard',
affix: true,
noCache: true
}
},
{
path: '/404',
name: 'Page404',
component: () => import('@/views/404'),
meta: {
title: '404'
},
hidden: true
}
]
}
]
const createRouter = () => new Router({
mode: 'history',
scrollBehavior: () => ({
y: 0
}),
routes: constantRoutes
})
const router = createRouter()
export function resetRouter() {
const newRouter = createRouter()
router.matcher = newRouter.matcher
}
export default router
import.js提取模块配置路由组件
import.js
import Layout from '@/layout'
export default file => {
return map[file] || null
}
const map = {
// 风控系统
'manage': Layout,
'rules': () => import('@/views/rules/index.vue'),
}
通过后端接口获取配置的路由参数,通过匹配import.js文件下的路由参数动态添加路由加载对应的模块。
import router from './router'
import Layout from '@/layout'
import _import from '@/router/import'
function routerGo(getRouter) {
getRouter = filterAsyncRouter(getRouter)
router.addRoutes(getRouter)
}
function filterAsyncRouter(asyncRouterMap) {
const accessedRouters = asyncRouterMap.filter(item => {
if (item.component === 'Layout') {
item.component = Layout
} else {
item.component = _import(item.name)
if (item.name === 'customize') {
item.hidden = true
}
if(item.id) {
item.path = item.path + '/' + item.id
// return () => import(`@/view/modules/${view}`);
}
}
if (item.children && item.children.length) {
item.children = filterAsyncRouter(item.children)
}
return true
})
return accessedRouters
}
由于版本的提升旧版本的api有些不适用,所以根据改动的版本开发了一套新的菜单导航动态加载路由,实现代码如下:
import { createRouter, createWebHistory } from "vue-router";
import Layout from '@/layout/index.vue'
export const routes = [
{
path: '/login',
name: 'login',
hidden: true,
component: () => import('@/views/login/index.vue')
},
{
path: '/redirect',
component: Layout,
hidden: true,
children: [
{
path: '/redirect/:path*',
hidden: true,
component: () => import('@/views/redirect/index.vue')
}
]
},
{
path: '',
redirect: '/home',
component: Layout,
hidden: true,
children: [
{
path: '/home',
name: 'home',
hidden: true,
component: () => import('@/views/home/index.vue'),
meta: {
title: '平台介绍',
icon: 'dashboard'
}
}
]
}
]
const router = createRouter({
history: createWebHistory(),
routes
})
export function resetRouter() {
const newRouter = createRouter()
router.matcher = newRouter.matcher
}
export default router
路由的配置也是通过后端接口获取的实现过程代码:
import router from '@/router/index.js'
import _import from '@/router/import.js'
import Layout from '@/layout/index.vue'
var getRouter
async function routerGo() {
getRouter = await filterAsyncRouter(getRouter)
for(let item of getRouter) {
router.addRoute(item)
}
const routeName = router.currentRoute.value.fullPath
router.push(routeName)
}
function filterAsyncRouter(asyncRouterMap) {
const accessedRouters = asyncRouterMap.filter(item => {
if (item.component === 'Layout') {
item.component = Layout
} else {
item.component = _import(item.name)
if (item.name === 'customize') {
item.hidden = true
}
if(item.id) {
item.path = item.path + '/' + item.id
// return () => import(`@/view/modules/${view}`);
}
}
if (item.children && item.children.length) {
item.children = filterAsyncRouter(item.children)
}
return true
})
return accessedRouters
}
这两个版本的路由配置适用于菜单导航动态路由配置,可以通过后台配置权限控制用户管理菜单,并实现动态加载模块的形式,整体代码清晰有利于迭代维护。