vue-admin 详细注释,必须手把手作项目系列之(一)

vue-admin-stepbystep

A Vue.js projectjavascript

系列文章

项目功能

  • 1 登陆
  • 2 首页
  • 3 退出
  • 4 table页

项目技术点

  • 1,使用vue
  • 2,使用echarts
  • 3, 使用json-server (系列二写详细文档)
  • 4, 使用node起一个简单的服务,服务于接口(系列二写详细文档)
  • 5, 使用axios
  • 6, vue-router的使用规则(异步加载,和同步加载)
  • 7, 回话拦截的使用(localstorage or cookie)
  • 8, 配合element-UI
  • 9, 修改组件里面的样式里面的坑
  • 10, 打包时的优化
  • 11, DNS优化
  • 12, 配置本地代理,使用接口(系列二写详细文档)
  • 13, 使用axios配合json-server 模拟增删改查(系列二写详细文档)
  • 14, 使用nprogress 插件
  • 15, 不为人知的element-UI 的滚动条
  • 16, 栅格布局,大小屏适应配合媒体查询
  • 17, css使用less
  • 18, 代码风格,我的风格,禁用了jslint 防止不懂得小伙伴抓狂
  • 19, 兼容性的处理(系列二写详细文档)

项目搭建

  • 1 vue init webpack XX 使用vue-cli 2.0
Project name                            :默认
Project description                     :默认
Author                                  :默认
Vue build                               :选择 Runtime + Compiler
Install vue-router?                     :Y
Use ESLint to lint your code?           :Y 选择 Standard
Set up unit tests                       :n
Setup e2e tests with Nightwatch?        : n
Should we run `npm install` for you after the project has been created? (recommended) : Yes, use NPM
复制代码
  • 2 进入项目:cd vue-admin-stepbystep
  • 3 运行项目:npm run dev

如何添加一个新的功能???

  • 1 在 components 中新建一个文件夹(login),在文件中建立组件(Login.vue)
  • 2 在 router/index.js 中导入组件(login.vue)
  • 3 配置路由规则

在项目中使用 element-ui(其余自行gg加深映像)

// main.js

// 导入elementui - js
import ElementUI from 'element-ui'
// 导入elementui - css
import 'element-ui/lib/theme-chalk/index.css'
// 安装插件
Vue.use(ElementUI)
复制代码

项目启动作了什么

  • 1 在终端中运行:npm run dev,实际上就是运行了:webpack-dev-server ...
  • 2 使用 webpack-dev-server 开启一个服务器
  • 3 根据指定的入口 src/main.js 开始分析入口中使用到的模块
  • 4 当遇到 import 的时候,webpack 就会加载这些模块内容(若是有重复模块,好比:Vue,实际上未来只会加载一次),遇到代码就执行这些代码
  • 5 建立 Vue 实例,将 App 组件做为模板进行编译,而且将 App 组件中 template 的内容渲染在页面 #app 的位置

路由配置

  • 1 异步加载路由
  • 2 使用进度条插件
  • 3 登陆拦截 会话保持
import Vue from 'vue'
import Router from 'vue-router'
//引入nprogress进度条
import NProgress from 'nprogress'
//引入nprogress进度条的样式
import 'nprogress/nprogress.css'
//在打包过程当中每个组件都会打包成一个js文件,若是不使用使用/* webpackChunkName: "home" */
//在打包的时候就会生成0.js,1.js等等,使用了以后就会打包成home.js
// 导入 Login 组件(注意,不要添加 .vue 后缀)
//这是路由的异步加载,!important,这是优化项目必须的

//引入home组件
const Home = () => import(/* webpackChunkName: "home" */ '@/components/home')
//引入登陆组件
const Login = () => import(/* webpackChunkName: "home" */ '@/components/login')
//引入table组件
const Table = () => import(/* webpackChunkName: "home" */ '@/components/table/table')
//引入homeMain组件
const HomeMain = () => import('@/components/HomeMain')

//这里是同步加载
//import Login from '@/components/login/Login'

Vue.use(Router)

