vue3 自定义系统流程【1】

516 阅读5分钟

本文已参与「掘力星计划」,赢取创作大礼包,挑战创作激励金。

vue3 自定义系统流程

  • 升级vue 全家桶 及修改 vue-element-admin

零 前言

  1. 说明
  • 我并不是全职前端,对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 出来。

  1. 适用范围
  • 本文也许适合,类似我这样,完全没入门,发贴问容易被人说自己去看文档,看文档又看的一头雾水的吃瓜群众。。但又很想吃瓜的菜菜
  1. 计划
  • 整篇按照 安装-升级-优化的流程进行
  • 先将所有的升级一遍,然后再改一些自己觉得不太合理的地方。
  1. 感谢和抱歉
  • 感谢花裤衩 的那个教程,基础更好的直接去看那个就可以了。下面有链接。
  • 不足或者没有做到或者做错的欢迎指正,我会修改。
  1. 附录:【后面还会添加】
  • 改动源码 :源自花裤衩的 手摸手系列 链接:juejin.cn/post/684490…
  • 参考文档:vue 官网,element 文档,等。。后面会补充

一、使用cli 快速生成

  1. 进入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  
- 会自动启动服务器

二、调整部分默认文件夹

  1. App.vue
  • 去除示例中的实例组件及 css
<template>
  <div id="app">
    <router-view />
  </div>
</template>

<script>
export default {
  name: 'App'
}
</script>
  1. main.js 的变化及设置
import { createApp } from 'vue'
import App from './App.vue'
import router from './router'
createApp(App).use(router).mount('#app')
  1. 示例组件的删除和 新建新示例
  • 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

三、路由

  1. 安装路由 vue-router
  • 4.x 最新版
npm install vue-router@4
  1. 创建路由?
  • 创建 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

/**
   * 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: '/',

四、静态资源及样式表

  1. 安装 sass 加载器
npm i -D sass
npm i -D sass-loader
  1. 静态资源文件夹
  • 静态资源都放到【assets】 中【打包后直接拷贝的】,例如图片、logo等
  1. 新建资源文件夹 res;用于放置 svg、sass 等文件
  • 创建 res/icons
  • 创建 res/styles
  • 创建 res/styles/global.scss 全局样式表
- main.js 中引入
import '@/styles/global.scss' // global css
  • 将 index.scss 考入,前面的import 先不考入,后面再说

五 svg 的支持

  1. 安装插件
npm i -D svg-sprite-loader
  1. 增加 svg 组件
\src\components\SvgIcon
  1. 增加工具文件夹 src/utils/
  • 创建 validate.js 验证器
  1. 资源文件夹 src/res/icons/svg
  • 放入 svg 文件
  1. 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')
  }

}
  1. 创建配置文件夹及 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)
  1. 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')
  1. 模板 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>


  1. 首页测试 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 后 增加


问题

  1. 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
  1. 路由空白
  • 检查错误
  • 是否路径不对?是否定位到了文件夹?是否把文件夹和文件混淆了?
  • 或者看看是否只有div ,没有内容
  1. 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


  1. error The $listeners is deprecated vue/no-deprecated-dollar-listeners-api
  1. "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')