上次做vue的项目大概是一年前了,这次又接触到vue,发现vue cli都到4.5了,一时突然分不太清vue3.0和vue cli4.0,之前用vue时一直用的elementui ,不过elementui好像没有对应vue3.0的。只能选择antd(Ant Design of Vue) 了,这中间遇到了太多的坑就不一一列举了。
先看一下本机环境
node 10.13.0
@vue/cli 4.5.9
node是之前就安装的并没有做更新,安装了最新的vue脚手架
这里就不示例项目创建过程了,直接看当前的目录结构
这里一股脑的把 vue-router、vuex、ant-design-vue、axios、echarts、data-view、mitt(代替数据总线Bus)、mockjs都用上了,还用了iconfonts的自定义图标和百度地图的使用
这里可以看到用到的每个组件的版本,以下不在赘述npm install 或者cnpm install
在vue3.0之后 antd只能是2.x之后的,router 只能是4.x之后的 vuex 只能是4.x之后的,大概是这样,你也可以尝试使用老版本试试
"dependencies": {
"@jiaminghi/data-view": "2.10.0",
"@types/echarts": "^4.4.3",
"ant-design-vue": "^2.0.0-rc.1",
"axios": "^0.21.0",
"babel-plugin-import": "^1.13.1",
"core-js": "^3.6.5",
"echarts": "^4.6.0",
"js-cookie": "^2.2.1",
"mitt": "^2.1.0",
"mockjs": "^1.1.0",
"vue": "^3.0.0",
"vue-router": "^4.0.0-beta.13",
"vuex": "^4.0.0-0",
"screenfull": "4.2.0"
},
"devDependencies": {
"@vue/cli-plugin-babel": "~4.5.0",
"@vue/cli-plugin-eslint": "~4.5.0",
"@vue/cli-service": "~4.5.0",
"@vue/compiler-sfc": "^3.0.0",
"babel-eslint": "^10.1.0",
"compression-webpack-plugin": "^6.1.1",
"eslint": "^6.7.2",
"eslint-plugin-vue": "^7.0.0-0",
"less": "^3.12.2",
"less-loader": "^7.1.0",
"node-sass": "^5.0.0",
"sass-loader": "^10.1.0",
"vue-loader-v16": "^16.0.0-beta.5.4",
"webpack-cli": "^4.2.0"
},
下面我们来一步一步的整合他们,这里主要说vue3.0下整合各个组件所注意的点,这段时间看到网上也是很多说是vue3.0的实际上说的是vue cli3.0的事儿,用的还是vue2.x
(vue cli 3.0之后项目结构变为public、src这样,vue3.0则是 package.json 下vue的版本)
// main.js
import { createApp } from 'vue'
import app from './App.vue'
const App = createApp(app,{});
App.mount('#app');
// 也可以这样写---我暂时没用这种写法
// createApp(app,{}).mount('#app');
// 加载router和antd对象可以这样
// createApp(app,{}).use(antd).use(router).mount('#app');
在vue3.0之前router下直接import vue这样用
import Vue from 'vue'
import Router from 'vue-router'
Vue.use(Router)
在vue3.0之后这样
import { createRouter, createWebHashHistory, createWebHistory, ErrorHandler } from 'vue-router'
用createRouter方法创建路由对象
router/index.js
import { createRouter, createWebHashHistory, createWebHistory, ErrorHandler } from 'vue-router'
// 两种路由mode,hash和history
// const routerHistory = createWebHistory(process.env.BASE_URL); // createWebHistory()
const routerHistory = createWebHashHistory(process.env.BASE_URL); // createWebHistory()
const router = createRouter({
history: routerHistory,
routes: [
{
path: '/',
name: 'index',
component: () => import( '../views/index.vue'),
children:[{
path:'/',
name: 'dashboard-a',
// 单个router-view用:component
component: () => import( '../views/dashboard.vue')
}, {
path:'/baidumap',
name: 'baidumap-a',
// 单个router-view用:component
component: () => import( '../views/baidumap.vue')
}]
},{
path: '/big_screen_main',
name: 'big_screen_main',
component: () => import( '../views/big_screen_main.vue'),
children:[{
path:'/big_screen_main/',
name: 'dashboard-b',
// 单个router-view用:component
component: () => import( '../views/dashboard.vue')
}, {
path:'/big_screen_main/baidumap',
name: 'baidumap-b',
// 单个router-view用:component
component: () => import( '../views/baidumap.vue')
}]
},{
path: '/big_screen_main1',
name: 'big_screen_main1',
component: () => import( '../views/big_screen_main1.vue')
}
]
})
router.beforeEach((guard) => {
console.log("router.beforeEach", guard)
});
router.onError((handler) => {
console.log("router.Error:", handler);
});
export default router
main.js 下加载路由
import { createApp } from 'vue'
import app from './App.vue'
import router from './router'
const App = createApp(app,{});
App.use(router);
App.mount('#app');
和router版本变更后的区别差不多
vue3.0之前这样用
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
vue3.0之后 import { createStore } from 'vuex'
用createStore创建对象
store/index.js
import { createStore } from 'vuex'
import getters from './getters'
const modulesFiles = require.context('./modules', true, /\.js$/)
// 也可以这样引用 `import user from './modules/user'`
// 自动引用modules下的文件
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 = createStore({
state: {
collapsed: false,
},
mutations: {
SET_COLLAPSED: (state, val) => {
state.collapsed = val
}
},
actions: {
},
modules,
getters
})
export default store
main.js 下加载vuex
import { createApp } from 'vue'
import app from './App.vue'
import router from './router'
import store from './store'
const App = createApp(app,{});
App.use(router);
App.use(store);
App.mount('#app');
antd文档 https://2x.antdv.com/docs/vue/getting-started-cn/
安装antd后直接在main.js加载到vue(这里直接连同antd自定义主题一起弄了)
main.js
import { createApp } from 'vue'
import app from './App.vue'
import router from './router'
import Antd from 'ant-design-vue/es';
import 'ant-design-vue/dist/antd.less'; // 自定义主题需要引入less文件
import * as Icons from "@ant-design/icons-vue"; // 批量引入antd的图标组件
import store from './store'
const App = createApp(app,{});
App.use(router);
App.use(Antd);
App.use(store);
批量引入antd的图标组件
for (const i in Icons) {
App.component(i, Icons[i]);
}
App.mount('#app');
babel.config.js
module.exports = {
presets: [
'@vue/cli-plugin-babel/preset'
],
plugins: [
[
"import",
{ libraryName: "ant-design-vue", libraryDirectory: "es", style: true }
]
]
}
配置主题风格
完整的vue.config.js
/**
* vue会读取该文件,并合并到webpack配置文件上面,如果你想了解更多关于cli3和webpack
* https://cli.vuejs.org/zh/guide/webpack.html
*/
const CompressionWebpackPlugin = require("compression-webpack-plugin");
const IS_PRODUCTION = process.env.NODE_ENV === "production";
const path = require('path')
const cdn = {
css: [],
js: [
],
};
// const host = window.location.host;
console.log(IS_PRODUCTION);
const externals = {
};
const resolve = dir => {
return path.join(__dirname, dir)
}
module.exports = {
publicPath: "./",
outputDir: "dist",
assetsDir: "static",
indexPath: "index.html",
productionSourceMap: false, // 关闭sourceMap
configureWebpack: {
// Webpack配置
// devtool: "none", // webpack内关闭sourceMap
optimization: {
// 优化配置
splitChunks: {
chunks: "all",
cacheGroups: {
// 拆分Vue
vue: {
test: /[\\/]node_modules[\\/]vue[\\/]/,
name: "chunk-vue",
},
},
},
},
resolve: {
alias: {
"@": resolve("src"), // 主目录
"views": resolve("src/views"), // 页面
'components': resolve("src/components"), // 组件
'api': resolve("src/api"), // 接口
'utils': resolve("src/utils"), // 通用功能
'assets': resolve("src/assets"), // 静态资源
'style': resolve("src/style"), // 通用样式
},
},
externals: {
"BMap": "BMap",
'BMapLib': 'BMapLib'
}
},
pluginOptions: {
'style-resources-loader': {
preProcessor: 'less',
patterns: [
resolve('path/to/global.less')
]
}
},
chainWebpack(config) {
if (IS_PRODUCTION) {
config.plugin("html").tap(args => {
args[0].cdn = cdn;
args[0].title = "ST-ADMIN";
return args;
});
config.externals(externals);
config.plugin("html").tap(args => {
args[0].minify.minifyCSS = true;
return args;
});
// gzip需要nginx进行配合
config
.plugin("compression")
.use(CompressionWebpackPlugin)
.tap(() => [
{
test: /\.js$|\.html$|\.css/, // 匹配文件名
threshold: 10240, // 超过10k进行压缩
deleteOriginalAssets: true, // 是否删除源文件
}
]);
} else {
config.plugin("html").tap(args => {
args[0].title = "ST-ADMIN";
return args;
});
}
},
css: {
// 是否使用css分离插件 ExtractTextPlugin
extract: !!IS_PRODUCTION,
// 开启 CSS source maps?
sourceMap: false,
// css预设器配置项
// 启用 CSS modules for all css / pre-processor files.
requireModuleExtension: true,
loaderOptions: {
less: {
lessOptions: {
modifyVars: {
'primary-color': '#1890ff', // 全局主色
'link-color': '#1890ff', // 链接色
'success-color': '#52c41a', // 成功色
'warning-color': '#faad14', // 警告色
'error-color': '#f5222d', // 错误色
'font-size-base': '14px', // 主字号
'heading-color': 'rgba(0, 0, 0, .85)', // 标题色
'text-color': 'rgba(0, 0, 0, .65)', // 主文本色
'text-color-secondary ': 'rgba(0, 0, 0, .45)', // 次文本色
'disabled-color ': 'rgba(0, 0, 0, .25)', // 失效色
'border-radius-base': '2px', // 组件/浮层圆角
'border-color-base': '#d9d9d9', // 边框色
'box-shadow-base': '0 2px 8px rgba(0, 0, 0, .15)', // 浮层阴影
},
javascriptEnabled: true,
},
},
},
}
}
到这里基本的结构已经搭建起来了
下一篇文章再说其他组件的引入