const router = new Router({
	mode: 'history',//开启了history模式,去除了#,
	 // 在vue中,通常来讲经过实例去访问某个属性的
     // vm.xxxx vm.$set vm.$refs vm.$router
	routes: [
		{
			path: '/',
			redirect: '/homeMain'//路由的重定向
		},
		{
			path: '/login',
			name: 'login',
			component: Login
		},
		{
			path: '/home',
			name: 'home',
			component: Home,
			// children 用来配置子路由,未来匹配的组件会展现在 Home 组件的 router-view 中
		    // 对于子路由path来讲:
		    // 1 若是不是以 / 开头,那么,哈希值为: 父级path + / + 子级path
		    // 也就是: /home/homeMain
		    // 2 若是子级路由的path是以 / 开头的,那么未来的哈希值为:/users 再也不带有父级的path了
            // 也就是:/homeMain
            //这是页面中的子路由,在页面中必须声明router-view做为出口
			children: [
				{
					path: '/homeMain',
					name: 'homeMain',
					component: HomeMain
				},
				{
					path: '/table',
					name: 'table',
					component:Table
				}
			]
		}
	]
});
// 给router配置导航守卫
// to: 去哪儿
// from: from 哪儿来
// next() : next():放行 next('/login') 去login组件
// 在登陆成功之后,将 token 存储到 localStorage 中
// 在 导航守卫 中先判断当前访问的页面是否是登陆页面
// 若是是登陆页面,直接放行(next())
// 若是不是登陆页面,就从 localStorage 中获取 token,判断有没有登陆
// 若是登陆了,直接放行(next())
// 若是没有登陆,就跳转到登陆页面让用户登陆(next('/login')
router.beforeEach((to, from, next) => {
// 开启进度条
	NProgress.start()
// 获取是否有token
	let token = localStorage.getItem('myToken')
	// 若是已经就是要去login了,就不须要拦截了
	if (to.path === '/login' || token) {
		next()
	}else {
		next('/login')
	}
	
});
router.afterEach(() => {
// 关闭进度条
	NProgress.done()
})

export default router
复制代码

登陆功能

  • 1 安装:npm i -S axios
  • 2 在 Login.vue 组件中导入 axios
  • 3 使用 axios 根据接口文档来发送请求,完成登陆
  • 4 登陆时设置token ,能够用localStorage cookie等任君选择
<div class="l-right">
   		<div class="l-l">
   			 <!-- @tab-click="handleClick" -->
   			<el-tabs v-model="activeName">
   				<el-tab-pane label="用户登陆" name="first">
   					<!-- el-form:自定义表单组件 -->
   				    <!-- :model="form" 表单对象,用于收集收据 -->
   				    <!-- label-width="80px":label的宽度 -->
   				    <!-- el-form-item:表单项 -->
   					<el-form ref="form" status-icon :rules="rules" :model="form" label-width="80px">
   						<el-form-item prop="username">
   							<el-input v-model="form.username" placeholder="请输入用户名" prefix-icon="iconfont icon-yonghuming"></el-input>
   						</el-form-item>
   						<el-form-item prop="password">
   							<!-- 未来咱们给组件注册事件的时候,能够会注册不上 -->
   							<!--@keyup.enter点击键盘的enter触发事件-->
   							<!-- .native: 注册事件,给组件的根元素注册事件 -->

   							<el-input type="password" v-model="form.password" placeholder="请输入密码" @keyup.enter.native="login" prefix-icon="iconfont icon-mima"></el-input>
   						</el-form-item>
   						<el-form-item>
   							<!--使用@语法糖绑定事件-->
   							<el-button type="primary" @click="login">登陆</el-button>
   							<el-button @click="reset">重置</el-button>
   						</el-form-item>
   					</el-form>
   				</el-tab-pane>
   				<el-tab-pane label="帅哥登陆" name="second">长得很帅</el-tab-pane>
   			</el-tabs>
   		</div>
   		
   	</div>
   </div>
