目录

一.设计语言学习

1. 版本要求

2. 按需引入文件配置的2种方式

3. 组件列表

4.引入单个组件注意

5.配置.babelrc

二.搭建项目

1.安装vue的脚手架 vue/cli  (vue/cli2版)

2.新建项目

3.版本控制

(1). 安装svn服务端

(2). 发布到svn服务器

4.开发项目步骤、一些配置和一些注意文件的用途

(1). 端口

(2). 做主页

(3). 配置路由

(4). 引入组件 

(5). package-lock.json的作用

5.改变组件样式

三.项目开发

1.左侧菜单

2.顶部头菜单

3. vuex全局管理数据

4.后台获取菜单数据,配置路由菜单

(1). main.js中引入axios 

(2). 因为路由的路径要保存到store中,所以要在router/index.js中引入 store

(3). 从后台获取数据方法

(4). 在未真正从后台取数前,或许可以使用mock随机生成数据。

(5). 打印默认的可配置的路由路径

(6). 前置导航守卫,做验证,并配置component

(7). 配置component、动态路由数据、加载到router中

(8).路由配置成功标志 

5.关联菜单

(1). 获取store路由数据

(2). 菜单调用 

四. 问题


前言:一下一切都是我摸索中写的,不一定对,如果有写的不对,会误导大家的地方,请前辈们指正。

一.设计语言学习

1. 版本要求

