网站主要完成:侧边菜单栏、页面标签卡、内容栏
源代码gitee地址:https://gitee.com/zhao_liangliang1997/navigation-bar
一、起步
1、创建vue项目
vue create 项目名
2、引入element
3、其他安装
1、首先需要安装如下
cnpm install vuex
cnpm install vue-router
cnpm install sass
cnpm install sass-loader
cnpm install node -sass
2、main.js中引入相关
引入后,可能会报错,请别急,继续往下走。
import Vue from 'vue'
import App from './App.vue'
import store from './store'
import router from './router'
import ElementUI from 'element-ui';
import 'element-ui/lib/theme-chalk/index.css';
// 引入基础样式[下面给链接复制style.scss以及variables.scss]
import './assets/scss/style.scss';
Vue.config.productionTip = false
Vue.use(ElementUI);
new Vue({
router,
store,
render: h => h(App)
}).$mount('#app')
3、改造App.vue
<template>
<div id="app">
<router-view/>
</div>
</template>
<script>
export default {
name: 'App',
}
</script>
<style lang="scss">
#app {
height: 100vh;
}
</style>
完成侧边栏的项目结构,如下图:
相关链接
1、style.scss;
2、variables.scss
4、配置路由[router下的index.js]
配置如下路由后,下一步您需要对layout进行页面设计【第一步侧边菜单栏】
import Vue from 'vue'
import VueRouter from 'vue-router'
Vue.use(VueRouter)
const router = new VueRouter({
routes:[
{
path: '/',
hidden: true,
component: () =>
import ('@/page/layout'),
children: [
{
path: 'index',
component: () =>
import ('@/page/index'),
hidden: true
}
]
},
]
})
export default router
二、侧边菜单栏的设计
1、封装菜单组件navMenu.vue
<template>
<div>
<template v-for="(item, index) in userNav">
<el-menu-item :index="item.path" v-if="!item.hidden && !item.children">
{{ item.name }}
</el-menu-item>
<el-submenu :index="item.path" v-if="!item.hidden && item.children">
<template slot="title">{{ item.name }}</template>
<nav-menu :user-nav="item.children"/>
</el-submenu>
</template>
</div>
</template>
<script>
export default {
name: "navMenu",
props: {
userNav: {
type: Array,
default: []
}
}
}
</script>
2、layout中实现侧边栏
思路: ①首先画出侧边栏;②路由信息存放vuex中;③vuex中的路由从路由js中获取
<template>
<el-container>
<el-aside width="20vh" class="aside">
<div class="logo_box pr">
<span class="fl w_100 tc f20 text-white w_h_center pl20 pr20">测试服务平台</span>
</div>
<el-menu :default-active="activeIndex"
class="el-menu-vertical-demo"
style="flex: 1; overflow: auto; width: 100%; overflow-x: hidden"
background-color="#6187F7"
text-color="#fff"
active-text-color="#ffd04b"
unique-opened
@select="handleSelect">
<template v-for="(item, index) in userNav">
<el-menu-item :key="index" :index="item.path" v-if="!item.hidden && !item.children">
{{ item.name }}
</el-menu-item>
<el-submenu :key="index" :index="item.path" v-if="!item.hidden && item.children">
<template slot="title">{{ item.name }}</template>
<nav-menu :user-nav="item.children"/>
</el-submenu>
</template>
</el-menu>
</el-aside>
<el-container>
<el-header>Header</el-header>
<el-main>
<router-view/>
</el-main>
</el-container>
</el-container>
</template>
<script>
import NavMenu from '@/page/navMenu/navMenu'
import {mapState, mapMutations} from 'vuex'
export default {
name: "VueLayout",
components: {
NavMenu
},
data() {
return {
url: '',
activeIndex:'/'
}
},
created() {
// 获取菜单权限 [因此刻未配动态路由,所以在此处调用]
this.setMenu()
},
computed: {
...mapState(['userNav'])
},
methods: {
...mapMutations(['setMenu']),
handleSelect: function (key) {
let path = this.$route.path
if (path !== key) {
if (key === '/' && path === '/index') {
return
}
this.$router.push(key)
}
},
}
}
</script>
<style less scoped>
/deep/ .el-tabs__header {
margin: 0;
}
.aside {
background-color: #6187F7;
display: flex;
flex-direction: column;
}
.logo_box {
height: 60px;
border-bottom: 1px solid white;
}
</style>
3、vuex
//1.引入Vue
import Vue from 'vue';
import Vuex from 'vuex';
import view from '@/router/baseView';
import router from '@/router/index'
import dynamicView from "@/router/dynamicView";
//2.安装
Vue.use(Vuex);
const store = new Vuex.Store({
//存储状态
state:{
userNav: [], // 导航栏路由, 默认未登录,展示静态路由
activeIndex: '/',
tagMap: new Map(),
},
// Vuex中的Store状态(state)更新的唯一方式:提交Mutation
mutations:{//定义mutations
// 定义改变全局共享数据的方法
setMenu(state) {
let baseView = Object.assign([], view) // 初始化导航栏
// 根据菜单权限获取菜单
let nav = getNav(dynamicView)
nav.forEach(item => {
baseView.push(item)
})
state.userNav = baseView
},
}
})
//导出
export default store
function getNav(navs) {
let list = []
navs.forEach(nav => {
let obj = {}
obj.path = nav.path
obj.name = nav.name
obj.icon = nav.icon
obj.isPage = nav.isPage
if (nav.isPage) {
obj.component = () => import ('@/views' + nav.path)
}
if (nav.children) {
obj.children = getNav(nav.children)
}
list.push(obj)
})
return list
}
三、页面标签卡
1、头部、内容栏及页面标签卡
页面标签卡:标签卡为外部引入组件【代码请到Gitee查看】
2、注意事项:
1、tag改变方法【activeIndex从vuex引入】
2、tag标签页根据路由创建【navClick从vuex引入】
3、最终效果
4、后续相关token
1.客户端使用用户名跟密码请求登录
2.服务端收到请求,去验证用户名与密码
3.验证成功后,服务端会签发一个 token 并把这个 token 发送给客户端
4.客户端收到 token 以后,会把它存储起来,比如放在 cookie 里或者 localStorage 里
5.客户端每次向服务端请求资源的时候需要带着服务端签发的 token
6.服务端收到请求,然后去验证客户端请求里面带着的 token ,如果验证成功,就向客户端返回请求的数据
-
每一次请求都需要携带 token,需要把 token 放到 HTTP 的 Header 里
-
基于 token 的用户认证是一种服务端无状态的认证方式,服务端不用存放 token 数据。用解析 token 的计算时间换取 session 的存储空间,从而减轻服务器的压力,减少频繁的查询数据库
-
token 完全由应用管理,所以它可以避开同源策略
-
什么是同源策略?
同源策略是客户端脚本(尤其是 Javascript)的重要的安全度量标准。其目的是防止某个文档或脚本从多个不同源装载。 这里的同源策略指的是:协议,域名,端口相同,同源策略是一种安全协议,指一段脚本只能读取来自同一来源的窗口和文档的属性。 -
为什么要有同源限制?
我们举例说明:比如一个黑客程序,他利用 Iframe 把真正的银行登录页面嵌到他的页面上,当你使用真实的用户名,密码登录时,他的页面就可以通过 Javascript 读取到你的表单中 input 中的内容,这样用户名,密码就轻松到手了
5、permission.js
在登陆这个流程中,permission.js这个是很最重要的一环,是路由的全局钩子(beforeEach和afterEach),全局钩子就是每次跳转的时候可以根据情况进行拦截,不让它进行跳转。使用场景最常见的就是有些页面需要用户登陆之后才能访问,就可以在beforeEach中校验用户是否登陆来进行相对应的拦截处理。
6、相关学习博客推荐:
vue-element-admin 登陆