复制代码
export default {
		data () {
			return {
// 定义一些变量,可使用{{}}语法在页面中直接获取
				activeName: 'first',
				form: {
					username: 'why',
					password: "123456"
				},
				rules: {
					// 用户名的校验
					username: [
						// 用户名是必须
// required是否必须
// message提示信息
// trigger如何触发
						{ required: true, message: '请输入用户名', trigger: 'change' },
						{ min: 3, max: 6, message: '长度在 3 到 6 个字符', trigger: 'change' }
					],
					// 密码的校验
					password: [
						{ required: true, message: '请输入密码', trigger: 'change' },
						{ min: 6, max: 12, message: '长度在 6 到 12 个字符', trigger: 'change' }
					]
				}
			}
		},
		methods: {
			login () {
// 先触发页面中的检验规则,不经过给提示,经过就向后台发送请求,
// $refs是vue中获取页面的,在html中要写 ref="form"
		     this.$refs.form.validate(async (valid) => {
				 if (valid) {
// 使用axios向后台发送请求
// 在es6中的箭头函数没有this绑定,能够打印出来指向的是vue实例,这点能够自行百度,加深映像
					 this.axios('/api/login').then( res => {
						 console.log(res.data[0])//用来查看接口里面的数据
						 let lg = res.data[0] //把数据赋值给变量
						 console.log(lg.username,lg.password)//主要用来查看数据
						 if(lg.username === this.form.username && lg.password==this.form.password){
							 localStorage.setItem('myToken',lg.username)//设置拦截,能够用cookie等,在控制台中的Application中查看
							 this.$message.success('恭喜你,登陆成功')//登陆成功的提示
							 this.$router.push('homeMain') //使用编程式导航路由进行跳转
						 }else {
							 this.$message.error('帐号或者密码错误')//帐号密码错误时的提示

						 }
					 })
				 }
			 })
			},
			reset () {
				this.$refs.form.resetFields()//清空输入框中的信息
// 数据被我写死了,能够自行改动
			}
		}
  };
复制代码

顶部和侧边

<el-container>
			<!--给el-header设置 高度-->
			<el-header style="height: 70px;">
				<div class="logo">
					<!--这里能够放通常网站的logo-->
					<!--<img src="../assets/main/logo.png" alt="">-->
				</div>
				<div class="header-right">
					<div class="logout" @click="layout">
					    <!--javascript:;为了防止a标签的默认行为,-->
						<a href="javascript:;">退出</a>
					</div>
					<div class="people">
						<!--映入iconfont 的字体图标-->
						<i class="iconfont icon-lianxirenwode"></i>
						张三
					</div>
					<div class="call">
						<i class="iconfont icon-lianxiwomen"></i>
						联系咱们
					</div>
				</div>
			</el-header>
			<el-container>
				<el-aside width="160px" background-color="#26292E">
					<el-scrollbar style="height: 100%;">
						  <!-- el-menu: 导航菜单的组件 -->
				          <!-- default-active:默认高亮的菜单 -->
				          <!-- open close 展开和关闭的事件 -->
				          <!-- el-submenu: 子菜单 -->
				          <!-- el-menu-item-group: 子菜单中分组 -->
				          <!-- el-menu-item:子菜单中的每一项 -->
				          <!-- unique-opened: 保证只能打开一个子菜单 -->
				          <!-- router: 若是router为true,那么index就会做为路由的链接 -->
				          
						<el-menu :unique-opened='true' :router="true" text-color="#ffffff" active-text-color="#cccccc">
							<el-submenu index="1">
								<template slot="title"><i class="iconfont icon-shouye"></i>
									<span @click="gomain">
										首页
									</span>
								</template>
							</el-submenu>
						
							<el-submenu index="2">
								<template slot="title"><i class="iconfont icon-message-channel"></i>table</template>
								<el-menu-item-group>
									<el-menu-item index="/table">table</el-menu-item>
								</el-menu-item-group>
							</el-submenu>
						</el-menu>
					</el-scrollbar>
				</el-aside>
				<el-container>
					<!--使用element的自带的滚动条,官方文档没有-->
					<el-scrollbar style="height: 100%;width: 100%;">
					<el-main>
						 <keep-alive>
				            <!-- 这里是会被缓存的视图组件 -->
				            <!-- $route.meta.keepAlive:若是是true, 说明是缓存组件,经过keep-alive这个标签把缓存组件显示出来 -->
			              <router-view v-if="$route.meta.keepAlive">
			              </router-view>
			             </keep-alive>
			          <!-- 这里是不被缓存的视图组件 -->
			          <router-view v-if="!$route.meta.keepAlive">
			          </router-view>
					</el-main>
					</el-scrollbar>
				</el-container>
			</el-container>
		</el-container>
复制代码
export default {
		created() {

		},
		data() {
			return {

			}
		},
		methods: {
			gomain() {
			//编程式导航
				this.$router.push('/homeMain')
			},
          //退出功能
			layout() {
// 退出功能要移除localStorage中的myToken
				localStorage.removeItem('myToken')
// 跳转到首页
				this.$router.push('login')
// 退出成功提示
				this.$message.success('退出成功了')
			},
			
		},
	}
