vue项目实战(pc端)
相关资料(一) 下载和运行项目(1) pc端:(2) 服务器端(二) 路由守卫和用户权限管理(重点难点)(0) 准备工作和注意事项(1) 路由守卫(2) 用户权限控制(3) 动态渲染侧边栏(三) 导出表格(四) 几个小知识(1) 复制文本(2) 国际化(3) 隐藏模块(4) 路由模块高亮(5) 表格序号(6) 监听路由变化项目实践代码(一) 测量模块相关资料#饿了么UI库:Element - Th
·
相关资料#
- 饿了么UI库: Element - The world's most popular Vue UI framework
- 项目预览地址: http://nongye.huruqing.cn
- 项目demo地址:
git@gitee.com:huruqing/nongye-vue-w1206.git
- 生产接口地址: http://huruqing.cn:3007
- 上课代码地址:
git@gitee.com:huruqing/nongye-admin-w1206.git
(一) 下载和运行项目#
(1) pc端:#
- 下载项目
git clone git@gitee.com:huruqing/nongye-admin-template.git
npm i
安装依赖npm run serve
运行项目
(2) 服务器端#
01 开发环境#
-
下载项目
git clone git@gitee.com:huruqing/nongye-server-template.git
-
进入项目
-
npm i 安装依赖
-
npm run dev 运行项目
-
数据库
- 全局安装 json-server
npm i json-server@0.17.0 -g
- 进入/nongye-server-template/db, 执行 npm i
- 启动数据库 进入/nongye-server-template, 执行
npm run json
- 全局安装 json-server
02 生产环境#
-
接口地址:
http://106.55.50.108:3007
-
配置数据库地址
- /src/utils/request.js
- 端口号从7001~7040
import axios from "axios"; import { Message, Loading } from "element-ui"; import store from "../store"; // 判断环境 let isDev = process.env.NODE_ENV === "development"; let baseURL; if (!isDev) { baseURL = "http://localhost:3007"; } else { baseURL = "http://106.55.50.108:3007"; } const service = axios.create({ baseURL, timeout: 30000, // 请求超时时间(因为需要调试后台,所以设置得比较大) }); // request拦截器 service.interceptors.request.use( (config) => { let port = 端口号; // 7001~7040 config.data = { ...config.data, port, }; config.params = { ...config.params, port, }; ....... }
(二) 路由守卫和用户权限管理(重点难点)#
(0) 准备工作和注意事项#
-
修改路由配置
-
添加登录路由和组件
-
登录成功保存用户信息
-
在layout组件显示用户名和添加退出登录
注意: 把vuex持久化先注释
(1) 路由守卫#
vue-router的路由守卫和axios拦截器有着类似的作用
- from 当前路由
- to 要前往的目标路由
- next 执行下一步操作
- next() 进入到目标路由(相当于放行)
- next({ path: '/login' }) 跳转到/login路由
import Vue from "vue";
import Router from "vue-router";
import Layout from "@/views/layout/layout";
import store from '@/store/index';
Vue.use(Router);
const initRoutes = [
{
path: "/",
redirect: "/login",
},
{
path: "/login",
name: "login",
component: () => import("../views/login/login.vue"),
},
{
path: "/about",
name: "about",
component: () => import("../views/about/about.vue"),
},
];
export const routes = [
{
path: "/home",
name: "home",
meta: {
title: "首页",
icon: "location-o",
},
component: Layout,
redirect: "/home/index",
children: [
{
path: "index", // /home/index
name: "home-inex",
component: () => import("../views/home/home.vue"),
},
{
path: "list", // /home/list
name: "home-list",
component: () => import("../views/home/list.vue"),
},
],
},
{
path: "/type",
name: "type",
meta: {
title: "分类",
icon: "like-o",
},
component: Layout,
redirect: "/type/index",
children: [
{
path: "index", // /type/index
name: "type-inex",
component: () => import("../views/type/type.vue"),
},
],
},
{
path: "/cart",
name: "cart",
meta: {
title: "购物车",
icon: "star-o",
},
component: Layout,
redirect: "/cart/index",
children: [
{
path: "index", // /cart/index
name: "cart-inex",
component: () => import("../views/cart/cart.vue"),
},
],
},
];
const router = new Router({
routes: [
...initRoutes,
...routes,
]
});
/**
* to 要去的路由
* from 当前路由
* next 执行下一步操作 next(), next('/login')
*/
/**
* 判断逻辑:
* 1. 判断是否应登录
* 2. 判断要去哪个路由
* 3. 设置一个白名单, 白名单上面的路由直接放行, 比如login
*/
let whiteList = ['login','about'];
router.beforeEach((to,from,next)=>{
let token = store.state.token;
// token存在表示已经登录
if (token) {
// 已登录, 所去路由为login时,直接跳首页
if(to.name === 'login') {
next('/home')
} else {
next();
}
} else {
/**
* 没有登录时的逻辑
* 白名单内的路由,直接放行
* 其它路由跳转到登录页面
*/
if (whiteList.includes(to.name)) {
next();
} else {
next('/login');
}
}
});
export default router;
(2) 用户权限控制#
用户权限控制的思路是:
- 前端一开始的路由只配置了一些基本的路由(无需登录的路由)
- 用户登录之后, 后台会给前端返回一个角色字段(比如type), 表明用户的身份
- 前端就根据用户的身份(角色字段)配置不同的路由(有的公司由后台返回)
- 前端使用router.addRoutes方法动态添加权限路由。
- 在后台管理系统的侧边栏一般根据路由数组动态渲染,这样不同角色能看到的列表就不一样。
实践: 在各个代码的关键节点打上断点, 查看整个流程
(3) 动态渲染侧边栏#
- 让侧边栏组件(layout)作为所有需要侧边栏的父路由组件(父路由有什么内容, 子路由就有什么内容)
- 刚开始创建路由的时候, 只创建无需登录就能访问的路由
- 根据设置权限设置多个路由数组(routes)
- 登录成功的时候添加加权限动态添加相应的路由数组, 并把路由数组存入vuex的store(仓库)
- 渲染侧边栏的时候, 把路由数组(routes)从store取出, 使用v-for进行动态渲染
(三) 导出表格#
- 安装插件
vue-json-excel
- 到时并使用(main.js)
import JsonExcel from 'vue-json-excel'
Vue.component('downloadExcel', JsonExcel)
- demo
<template>
<div>
<download-excel
:data="json_data"
:fields="json_fields"
type="xlsx"
worksheet="My Worksheet"
name="我的表格.xlsx"
>
<el-button type="primary" size="mini">导出数据 </el-button>
</download-excel>
<el-table :data="json_data">
<el-table-column label="编号" prop="id"></el-table-column>
<el-table-column label="姓名" prop="username"></el-table-column>
<el-table-column label="年龄" prop="age"></el-table-column>
<el-table-column label="备注" prop="desc"></el-table-column>
</el-table>
</div>
</template>
<script>
export default {
data() {
return {
// 表头
json_fields: {
编号: "id",
姓名: "username",
年龄: "age",
备注: "desc",
},
// 表格内容
json_data: [
{
id: "234",
username: "aaa",
age: "11",
desc: "xxxx",
},
{
id: "112",
username: "bbb",
age: "12",
desc: "xxxx",
},
],
};
},
};
</script>
(四) 几个小知识#
(1) 复制文本#
- 安装插件
vue-clipboard2
- 导入并使用插件
// main.js
import VueClipboard from 'vue-clipboard2'
Vue.use(VueClipboard);
- demo
<template>
<div>
<p>
<span>{{ msg }}</span
><button v-clipboard:copy="msg" v-clipboard:success="onCopy">复制</button>
</p>
<p>
<span>{{ msg2 }}</span
><button v-clipboard:copy="msg2" v-clipboard:success="onCopy">复制</button>
</p>
</div>
</template>
<script>
export default {
data() {
return {
msg: "哈哈哈哈哈哈哈哈哈哈",
msg2: "嘿嘿嘿嘿嘿嘿",
};
},
methods: {
onCopy() {
alert("复制成功");
},
},
};
</script>
<style>
</style>
(2) 国际化#
- 安装插件
vue-i18n
- 导入和配置插件
- this.$i18n.locale 可以修改语言
// 配置语言包, /src/lang目录下新建en.js和zh.js
// en.js
export const lang = {
account: 'account',
password: 'password',
}
// zh.js
export const lang = {
account: '账号',
password: '密码',
}
// main.js
import VueI18n from "vue-i18n/dist/vue-i18n.esm.js";
Vue.use(VueI18n); // 通过插件的形式挂载
const i18n = new VueI18n({
locale: store.state.lang, // 语言标识
// this.$i18n.locale // 通过切换locale的值来实现语言切换
messages: {
"zh": require("./lang/zh"), // 中文语言包
"en": require("./lang/en"), // 英文语言包
},
});
// 使用
<template>
<div>
<p>{{ $t("lang.account") }}: zhangsan</p>
<p>{{ $t("lang.password") }}: 123456</p>
<button @click="handClick">切换语言</button>
</div>
</template>
<script>
export default {
methods: {
handClick() {
if (this.$i18n.locale === "en") {
this.$i18n.locale = "zh";
} else {
this.$i18n.locale = "en";
}
},
},
};
</script>
(3) 隐藏模块#
{
path: "developkit",
hidden: true, // 隐藏
meta: { title: "开发套件" },
name: "device-developkit",
component: () => import("@/views/device/developKit.vue"),
},
(4) 路由模块高亮#
详情请看饿了么UI库的 el-menu
<el-menu
:uniqueOpened="true" // 只打卡一个模块
:default-active="activeRoute" // 路由高亮
class="el-menu-sidebar-menu"
background-color="#0d2439"
text-color="#fff"
active-text-color="#69B3FF"
:collapse="isCollapse"
:router="true"
>
(5) 表格序号#
<el-table-column align="center" type="index" label="序号" width="100"></el-table-column>
(6) 监听路由变化#
watch: {
$route(newRoute) {
console.log(newRoute);
}
}
项目实践代码#
(一) 测量模块#
(1) 新建组件 measure
(2) 配置路由
{
path: '/measure',
name: 'measure',
component: Layout,
meta: {
title: '测量',
icon: "icon-fyxx"
},
redirect: '/measure/measure',
children:[
{
path:'measure',
name: 'measure-measure',
component: () => import("@/views/measure/measure.vue"),
}
]
}
(3) 渲染列表
- 表格 stripe添加斑马纹, border添加边框
- 单元格 align="center" 内容居中
- 添加操作按钮
(4) 获取数据, 渲染列表
-
统一管理请求 api/index.js里封装请求方法
export const $measurementList = (params={})=> { return $axios.get('/measurement/list',{params}); }
-
使用方法
// 导入方法 import {$measurementList} from '@/api/index'; // 使用 getList() { $measurementList().then(res=> { this.list = res.data; }) }
更多推荐
已为社区贡献3条内容
所有评论(0)