(1). 现代浏览器和 IE9 及以上(需要 polyfills)    

      对于 IE 系列浏览器,需要提供 es5-shim 和 es6-shim 等 Polyfills 的支持。

      如果你使用了 babel,强烈推荐使用 babel-polyfill 和 babel-plugin-transform-runtime 来替代以上两个 shim。

      ( 避免同时使用 babel 和 shim 两种兼容方法,以规避 #6512 中所遇问题 )

(2). ant-design-vue  v1.3.8 稳定版

(3). Node.js  v8.9 或以上

 

2. 按需引入文件配置的2种方式

(1). 使用 babel-plugin-import(推荐)。babel-plugin-import 是一个用于按需加载组件代码和样式的 babel 插件。

// .babelrc or babel-loader option
{
  "plugins": [
    ["import", { "libraryName": "ant-design-vue", "libraryDirectory": "es", "style": "css" }] // `style: true` 会加载 less 文件
  ]
}

注意:webpack 1 无需设置 libraryDirectory

然后只需从 ant-design-vue 引入模块即可,无需单独引入样式。等同于下面手动引入的方式。

// babel-plugin-import 会帮助你加载 JS 和 CSS
import { DatePicker } from 'ant-design-vue';

这个配置在类似vue-cli@2的 .babelrc文件中

https://www.jb51.net/article/135232.htm          https://www.cnblogs.com/wulinzi/p/8079509.html

(2). 手动引入

import DatePicker from 'ant-design-vue/lib/date-picker';  // 加载 JS
import 'ant-design-vue/lib/date-picker/style/css';        // 加载 CSS
// import 'ant-design-vue/lib/date-picker/style';         // 加载 LESS

3. 组件列表

https://github.com/vueComponent/ant-design-vue/blob/master/site/components.js

4.引入单个组件注意

   (1). 在开发时,import { Button } from 'ant-design-vue';  的写法会引入了 antd 下所有的模块,

         这会影响应用的网络性能。( 因为from的时候是从所有中找,就会先把所有都加载了。)

   可以通过以下的写法来按需加载组件。

import Button from 'ant-design-vue/lib/button';
import 'ant-design-vue/lib/button/style'; // 或者 ant-design-vue/lib/button/style/css 加载 css 文件

  (2). 如果你使用了 babel,那么可以使用 babel-plugin-import 来进行按需加载,加入这个插件后。你可以仍然这么写:

import { Button } from 'ant-design-vue';

插件会帮你转换成 ant-design-vue/lib/xxx 的写法。另外此插件配合 style 属性可以做到模块样式的按需自动加载。

注意,babel-plugin-import 的 style 属性除了引入对应组件的样式,也会引入一些必要的全局样式。如果你不需要它们,建议不要使用此属性。你可以 import 'ant-design-vue/dist/antd.css 手动引入,并覆盖全局样式。

5.配置.babelrc

使用vue-cli@2和vue-cli@3的配置是不同的

如果配置env(环境)字段 https://excaliburhan.com/post/babel-preset-and-plugins.html

transform-es2015-modules-commonjs // 将modules编译成commonjs

 

二.搭建项目

1.安装vue的脚手架 vue/cli  (vue/cli2版)

   全局:npm install -g @vue/cli   (这是用vue/cli3)

   固定文件夹:npm install  vue-cli  (这个安装的是vue/cli2) 如果安装完了想升级 ,执行一遍 npm install @vue/cli 

   

 查看版本 vue -V 或 vue --version

2.新建项目

用vue/cli3:vue create antd-demo

用vue/cli2:vue init webpack ant_design

在问到Vue build时 ,build是项目打包时的命令,use arrow keys(可通过上下键进行选择,通常选一,就是直接回车就可以了)

问Install vue-router,是否初始化路由,选y,路由是必备项

这里问到ESLint时可选y,代码检查,是否用ESLint来校验你的代码。(如果想代码更规范,可选,但比如多一个或少一个空格,都是报警告信息,这个不是必选)。

如果选了yes(一般如果选了NO,别人的代码有一些带空格的校验,你更新别人的代码时,会把空格更新上,就显示很多行代码都更新了,不好判断具体别人都改哪些,需要一条条去找)

     第一个选项是标准的,具体校验规则可在网上搜索。

     最后一个是自己去配规则,可以自己设置一些规则,同时跟自己编辑器保存自动格式化的规则统一,如果是多人开发,就把workspace setting.json也上传到git,整个项目组的都统一格式化配置。

    (这里可选none,以后就只配空格的校验,让代码提交时,自己把空格加上)

Set up unit tests (Y/n)  --->是否建立单元测试,不用选,一般用不上

Setup e2e tests with Nightwatch:是否安装e2e测试,不选,一般用不上

Should we run `npm install` for you after the project has been created? (recommended) (Use arrow keys):是否创建完项目就直接自动安装包,如果自己搭着玩,可选y,有其他需求,比如发到服务器上进行管理,供他人下载,就选最后一个,上传服务器后,再手动安装 npm install

没有默认让它安装包,

如果想把项目发布到服务器进行版本管理,建议不要先安装包

① 因为会生成package-lock.json文件(下面有说)

② 因为上传服务器网速慢,可以先传项目,把项目从服务器检出后,再安装包。

cd到目录下,或者用软件打开项目,如果想加入别的包,可以改变package.json,再安装包 npm install。

初始化的包,生产环境dependencies只有2个包

安装包时,会出现警告提示,一些包的依赖包版本过低,当其他包需要同样的高版本的依赖包时,会安装高版本的包。

警告可略。

提高版本:

browserslist@2.11.3:browserslist 2在读取其他工具中使用的browserslist>3.0配置时可能失败。

查看后,有高版本的。

browserslist 目标浏览器配置表 https://www.jianshu.com/p/bd9cb7861b85

安装方法:(1). 在安装所有包之前,在package.json中的dependencies中加入

                  (安装后,再写到文件里,再执行npm install也可以,程序会跳过已安装的包,安装新的包。)

                  (2). npm install ant-design-vue

                  (3).安装到生产环境的包,安装时,把包信息写入到package.json中,  npm install 包名 -S 

npm install Xxx --save 安装模块,并把模块名和版本号添加到dependencies 部分。
  npm install xxx --save-dev 安装模块,把模块名和版本号写在devdependencies部分。
 -P 相当于 --save-prod,  添加dependencies 里面所有的包。在 -D -O 不存在时,-P 就是默认值
   -S 相当于 --save;      添加dependencies 里面所有的包。
   -D 相当于 --save-dev;  添加devDependencies 里面所有的包,
   -O 相当于 --save-optional, 添加在 optionalDependencies 里面的包,
   --no-save:      阻止保存记录在dependencies 中,

卸载包 npm uninstall xxx --save

在项目中:要学习ant design vue ,安装这个包,官网最稳定版本1.3.9 ,但这个可能是针对vue/cli3

                 所以安装低一点的版本  npm install ant-design-vue@1.3.8 --save

                  要到后台取数 要安装axios  npm install axios@0.18.0 --save

                  在写界面时,需要用到echart的话,要安装echart     npm install echarts --save

                  需要本地储存一些信息,全局使用,要安装vuex

在安装axios时遇到问题,官网最新版是0.19.0,兼容写的是ie11,不太确定ie11之前的兼容性。

所以选择安装 0.18.0  兼容到ie8以上  https://www.npmjs.com/package/axios/v/0.18.0

一般的包都是用es5写的,具体可以从git上看下源码,也有很少es6写的。比如一些第三方插件。

 

 

3.版本控制

(1). 安装svn服务端

在写项目之前,考虑要修改代码,对比不同版本的代码,所以要进行版本控制。

可以选用git 版本控制,但很多项目使用git不安全,所以,可以使用其他方式控制,比如svn。

用码云有免费的私有空间,但以后也许会收费。

在本地安装svn的服务端,作为版本管理的服务器。

在官网下载:https://www.visualsvn.com/server/download/

打开安装

文档:https://www.visualsvn.com/server/getting-started/

可选地,在启动安装之前调整默认配置设置。

  • 地点。指定VisualSVNServer安装目录。该选项只能在第一次安装时配置。
  • 储存库。指定存储Subversion存储库的根目录。建议在第一次安装时保留默认存储库位置。安装服务器后,可以更改存储库根目录。读这篇文章KB 22如果计划将存储库存储在网络共享上。
  • 服务器端口。指定VisualSVNServer将用于通过HTTP(S)访问存储库的TCP端口。安装服务器后,可以更改服务器端口。
  • 使用安全连接。指定是否使用安全HTTPS协议访问存储库。建议继续启用HTTPS协议。安装服务器后,可以调整此选项。
  • 备份。指定用于Subversion存储库备份的默认目标位置。

VisualSVNServer允许在安装期间选择身份验证模式。有两种身份验证模式:subversion authenticationWindows认证(建议用于ActiveDirectory环境)。读这篇文章KB 39:理解VisualSVN服务器身份验证选项想了解更多信息。

以后可以使用VisualSVN服务器管理器控制台重新配置身份验证模式。注意,在接下来的步骤中,安装程序将生成评估许可证,或者如果选择Windows身份验证,将请求您提供足够的许可密钥,因为在免费社区许可下无法获得此功能。

安装完成打开

新建版本库

有三种储存数据的方式 FSFS 和 BDB 和 VDFS (BDB在新版中以废弃)

区别:https://blog.csdn.net/weixin_34342207/article/details/85744176

           http://svnbook.red-bean.com/

           VDFS:https://www.visualsvn.com/server/features/multisite-replication/

没有数据锁定,可以立即将现有的基于FSFS的存储库转换为VDFS存储库,反之亦然。

选用基础的FSFS的。

给仓库命名,这个仓库是以后用来存项目的,在新发起项目时,在这个仓库中新建文件或者项目结构,这个之后说。

选择仓库结构,选最基础的

如果选高级:https://blog.csdn.net/mynamepg/article/details/79064304

设置权限,选择默认的了。

点击create

Finish 完成

https://wenku.baidu.com/view/95f3eeaef18583d048645986.html

创建用户

lyq 123456

创建组,并添加成员

给仓库添加权限

      

如果在上面配置的时候,选customize 这里应该就没有Everyone了。

接下来,把本地的项目配置到SVN的仓库。

(2). 发布到svn服务器

先在服务器端新建个文件或项目结构,用于保存要发布的项目。不建文件夹也能导,会乱七八糟的存在仓库中。

新建文件夹

新建项目结构

如果是项目结构,就多了3个空文件夹

所以,新建个文件夹就行了,结构不用这样的。

有了可以存项目的地方,可以把本地项目导入到服务器了。

安装svn客户端  https://www.visualsvn.com/visualsvn/download/tortoisesvn/

第二个选项默认是没选的,要选第一个,和图无关。为的是安装一个svn.exe文件

右击本地项目 → TortoiseSVN → 导入  → 到服务器地址 ,例如本地的https://LIYQ:9080/svn/ProjectLibrary/ant_design

发布项目时,因为有速度限制,所以开始不要安装包,如果安装了,先把项目的node_modules文件夹的删除,再导出。

写好地址,点击确定

https://LIYQ:9080/svn/ProjectLibrary/ant_design

关于忽略文件:https://blog.csdn.net/hemingwang0902/article/details/6904205

如果需要认证,输入用户名密码,如果不想每次都输,就保存认证,确定

导出完成了

(3). 导出项目到本地

右击要导出的地方,SVN检出(K)

为了和本地的有区别,文件名加_v,表示这是带版本更新的从服务器导出的项目。

导出成功

可以看到,本地的项目和检出的项目的区别,检出的项目带个绿色的对号。

这时,用软件打开,就会看到版本管理了。

原本地项目项目没有版本管理

检出项目有了

完美,可以开始愉快的写项目了 ^_^

可以安装包了,之后的修改,就提交就可以了。

当开发完成,把项目部署到其他服务器时,就打包成服务器能识别的压缩文件。dist 这个以后再研究。

4.开发项目步骤、一些配置和一些注意文件的用途

了解项目的目录:https://blog.csdn.net/zbl744949461/article/details/80433572

(1). 端口

在本地启动服务,先写定合适的端口,防止和本地其他项目冲突。

配置config文件下的index.js 的dev的 port 默认8080。

(2). 做主页

思路:主页考虑做一个主架构,

           header有logo,切换页签,用户头像等

           左侧有导航菜单,和根据头部的切换页签变化。菜单有收起功能

           中间上部有打开tab页有关闭功能,还有当前页的面包屑

           中间主体是根据菜单变换的子路由页面

在src文件夹下新建2个文件夹 layout(主页文件) 和 views(子页文件)

在src/assets文件夹下新建css文件,用于存放全局的css设置

   layout下有页面 index.vue 和 用到的components(index用到的组件)文件夹 和 error-page(放错误界面)文件夹,

   index.vue 中至少先写一个template标签,不然路由时会报错

   

   如果错误页面就只有1、2个,不放文件夹里,单独放出来和index.vue并列也可以。

   layout文件夹下是不让用户删除的。

   理论上主页可以都写到同一个界面里,但都写在一个界面里,代码很长,不方便多人调试,

    为了方便多人调试,做成index.vue和引用的组件一起使用。

    pages文件夹下有demo(开发的事例,以后如果用户不需要,删除也可以)文件夹。

    

(3). 配置路由

   默认项目的组件路由指向的是src/assets/components/HelloWorld.vue

   假如要改成新的界面 src/layout/index.vue

   在router下的index.js修改

   import 时,from的是文件夹,会默认找文件夹下的index.vue文件,找不到会报错。

   

项目要实现从后台获取路由信息,并配置路由。前端实现动态引入组件,并按需加载组件的功能。

所以,先不用import把所有组件导入。

用resolve来回调,resolve 就是 promise 的 resolve 回调,组件加载成功后调用。

这是异步加载组件,当你访问 / ,才会加载 ./layout/index.vue。

如下:

虽然动态调用组件成功了,但组件所用的代码还是会在打包时打包在同一个js文件夹里?,这样执行很慢?

使用 vue-cli构建的项目,在 默认情况下 ,会将所有的js代码打包为一个整体比如index.js。

当使用存在多个路由代码的时候,index.js可能会超大,影响加载速度。

用require.ensure后,这个每个路由页面除了index.js 还会有一个当前路由页面的js这样拆分了index.js的体积。

require.ensure这个函数是一个代码分离的分割线,表示 回调里面的require是我们想要进行分割出去的,

即require('./layout'),把./layout/index.js分割出去,形成一个webpack打包的单独bundle。

可以在模块执行时才运行代码,只有在满足某些条件时才加载依赖项。

https://www.cnblogs.com/weiyuanquyu/p/8432044.html

https://webpack.docschina.org/api/module-methods/#require

https://www.jianshu.com/p/9fa38e536033

第一个参数是什么意思呢?[], 其实就是 当前这个 require.ensure所依赖的其他 异步加载的模块。

你想啊?如果A 和 B都是异步加载的,B中需要A,那么B下载之前,是不是先要下载A啊?,

所以ensure的第一个参数[],也是请求下载的模块,如果想加载A require.ensure(['A.js'],function) 即可。

代码如下:(bundle名可以省略)

这只是获取了一个组件,要获得所有的routes,先从后台获取,在通过 router.addRoutes([所有路由数组]),

把所有路由加载进来。

注:路由中如果配置path之类的, 或 有唯一性的值,不要重复,不然菜单获取后会报错,虽然不影响使用,但不好看。

如下,就是有多个path:/form。

(4). 引入组件 

在main.js中 引用ant design vue的插件,并注册成全局组件,在任意地方都可以使用。

vue.use()全局注入一个插件,从而不需要在每个组件文件中import插件。

https://segmentfault.com/a/1190000016256277

https://blog.csdn.net/weixin_42283462/article/details/80600623

引入插件 import Antd from 'ant-design-vue'

引入样式 import 'antd-design/dist/antd.css'

全局注册 Vue.use(Antd);

在webstorm软件中显示的安装包文件下没显示这个css文件,但实际目录下有。

  

引入全局预设样式 import './assets/css/reset.css'      这个./ 指的应该是main.js的相对路径文件夹src

 

(5). package-lock.json的作用

      https://www.cnblogs.com/cangqinglang/p/8336754.html 

      其实用一句话来概括很简单,就是锁定安装时的包的版本号,

      并且需要上传到git,以保证其他人在npm install时大家的依赖能保证一致。

      根据官方文档,这个package-lock.json 是在 `npm install`时候生成一份文件,

      所以,在项目上传到服务器之前,不要先安装包

 

 

 

5.改变组件样式

当要改变引用的组件渲染后出现元素的样式,私有化的要用到>>>

https://blog.csdn.net/WXY19951125/article/details/83176417

.tagParent 是在引用组件上定义的, .ant-tabs-tab是页面上占时没有、未被初始化的元素。

三.项目开发

1.左侧菜单

分成了3部分做

在index.vue中引入leftMenu组件,在leftMenu中引用submenu组件

ant 的菜单组件,因组件内部会动态更改a-sub-menu的属性,如果拆分成单组件,无法将属性挂载到a-sub-menu上。

官方使用了函数式组件 https://github.com/vueComponent/ant-design-vue/blob/master/components/menu/demo/SubMenu.vue

如果不使用函数式组件,会报错

functional:函数式组件 

https://cn.vuejs.org/v2/guide/render-function.html#%E5%87%BD%E6%95%B0%E5%BC%8F%E7%BB%84%E4%BB%B6

2.顶部头菜单

切换顶部头菜单的选项,左侧菜单随之变化。

需要从后台获取菜单数据,并动态生成菜单目录。

考虑到这种数据联动变化,使用vuex全局来管理数据和路由子菜单。

3. vuex全局管理数据

vuex的功能是 读取数据,保存数据,操作数据

keep-alive 的功能是缓存切换路由页面,界面做了操作,切换回来,操作还在。

vuex是一个专门为vue.js设计的集中式状态管理架构。

安装vuex   https://vuex.vuejs.org/zh/installation.html

npm install vuex --save  

状态管理:https://cn.vuejs.org/v2/guide/state-management.html#%E7%AE%80%E5%8D%95%E7%8A%B6%E6%80%81%E7%AE%A1%E7%90%86%E8%B5%B7%E6%AD%A5%E4%BD%BF%E7%94%A8

flux 架构: https://facebook.github.io/flux/docs/in-depth-overview.html#content

深入响应原理:https://cn.vuejs.org/v2/guide/reactivity.html

使用步骤:  http://www.php.cn/js-tutorial-394689.html

在src文件夹下新建个文件夹vuex,在文件夹下新建文件store.js

在store.js中引用 vue 和 vuex

import Vue from 'vue'
import Vuex from 'vuex'

Vuex.store构造器的使用 https://vuex.vuejs.org/zh/api/

const store = new Vuex.Store({ ...options })

store状态管理有5个核心,分别是state、getter、mutation、action以及module

暂时用其中的三个

const store = new Vuex.Store({

state:{},

getter:{},

mutation:{}

})

导出store

export default store 或者 export {store as default};    

不建议用 export {store};

 用默认导出default的原因 在 

https://blog.csdn.net/zbl744949461/article/details/80433572  10 import和export中有写。

在main.js中引入这个对象,挂载到Vue的原型上

import store from './vuex/store'

Vue.prototype.$store=store

state:https://vuex.vuejs.org/zh/guide/state.html

便于全局管理 ,Vuex 通过 store 选项,提供了一种机制将状态从根组件“注入”到每一个子组件中

在new Vue的实例中,放入store,便于全局使用管理。 vue这个构造函数是怎么工作的。

4.后台获取菜单数据,配置路由菜单

(1). main.js中引入axios 

      这步是以后用的,在配置路由菜单这里没用,可以先不引用。

      https://blog.csdn.net/connie_0217/article/details/78703112

      import axios from 'axios'
      Vue.prototype.$axios=axios;

(2). 因为路由的路径要保存到store中,所以要在router/index.js中引入 store

      import store from './vuex/store'

      先定义个常量 空路由 并导出

      const router new Router();

      //  const router = new Router({routes: [] })       (注:如果要这样写,这里不要写错了?,是routes?,这是必须吗?)

     export default router

     要使用路由,在new Vue时,要把路由传入。

     在main.js中import router from './router'

      new Vue 时加入 这2步在vue cli中默认就有。

      

(3). 从后台获取数据方法

      要从后台拿到返回数据,需要axios,考虑到拿到的数据有的是和我们设定要求的数据格式一样,有的不一样,

      如果不一样,就需要提前处理成一样的。考虑到这样的需求,将这个获取和处理的过程,放到另外一个js文件中执行,

      在当前文件只使用 已处理好的数据 格式。可以看看 vue-element-admin 找找灵感

      在src文件夹下新建permission.js文件(许可),并把这个文件引入到router/index.js中。

      从后台取数需要axios 在permission.js中引入axios (是的,axios是这里要用的,所以在这里引用

      import axios from 'axios'

      考虑要导出,所以先定义个常量,这个常量如果是个函数,获取后台数据,并返回值,它就是变量了,

       所以,把让它接收一个内置方法,让这个方法去处理后台返回的数据。

       这样,这个常量可以被导出使用了,也不会变成变量。

       const findMenusByService = function(处理数据,动态构建路由的函数){

      //获取后台数据

      axios.get('先写静态数据json地址').then(res =>{

           //如果后台返回的数据格式不对,预先处理

          //处理后,使用函数方法,动态构建路由

          构建路由方法(res);  

       });

}

导出 常量 函数对象

export default findMenusByService;

也可以这样写:因为这个aaa是个参数,向上面的写法,就是告诉程序员,这里以后要用的方法名是什么。上面的比较好。

动态获取路由的方法,在index.js中写。

(4). 在未真正从后台取数前,或许可以使用mock随机生成数据。

      可以看看vue-element-admin的mock  文件目录。

      https://panjiachen.github.io/vue-element-admin-site/zh/guide/essentials/mock-api.html#easy-mock

      如果使用mock 语法:https://github.com/nuysoft/Mock/wiki

      在static文件夹下建mock文件夹,或者在src同级新建个mock文件夹(不推荐,麻烦,需要安装express),

      在其面写一个routers.json,

      在static下创建的好处是,axios获取本机json数据时,可直接获取,不在static中的,需要配置。

      在vue-cli生成的项目的目录结构中,除了static目录下是能够被外面访问,其他任何路径下的文件都不能被外面直接访问到。

      想要访问需要修改build–webpack.dev.conf.js文件

       要安装express: http://www.expressjs.com.cn/starter/installing.html

                                https://www.runoob.com/nodejs/nodejs-express-framework.html

      配置如下:https://blog.csdn.net/m0_38134431/article/details/83786085

                        https://segmentfault.com/q/1010000011628771

     关于静态文件:不确定解析:https://blog.csdn.net/Mr_YanYan/article/details/78783091

     如果没配置,直接写,会报如下错误

     

     基于真正的数据要在后台取,所以将 存假数据的mock文件夹 写在static下,简化取数步骤。

      routers.json中,写嵌套路由的路由地址格式 https://router.vuejs.org/zh/guide/essentials/nested-routes.html

      这里的 .指src文件夹?(不懂

      格式:

默认应该有默认的路径path,默认的组件component,如上默认找layout文件夹下的index.vue,

path是显示在url地址上#后面的,不是真实路径。

根目录组件是./layout下的index.vue,里面的要嵌套子组件,新建放置子组件的组件,这样写对吗

?其他路由的子组件在子组件中渲染,component的路径为./layout/RouterView.vue

 ? 在index.vue中导入RouterView,使用。

注:每次写嵌套路由,都要从外到内,先写最外父组件,再写子组件,再写子子组件,每一层都不能少。

       多余的逗号,ie8以上都可以兼容,但如果有多余的逗号,虽然不会报错,但获取数据时,json就不是个json对象了,

      变成了一串字符串,这样,在获取数据时就会有问题。

      当有多余逗号时,控制台打印 console.log(res,data)是这样:

      

没有多余逗号才会打印正确,是这样:

所以,不要有多余逗号,如果后台传过来的有的话,一般没有。要做好处理。怎么处理?

当要使用从定向时,不要和本身的path相同,如果相同,会一直循环执行。

比如:

浏览器会报错

 

(5). 打印默认的可配置的路由路径

      因为是后台配置路由再返回到前台,所以,在控制台打印出所有可以路由的地址,方便后台使用。

      这个地址不准备在前台更改,如果有增加和删除,在后台配置进行。

      所以,这个保存路径的对象,应该是个常量。     

      展示的界面在layout或pages文件夹下,所以,只要匹配这2个文件夹下的vue文件就好了。

     layout下的component文件夹里的组件是index.vue专用的,需要父级传参,这个参数不是定义在store中,不是全局的。

     所以。这个文件夹下的组件,不准备给用户用,如果使用路由引入,因为没传参,可能回报错。

     pages下的界面是展示界面,不用父级传参,如果想要首页传参,在首页把参数写在store中,这样就可以全局获取了。

     (keys不要匹配带.vue结尾,后台配置路径不加.vue,所以只配默认目录和可用的layout和pages目录及子目录下的组件)

      配置默认的目录是因为可以用./layout这样的目录取到下面的index.vue,所以要加./layout这样的目录

      如果没有默认写法,用下面的正则

      const availableContext= require.context('..',true,/(layout|pages)(?!.components).*.vue$/);

Ⅰ  有默认目录,就要显示2种,文件夹目录,和不带.vue结尾的,正则要改成以下:

      const availableContext= require.context('..',true,/\/(?:pages|layout)(?!.components)(?![^\.]*\.vue).*$/);

         写正则的思路:

             ① 首先要在相对路径 ..下的目录: /\//

             ② 在pages或layout下 : /\/(?:layout|pages)/

                  这里用(?:x|y)而不用(x|y) 是什么考虑,应该都是消耗字符的

                  https://blog.csdn.net/shashagcsdn/article/details/80017678

             ③ 去掉components文件夹下的组件

                  (?!.components)

             ③ 去掉带.vue结尾的路径

                 (?!.*\.vue)          

             ④ 考虑到以后要用require.ensure([],function) 可能都会用[]作为导入组件的依赖项,

                  layout/component下的组件依赖index.vue,但实际index.vue是最先导进来的,

                  如果以后单独使用layout/component下的组件,这里没有和依赖一起打包,不知道会不会有问题。

                  所以想在可给后台使用的组件目录中,去掉layout/component下的组件地址。

                 待写。

             ⑤ 还有些想不明白,再思考。

        于是这样写了:

        require.context('..',true,/\/(layout|pages)(?!.*\.vue)/);

         正则:https://deerchao.net/tutorials/regex/regex.htm

         require.context:https://www.jianshu.com/p/c894ea00dfec

         一个webpack的api,通过执行require.context函数获取一个特定的上下文,主要用来实现自动化导入模块

         只是模块,css不行。

         加快Vue项目的开发速度 https://juejin.im/post/5c106485e51d450e657571a6

         require.context函数接受三个参数

              directory {String} -读取文件的路径

              useSubdirectories {Boolean} -是否遍历文件的子目录

              regExp {RegExp} -匹配文件的正则

用keys()属性获取所有文件路径,展示到控制台,直接打印容易和数据混用,使用console.info()方法,打印信息,规范打印。

Ⅱ  const availablePageKeys = availableContext.keys();

Ⅲ  console.info('generate routers', {availablePageKeys} );

代码:

   调用require.context函数执行后 返回的是个函数webpackContext(req){},并且这个函数有3个属性 (这些在之后会用

             ① resolve {Function} -接受一个参数request,

                   request为test文件夹下面匹配文件的相对路径,返回这个匹配文件相对于整个工程的相对路径

             ② keys {Function} -返回匹配成功模块的名字路径组成的数组

             ③ id {String} -执行环境的id,返回的是一个字符串,主要用在module.hot.accept,应该是热加载? 

  https://segmentfault.com/a/1190000017160862

  https://www.cnblogs.com/zhouyideboke/p/10948294.html

  

 console.log(availableContext) 查看更多这个函数的上下文的js文件,

用availableContext(路径)可以得到一个对象?

(6). 前置导航守卫,做验证,并配置component

思路:二.4.(3)配置路由

在路由跳转前做一些验证,比如登录验证,是网站中的普遍需求。

在这个项目,点击跳转路由前,

① 首先需要从后台获取路由数据,

② 然后判断 所有可跳转的路由组件 是否 在本地存在,有,给它的组件属性赋值,没有就赋404。

③ 新建个空数组常量dynamicRouter,用于以后保存 动态路由数据。(这个写在导航守卫外面定义

④ 要把动态路由数据存到store中,用于给左侧菜单和顶部菜单使用。

⑤ 然后把整理好的动态路由数据通过 router.addRoutes(动态路由数据)到router(开始设置的是个空路由),

⑥ 再进行next()跳转。

⑦ 因为用了addRoutes()方法,为了确保addRoutes已完成,要用到hack方法跳转:next({...to,replace:true})

// hack方法 确保addRoutes已完成,设置replace:true,这样导航就不会留下历史记录。

因为要在跳转路由前实现这些需求,给路由一个全局前置导航守卫,用来处理这些需求,处理完,再跳转。

简单的例子:

因为网站地址现在默认访问路径就是"/",所以,就是执行到/了,导航守卫通过next()就跳转了。

next()方法传参不传参的不同,

next()传参的时候会再次进入路由钩子,容易出现n多次循环就导致堆栈溢出而报错(如下图)

而直接调用next()就不会在进入这个钩子。

所以我们在使用时,为了不让它一直循环执行,要给它条件判断执行。

前置导航守卫用router.beforeEach() 方法

https://cn.vuejs.org/v2/guide/migration-vue-router.html#router-beforeEach-changed

导航守卫:https://router.vuejs.org/zh/guide/advanced/navigation-guards.html

嵌套路由:https://router.vuejs.org/zh/guide/essentials/nested-routes.html

前辈解析:https://www.cnblogs.com/WQLong/p/8135553.html

三个参数:

  • to:router即将进入的路由对象
  • from:当前导航即将离开的路由
  • next:Function,进行管道中的一个钩子,如果执行完了,则导航的状态就是 confirmed (确认的);否则为false,终止导航。

为了解决next()传参重复进入钩子循环这个问题,加一个判断:

测试:

加判断条件,在第一次进入导航守卫时,a的长度是0,a数组加入6,执行传参的next(),

这时再执行,a的长度就不是0了,就去执行next()了。

扩展运算符... :将一个数组转为用逗号分隔的参数序列 

http://es6.ruanyifeng.com/?search=%E6%89%A9%E5%B1%95%E8%BF%90%E7%AE%97%E7%AC%A6&x=0&y=0#docs/array#%E6%89%A9%E5%B1%95%E8%BF%90%E7%AE%97%E7%AC%A6

执行过程:

第一次打开网址,通过访问/目录时,调用导航守卫,

这时,动态路由还是空的,执行方法findMenuByService,给路由加内容,再执行就不是空的了,就会跳next()方法。

这里用!dynamicRouter.length 可以包含很多种情况,比单一的 dynamicRouter.length == 0 好。

(7). 配置component、动态路由数据、加载到router中

具体配上一步的a方法,a是用来生成路由的,起个好听的名字generateRouter。

① const dynamicRouter=[]; 初始动态路由列表为空

② generateRouter方法: 

     

     generateRouter方法中设置的 常量f方法 就是 用来配置component 和 动态路由数据dynamicRouter 的。

          from:路由数据

          to:要写进的数组

    第一次执行是从后台获取的路由数据,经f处理,写到dynamicRouter数组中。

③ f方法:

最终要把解析好的目录push到dynamicRouter中,先要验证每个目录对应的路由组件是否存在。

具体细节步骤:

Ⅰ新建 常量 component = item.component 这是后台返回的组件路径

Ⅱ 新建 变量route ,route的其他属性直接定义在route上,组件要验证,先不挂在route上

Ⅲ 如果组件存在,

❈ 处理思路,要给每个组件属性赋上组件。

    ① 首先,如果用import引入组件给每个组件,就会一个个组件都加载进来,

        当项目打包时路由里的所有component都会打包在一个js中,成一个很大的index.js文件。

        造成进入首页时,需要加载的内容过多,时间相对比较长。

        当你用require.ensure这种方式引入的时候,会将你的component分别打包成不同的包,

        只用访问这个路由网址时才会加载这个包,第一次加载后会缓存。

        加载组件的时候是按需加载,通过resolve ↓

        component: resolve => require(['../pages/home.vue'], resolve),

        异步组件:https://cn.vuejs.org/v2/guide/components-dynamic-async.html#%E5%BC%82%E6%AD%A5%E7%BB%84%E4%BB%B6

         resolve 就是 promise 的 resolve 回调,组件加载成功后调用

         https://segmentfault.com/q/1010000017913060

    ② 给组件赋值

         https://webpack.docschina.org/api/module-methods/#require       

         https://www.cnblogs.com/leaf930814/p/8109747.html

     route.component = 判断组件是否在项目真正的组件列表里存在,

                                     如果存在,等于上,如果不存在,就挂404页面,

    使用some()方法判断本地所有可路由的组件路径有没有和后台返回的匹配的,

    如果全部循环有一个匹配上返回true,如果所有都匹配不上,返回false。  

    后台配置路径可能不加.vue这个后缀,在这里要判断下。在原值和加后缀2中情况下,有一种成立就可以。

  availablePageKeys.some(key =>{
    return  key == component || key ==component+'.vue';
  });

     用数组的some()方法验证 https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Array/some

    require.ensure()方法,以异步方式加载到单独的包中。在使用CommonJS模块语法时,这是动态加载依赖项唯一方法

                             官方文档: https://webpack.docschina.org/api/module-methods/#require-ensure

                             https://blog.csdn.net/zhbhun/article/details/46826129

    需要的时候才下载依赖的模块,requi.ensure的模块只会被下载下来,不会被执行,

    只有在回调函数使用require(模块名)后,这个模块才会被执行。所以要用 return xxx 调用下。

    `${expression}` 模板字面量 和 字符串占位符字 http://www.softwhy.com/article-9991-1.html

Ⅳ 如果item有子项,route.children=[],再执行一遍f(item.children,route.children)  (这个route.children=[]必须写吗,如果为了让它是初始化值是[],在新建变量route时,就写上不好吗,想了下,因为新建变量时,没有子项,就不需要这个属性,这个是动态的,写在这里判断很好。)

④ 并将dynamicRouter保存到store中

先在store的state属性中定义个属性RouterData,用来保存路由列表,这个数据以后要给左侧菜单和顶部菜单使用。

使用store要先在文件里导入store

store.state.RouterData = dynamicRouter;

给router动态添加更多的路由规则 https://router.vuejs.org/zh/api/#router-addroutes

⑤ router.addRoutes(dynamicRouter);

(8).路由配置成功标志 

     如果没有成功 在console.log(router)时,ready:false。 如果成功,会变成true。

     

5.关联菜单

路由配置成功后,和菜单关联在一起。

回到主页 layout/index.vue

(1). 获取store路由数据

因为路由的状态是依赖的响应式属性变化,所以在计算属性里写获取。

前提:在main中,把store绑定在vue的原型上,这里才能用this调用。(在 3.vuex全局管理数据 有写)

vue 生命周期:https://blog.csdn.net/zbl744949461/article/details/86134414

computed:{

    routes(){

         return this.$store.state.RouterData ;

    }

}

(2). 初始化菜单

打开界面时,要对界面的顶部菜单和左侧菜单进行初始化配置。

首先考虑到,根目录的菜单选项,不是顶部菜单和左侧菜单要使用的,所以,要先剔除掉根目录菜单。

在router.json中,给根目录加入属性 isRoot

在index 中,每个对象,如果有isRoot,isRoot就是true,没有就是undefined。

(3). 初始化顶部菜单

① 如果使用顶部菜单,顶部菜单会切换左侧菜单,所以先初始化顶部菜单。

假如顶部菜单如下图,默认显示4个,多余的放在。。。中,默认选中第一个。

关于顶部菜单的顺序,是否要在路由里加入排序的值(或者用key),让后台排好返回,

或者前台根据排序的值(或key值)排序。

② 考虑有的项目不需要顶部菜单,那要在data中写个参数enableTopMenu,用于判断要不要使用顶部菜单。

用就写true 不用就写false。

③ 定义初始化菜单的方法

如果使用菜单,顶部菜单数据就是过滤掉根目录以外的数组中的对象。

④ 在哪里执行这个方法

    有2种方案,(watch在mounted之前执行)

   Ⅰ 在watch 中 通过观察 enableTopMenu为真,在侦听开始之后被立即调用执行。

    

   Ⅱ 在mounted中调用,如果在这里,就在方法里加判断。

   

   

  调用后,数据要传到子组件中使用。

初始化顶部菜单,需要除了根目录以外的所有顶级菜单,name和key

 

(4). 初始化左侧菜单

 

(5). 顶部菜单切换左侧菜单

 

主题配置

假如项目要配置多种主题

比如首页框架,要用6个组件和路由的子界面。

① 先有个全局的css文件 reset.css 定义些基础样式,比如字体。

② 假如要3种主题风格,就要有3个css文件用来存放这些主题样式。

     原方案想,首页框架的6个组件,分别在组件内部写自己的样式,在主题文件里写一些颜色,字体的变化。

     后来想,如果主题有宽窄,位置布局变化,那改变主题后,可能会与组件自己的样式冲突,要来回反复改。

     于是,样式都写在主题css文件中,组件中不写。这样,即使有修改总字体需求,要3个文件一起改,

     但在主题自己的定位布局特色中,不会和其他地方的css冲突。

③ 还要注意 主题有全局class名 比如 .vaa-dawnblue    .vaa-darkblue   .vaa-red 

    组件里的命名要带独立前缀,防止与以后用户的命名冲突,比如 vaa-main-top-menu

    这样即使用户用top-menu 也不会与我们的定义有冲突

④ 引用ant design vue 的组件,组件也有不同的样式 这些组件,每个组件建立单独的css文件,用来放置预设样式

打包常见错误:https://www.cnblogs.com/hjvsdr/p/8064880.html

四. 问题

1.jsx不懂,啥时候去学???

   在"快速上手"中,jsx是怎么用的。https://baike.baidu.com/item/JSX/1686693?fr=aladdin

   

    https://github.com/vuejs/babel-plugin-transform-vue-jsx

 

Logo

前往低代码交流专区

更多推荐