复制代码

首页

  • 代码有点多截取一点,主要对echarts作了修改,x轴箭头呀,修改柱状图的样式呀等,还有element的栅格布局配合媒体查询
xAxis: {
       data: ["三月", "四月", "五月", "六月", "七月"],
		axisLine: {
			symbol: ['none', 'arrow'],
			lineStyle: {
			color: 'rgba(212,212,212,1)', // x坐标轴的轴线颜色 
				width: 1 //这里是坐标轴的宽度,为0就是不显示 
				}
            		}
        	},
        	yAxis: [{

			type: 'value',
			axisLabel: {
	    		show: false //这行代码控制着坐标轴x轴的文字是否显示 
			},
			splitLine: {
				show: false, // 网格线是否显示 
				// 改变样式 
			lineStyle: {
				color: '#EDEDED' // 修改网格线颜色 
					}
			},
			axisLine: {
				lineStyle: {
				color: '#fff', // x坐标轴的轴线颜色 
				width: 0 //这里是坐标轴的宽度,为0就是不显示 
					}
				}
		}],
复制代码

表格的使用

<div class="table">
		<div class="t-top">
			<!--使用el-input 要注意,他默认占父级100%的宽度-->
			<el-input v-model="query" placeholder="请输入内容"></el-input>
			<!--el-button 绑定点击事件向后台发送数据查询-->
			<!--在此处一般会涉及到模糊查询,此时咱们还须要绑定keyup事件,向后台请求数据,而后渲染一个小的下拉框,咱们须要作的是发送查询的字段给后台, 后台使用sql语句模糊查询,咱们渲染就能够-->
			<el-button type="primary" @click="search">查询</el-button>
		</div>
		<div class="t-bottom">
			
			    <!-- el-table:表格组件 -->
			    <!-- :data='tableData' 表格显示的数据 -->
			    <!-- el-table-column:表格的一列 -->
			    <!-- prop: 当前列要显示的数据 ,tableData内的数据-->
			    <!-- label:表头 -->
			    <!-- width: 这一列的宽度 -->
			    <!--min-width:用来设置百分比-->
			     <!--:header-cell-style="{background:'red'}"-->
		        <!--align="center"表格内的数据居中-->
			     
			 <el-table :data="tableData" style="width: 100%" :header-cell-style="{background:'red'}" >
		      <el-table-column prop="date" label="日期" align="center" width="180">
		      </el-table-column>
		      <el-table-column prop="name" label="姓名" align="center" width="180">
		      </el-table-column>
		      <!--若是不设置百分比,就自动分配剩余的宽度-->
		      <el-table-column prop="address" align="center" label="地址">
		      </el-table-column>
		    </el-table>
		</div>
	</div>
复制代码
export default {
	  data() {
	    return {
// 绑定的input 查询关键字
	      query: '',
// 须要一个数组用来存放table的数据
// 这是element组件里面的,
	        tableData: []
	    }
	  },
	  mounted() {
// 在vue的生命周期的mounted中调用渲染列表
	  	this.initTable()
	  },
	  methods:{
	  	initTable() {
	  		this.axios('/api/table').then( res => {
	  			console.log(res.data)//查看接口返回时什么样的数据,要经常使用
	  			this.tableData = res.data //接口返回的是一个数组,直接能够赋值给table
	  		})
	  	},
	  	search() {
	  		
	  	}
	  }
	}
复制代码

改element-ui的样式注意!

<!--使用scoped须要注意,使用的它以后,你就没法更改elelment组件中的样式-->
<style lang="less" scoped="scoped"> /*若是不想使用scoped,你就用父级的class把样式所有包裹起来,就不会相互影响页面的样式了*/ 复制代码

如下是一些概念性的东西,其余的功能系列二将会陆续完善

编程式导航

  • 就是经过 JS 代码来实现路由的跳转功能
// 注意:是 router 不是 route
// router用来实现路由跳转,route用来获取路由参数
// push 方法的参数为:要跳转到的路由地址(path)
this.$router.push('/home')
复制代码

密码

  • 给输入框组件添加 type="password" 就变为密码框状态了
