本文已参与「掘力星计划」,赢取创作大礼包,挑战创作激励金。
vue3 自定义系统流程
- 升级vue 全家桶 及修改 vue-element-admin
零 前言
- 说明
-
我并不是全职前端,对vue向往已久,一直都是在用jq 和 原生js 外加layui 开发前端。最近受到layui 的”告别演讲“ 触动,意识到得找新的框架来用了,却又无从下手。刚好回过头来看到了收藏夹藏了很久的花裤衩的手摸手,终于决心来搞一搞。
-
vue 现在已经是4,cli 全家桶也升级了,又看了一下 vue-element-admin ,发现得自己升级。
-
其实我看了有阵子vue的文档,对于es6不算很熟,ts也 不算熟,虽然有老 html和 css js 以及部分h5 的一些基础,还是看的一头雾水。想了想,拿个实例来修改还是最容易入门的。于是有了这个文章,作为一个新前端菜鸟的记录。
-
会分为几部分来写。其实这个是我自己的开发笔记,现在已经到第4部分了,但是第3部分写的还不咋地,觉得还得重写。。。
-
每部分下面都有【问题】 ,是这个流程发现的问题,以及一些解决方法。
-
源码基本来自花裤衩的 vue-element-admin,我看了一下协议是MIT的。中间有一些我觉得好像不合理的,我自己也改了一下,所以到时候这个做完了也会是MIT 出来。
- 适用范围
- 本文也许适合,类似我这样,完全没入门,发贴问容易被人说自己去看文档,看文档又看的一头雾水的吃瓜群众。。但又很想吃瓜的菜菜
- 计划
- 整篇按照 安装-升级-优化的流程进行
- 先将所有的升级一遍,然后再改一些自己觉得不太合理的地方。
- 感谢和抱歉
- 感谢花裤衩 的那个教程,基础更好的直接去看那个就可以了。下面有链接。
- 不足或者没有做到或者做错的欢迎指正,我会修改。
- 附录:【后面还会添加】
- 改动源码 :源自花裤衩的 手摸手系列 链接:juejin.cn/post/684490…
- 参考文档:vue 官网,element 文档,等。。后面会补充
一、使用cli 快速生成
- 进入web目录后 ,使用 vue cli 创建
cmd
cd d:/node/
vue create hello-world
-
会在 node 下创建 hello-world 模块,包含 .git, node_modules,public,src 等等;如果选择手动安装,会创建更多
-
运行
cd hello-world
npm run serve
- 会自动启动服务器
二、调整部分默认文件夹
- App.vue
- 去除示例中的实例组件及 css
<template>
<div id="app">
<router-view />
</div>
</template>
<script>
export default {
name: 'App'
}
</script>
- main.js 的变化及设置
import { createApp } from 'vue'
import App from './App.vue'
import router from './router'
createApp(App).use(router).mount('#app')
- 示例组件的删除和 新建新示例
- src/components/HelloWorld.vue 删除。也可以先保留,随便咯
- src 下新建views/layout 文件夹
- 建立 示例 首页 index.veu
<template>
<img alt="Vue logo" src="@/assets/logo.png">
<div>这是首页</div>
</template>
<script>
export default {
meta: {
name: 123,
},
};
</script>
<style>
#app {
font-family: Avenir, Helvetica, Arial, sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
text-align: center;
color: #2c3e50;
margin-top: 60px;
}
</style>
- 建立 错误页文件夹 error-page
- 创建 错误页 404.vue 401.vue
三、路由
- 安装路由 vue-router
- 4.x 最新版
npm install vue-router@4
- 创建路由?
- 创建 src/router 文件夹
- 新建 index.js
- index.js 的写法参考问题1,不需要再 import vue和router了
- 路由到刚才的错误页
export const staicRoutes = [
{
path: '/',
component: () => import('@/views/layout/index'),
//hidden: true
},
]
const router = createRouter({
history: createWebHistory(),
// scrollBehavior: () => ({ y: 0 }),
routes: staicRoutes
})
export default router
四、 拼写检查
- eslint
npm i -D eslint
五、 配置文件 vue.config.js
- 根目录 下的 vue.config.js
- 参考 cli.vuejs.org/zh/config/#…
/**
* You will need to set publicPath if you plan to deploy your site under a sub path,
* for example GitHub Pages. If you plan to deploy your site to https://foo.github.io/bar/,
* then publicPath should be set to "/bar/".
* In most cases please use '/' !!!
* Detail: https://cli.vuejs.org/config/#publicpath
*/
publicPath: '/',
四、静态资源及样式表
- 安装 sass 加载器
npm i -D sass
npm i -D sass-loader
- 静态资源文件夹
- 静态资源都放到【assets】 中【打包后直接拷贝的】,例如图片、logo等
- 新建资源文件夹 res;用于放置 svg、sass 等文件
- 创建 res/icons
- 创建 res/styles
- 创建 res/styles/global.scss 全局样式表
- main.js 中引入
import '@/styles/global.scss' // global css
- 将 index.scss 考入,前面的import 先不考入,后面再说
五 svg 的支持
- 安装插件
npm i -D svg-sprite-loader
- 增加 svg 组件
\src\components\SvgIcon
- 增加工具文件夹 src/utils/
- 创建 validate.js 验证器
- 资源文件夹 src/res/icons/svg
- 放入 svg 文件
- vue.config.js 中的配置
module.exports = {
//3.0版本
chainWebpack: config => {
const svgRule = config.module.rule('svg')
// 清除已有的所有 loader。
// 如果你不这样做,接下来的 loader 会附加在该规则现有的 loader 之后。
svgRule.uses.clear()
svgRule
.test(/\.svg$/)
.include.add(path.resolve(__dirname, './src/res/icons/svg'))
.end()
.use('svg-sprite-loader')
.loader('svg-sprite-loader')
.options({
symbolId: 'icon-[name]'
})
const fileRule = config.module.rule('file')
fileRule.uses.clear()
fileRule
.test(/\.svg$/)
.exclude.add(path.resolve(__dirname, './src/res/icons/svg'))
.end()
.use('file-loader')
.loader('file-loader')
}
}
- 创建配置文件夹及 svg 的配置文件
- /src/config/svg.js [其实就是以前的icons/index.js]
//此处递归获取.svg文件
const req = require.context('@/res/icons/svg', false, /\.svg$/)
const requireAll = requireContext => requireContext.keys().map(requireContext)
requireAll(req)
- main.js 中配置
import { createApp } from 'vue'
import App from './App.vue'
import router from './router'
import '@/res/styles/global.scss' // global css
import '@/config/svg' // icon
// createApp(App).use(router).mount('#app')
import SvgIcon from '@/components/SvgIcon/index.vue'// svg component
//const req = require.context('@/res/icons/svg', false, /\.svg$/) //这是svg文件路径
//req.keys().map(req)
const app = createApp(App)
app.component('svg-icon', SvgIcon).use(router).mount('#app')
- 如果不想要 【7步】的 svg.js, 也可以这样配置
import { createApp } from 'vue'
import App from './App.vue'
import router from './router'
import '@/res/styles/global.scss' // global css
import SvgIcon from '@/components/SvgIcon/index.vue'// svg component
//把 svg.js 的内容写在这里
const req = require.context('@/res/icons/svg', false, /\.svg$/) //这是svg文件路径
req.keys().map(req)
const app = createApp(App)
app.component('svg-icon', SvgIcon).use(router).mount('#app')
- 模板 src/components/SvgIcon/index.vue
<template>
<div v-if="isExternal" :style="styleExternalIcon" class="svg-external-icon svg-icon" v-on="$attrs" />
<svg v-else :class="svgClass" aria-hidden="true" v-on="$attrs">
<use :xlink:href="iconName" />
</svg>
</template>
<script>
// doc: https://panjiachen.github.io/vue-element-admin-site/feature/component/svg-icon.html#usage
import { isExternal } from '@/utils/validate'
export default {
name: 'SvgIcon',
props: {
iconClass: {
type: String,
required: true
},
className: {
type: String,
default: ''
}
},
computed: {
isExternal() {
return isExternal(this.iconClass)
},
iconName() {
return `#icon-${this.iconClass}`
},
svgClass() {
if (this.className) {
return 'svg-icon ' + this.className
} else {
return 'svg-icon'
}
},
styleExternalIcon() {
return {
mask: `url(${this.iconClass}) no-repeat 50% 50%`,
'-webkit-mask': `url(${this.iconClass}) no-repeat 50% 50%`
}
}
}
}
</script>
<style scoped>
.svg-icon {
width: 1em;
height: 1em;
vertical-align: -0.15em;
fill: currentColor;
overflow: hidden;
}
.svg-external-icon {
background-color: currentColor;
mask-size: cover!important;
display: inline-block;
}
</style>
- 首页测试 src/view/layput/index.vue 增加【测试 svg】
<template>
<img alt="Vue logo" src="@/assets/logo.png">
<div>这是首页</div>
<span class="svg-container">
<svg-icon icon-class="user" />
</span>
</template>
<script>
export default {
meta: {
name: 123,
},
};
</script>
六、增加默认配置 ./config/setting.js
- vue.config.js 中引入
const defaultSettings = require('./src/settings.js')
- module.exports 后 增加
问题
- Vue CLI 4 运行出现“export ‘default‘ (imported as ‘Vue‘) was not found in ‘vue‘的问题
- 之前在main中挂载的代码一般都是这个样子的
import Vue from "vue";
import App from './App.vue';
import router from "./router";
new Vue({
router,
render: h => h(App)
}).$mount("#app");
- 而cli4创建的项目默认是这个样子的
import { createApp } from 'vue'
import App from './App.vue'
createApp(App).mount('#app')
- 要按照cli4的写法去注册router或者store
createApp(App).use(store).use(router).mount('#app')
- 这样写的好处:
- 路由的js 里面,不需要再添加 import router 等了
- 之前的
import Vue from 'vue'
import Router from 'vue-router'
Vue.use(Router)
export const constantRoutes = [
{
path: '/',
component: Layout,
redirect: '/dashboard',
children: [
{
path: 'dashboard',
component: () => import('@/views/dashboard/index'),
name: 'Dashboard',
meta: { title: 'Dashboard', icon: 'dashboard', affix: true }
}
]
}
]
- 改成 :v4 写法
import { createRouter , createWebHistory } from 'vue-router'
const constantRoutes = [
{
path: '/',
component: () => import('@/views/layout/index'),
//hidden: true
},
]
const router = createRouter({
history: createWebHistory(),
// scrollBehavior: () => ({ y: 0 }),
routes: constantRoutes
})
export default router
- 路由空白
- 检查错误
- 是否路径不对?是否定位到了文件夹?是否把文件夹和文件混淆了?
- 或者看看是否只有div ,没有内容
- TypeError: this.getOptions is not a function
- 没有安装 sass
npm i -D sass
- 安装的 less-loader 或 sass-loader 版本过高,降低
npm un sass-loader
npm i -D sass-loader@8.0.0
- error The
$listenersis deprecated vue/no-deprecated-dollar-listeners-api
- V3 中 attrs
- 参考 v3.cn.vuejs.org/guide/migra…
- "export 'default' (imported as 'Vue') was not found in 'vue'
- Vue2 挂载代码
import Vue from "vue";
import App from './App.vue';
import router from "./router";
new Vue({
router,
render: h => h(App)
}).$mount("#app");
- vue3 cli4 挂载代码
import { createApp } from 'vue'
import App from './App.vue'
createApp(App).mount('#app')
- 然后使用
createApp(App).use(store).use(router).mount('#app')