<el-input type="password" v-model="loginForm.password"></el-input>
复制代码

登陆拦截

  • 说明:在没有登陆的状况不该该让用户来访问除登陆之外的任何页面

登陆和拦截的整个流程说明

  • 1 在登陆成功之后,将 token 存储到 localStorage 中
  • 2 在 导航守卫 中先判断当前访问的页面是否是登陆页面
  • 3 若是是登陆页面,直接放行(next())
  • 4 若是不是登陆页面,就从 localStorage 中获取 token,判断有没有登陆
  • 5 若是登陆了,直接放行(next())
  • 6 若是没有登陆,就跳转到登陆页面让用户登陆(next('/login'))

token 机制的说明

  • 在项目中,若是登陆成功了,那么,服务器会给咱们返回一个 token
  • 这个 token 就是登陆成功的标识
  • 这个 token 就至关于使用 cookie+session 机制中的 sessionid

公司人员和项目开发流程

  • 1 产品经理定制项目的需求
  • 2 分配任务:先将全部的任务分配到项目组,而后,再由项目组具体分配给每一个开发人员
  • 3 开发:拿到 产品原型 + 需求文档 + UI 设计稿 资料,转化为 HTML 页面,完成功能
  • 4 功能完成后,本身测试有没有 Bug
  • 5 由测试人员来测试你的功能,当测试出 Bug 后,就会经过 禅道 这样的项目管理系统,来提出 Bug
  • 6 由 本身 修改 测试人员提出来的 bug
  • 7 最终,没有 bug 了,项目才会上线
产品经理(Product Manager)
  提需求
  产出: 产品原型 + 需求文档
  原型设计软件:Axure 、墨刀

UI(设计)
  将 产品经理 给的 原型图 设计为 好看的UI稿

FE(前端)front-end
  产品原型 + 需求文档 + UI设计稿 ===> HTML页面

BE(后端) back-end
  给前端提供数据接口

测试人员
  产品原型 + 需求文档 + UI设计稿 来测试咱们写的功能
  发现你的功能 与 需求 不一致,那就说明除Bug了,那么,测试人员就会提Bug
  Bug系统: 禅道

项目经理(管理技术)
  技术攻坚,与其余项目组人员沟通,分配任务 等
复制代码

vue 单文件组件中的 scoped

  • 做用:给 style 标签添加 scoped 属性之后,样式只会对当前组件中的结构生效,而不会影响到其余组件

vue 单文件组件中的 lang

  • 做用:添加 lang="less" 后,就可使用 less 语法了
  • 可是须要本身安装:npm i -D less less-loader

VSCode 中使用 Vetur 插件格式化单文件组件的 template

  • 打开设置,配置:"vetur.format.defaultFormatter.html": "js-beautify-html"

接口调用的说明

  • 注意:全部接口都须要传递 token,只有传递了正确的 token,服务器才会将数据返回给前端
  • 若是没有传递token,服务器会返回 401 ,告诉接口调用者,没有权限来访问这个接口

cookie+session VS token

Git 使用

# 克隆仓库
git clone [仓库地址]

# 推送
git push [仓库地址] master

# 简化推送地址
git remote add XX [仓库地址]
git push -u XX master
# 第一次执行上面两条命令,之后只须要输入如下命令便可
git push XX

# 拉取
git pull [仓库地址] master
git pull XX master
复制代码

路由参数分页

  • 1 配置分页路由参数, 参数是可选的
    • 参数可选后, 路由就可以匹配: /XX 或者 /XX/3
  • 2 使用路由来分页, 有两种状况须要处理:
  • 3 第一种: 进入页面,就要根据当前路由参数中的页码,来获取到对应页的数据
  • 4 第二种: 点击分页组件获取数据, 须要作两件事:
    • 4.1 获取到当前页的数据( 调用获取数据的方法 )
    • 4.2 修改哈希值为当前页码 ( this.$router.push() )
  • 5 点击分页按钮获取数据的第二种思路:
    • 5.1 点击分页按钮, 触发了分组件的 pageChange 事件
    • 5.2 在 pageChange 事件中修改了路由( this.$router.push() )
    • 5.3 路由发生改变后, watch 中的 $route 监视到了路由的改变
    • 5.4 在 $route(to) {} 方法中, 经过参数 to 获取到当前页码, 从新调用获取数据的方法来获取当前页的数据

项目打包和优化

  • 打包命令:npm run build

按需加载

  • 1 修改 router/index.js 中导入组件的语法
// 使用:
const Home = () => import('@/components/home/Home')
// 替换:
// import Home from '@/components/home/Home'

// 给打包生产的JS文件起名字
const Home = () => import(/* webpackChunkName: 'home' */ '@/components/home/Home')

// chunkName相同,将 goods 和 goods-add 两个组件,打包到一块儿
const XX = () => import(/* webpackChunkName: 'XX' */'@/components/XX')
const XXX = () => import(/* webpackChunkName: 'XX' */'@/components/XXX')
复制代码
  • 2 (该步可省略)修改 /build/webpack.prod.conf.js 中的chunkFilename
{
  // [name] 代替 [id]
  chunkFilename: utils.assetsPath('js/[name].[chunkhash].js')
}
复制代码

使用CDN

  • 开源项目 CDN 加速服务css

  • 1 在 index.html 中引入CDN提供的JS文件html

  • 2 在 /build/webpack.base.conf.js 中(resolve前面)添加配置 externals前端

  • 注意:经过CDN引入 element-ui 的样式文件后,就不须要在 main.js 中导入 element-ui 的CSS文件了。因此,直接注释掉 main.js 中的导入 element-ui 样式便可vue

  • externals配置:java

externals: {
  // 键:表示 导入包语法 from 后面跟着的名称
  // 值:表示 script 引入JS文件时,在全局环境中的变量名称
  vue: 'Vue',
  axios: 'axios',
  'vue-router': 'VueRouter',
  'element-ui': 'ELEMENT',
  moment: 'moment',
  echarts: 'echarts',
}

import ElementUI from 'element-ui'
复制代码

经常使用包CDN

<!-- Include the Quill library -->
<script src="https://cdn.bootcss.com/quill/1.3.4/quill.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/vue"></script>
<!-- Quill JS Vue -->
<script src="https://cdn.jsdelivr.net/npm/vue-quill-editor@3.0.4/dist/vue-quill-editor.js"></script>
<!-- Include stylesheet -->
<link href="https://cdn.bootcss.com/quill/1.3.4/quill.core.min.css" rel="stylesheet">
<link href="https://cdn.bootcss.com/quill/1.3.4/quill.snow.min.css" rel="stylesheet">
<link href="https://cdn.bootcss.com/quill/1.3.4/quill.bubble.min.css" rel="stylesheet">
复制代码

移除console

new webpack.optimize.UglifyJsPlugin({
  compress:{
    warnings: false,
    drop_debugger: true,
    drop_console: true
  }
})
复制代码

缓存和保留组件状态

  • keep-alive
  • 解决方式:使用 keep-alive ,步骤以下:
1 在须要被缓存组件的路由中添加 meta 属性
  meta 属性用来给路由添加一些元信息(其实,就是一些附加信息)
{
  path: '/',
  name: 'home',
  component: Home,
  // 须要被缓存
  meta: {
    keepAlive: true
  }
}

2 修改路由出口,替换为如下形式:
  根据 meta 是否有 keepAlive 属性,决定该路由是否被缓存
<keep-alive>
  <!-- 这里是会被缓存的视图组件 -->
  <router-view v-if="$route.meta.keepAlive">
  </router-view>
</keep-alive>

<!-- 这里是不被缓存的视图组件 -->
<router-view v-if="!$route.meta.keepAlive">
</router-view>
复制代码

启用路由的 History 模式

  • 经过在路由中添加 mode: 'history' 能够去掉 浏览器地址栏中的 #
  • 在开发期间,只须要添加这个配置便可
  • 可是,在项目打包之后,就会出现问题
// 去掉 # 后,地址变为:

http://localhost:1111/home

那么,服务器须要正确处理 /goods 才能正确的响应内容,
可是,/home 不是服务端的接口,而是 用来在浏览器中实现 VueRouter 路由功能的
复制代码

后端的处理方式

  • 1 优先处理静态资源
  • 2 对于非静态资源的请求,所有统一处理返回 index.html
  • 3 当浏览器打开 index.html 就会加载 路由的js 文件,那么路由就会解析 URL 中的 /login 这种去掉#的路径了

待续中

[项目地址 github.com/whylisa/vue…)

相关文章
相关标签/搜索