vue后台_实战篇
一、一些常用组件效果的实现
1)面包屑导航
主要是使用$route.mathed:一个数组,包含当前路由的所有嵌套路径片段的路由记录 。路由记录就是 routes
配置数组中的对象副本 (还有在 children
数组)。
类似的有一个router.getMatchedComponents(location?):返回目标位置或是当前路由匹配的组件数组(是数组的定义/构造类,不是实例)。通常在服务端渲染的数据预加载时时候。
(还记的vue-router中router,route,routes的区别么?)
1)router:是指一个vue-router的实例
2)route:路由信息对象,表示当前激活的路由的状态信息,可以出现
在组件内,即
this.$route
在
$route
观察者回调内router.match(location)
的返回值导航守卫的参数:
router.beforeEach((to, from, next) => {
// `to` 和 `from` 都是路由对象
})
scrollBehavior
方法的参数:const router = new VueRouter({
scrollBehavior (to, from, savedPosition) {
// `to` 和 `from` 都是路由对象
}
})
3)routes:router的构造配置项
routes
类型:
Array<RouteConfig>
RouteConfig
的类型定义:declare type RouteConfig = {
path: string;
component?: Component;
name?: string; // 命名路由
components?: { [name: string]: Component }; // 命名视图组件
redirect?: string | Location | Function;
props?: boolean | string | Function;
alias?: string | Array<string>;
children?: Array<RouteConfig>; // 嵌套路由
beforeEnter?: (to: Route, from: Route, next: Function) => void;
meta?: any; // 2.6.0+
caseSensitive?: boolean; // 匹配规则是否大小写敏感?(默认值:false)
pathToRegexpOptions?: Object; // 编译正则的选项
}
<template>
<el-breadcrumb class="app-levelbar" separator="/">
<el-breadcrumb-item v-for="(item,index) in levelList" :key="item.path">
<router-link v-if='item.redirect==="noredirect"||index==levelList.length-1' to="" class="no-redirect">{{item.name}}</router-link>
<router-link v-else :to="item.redirect||item.path">{{item.name}}</router-link>
</el-breadcrumb-item>
</el-breadcrumb>
</template> <script>
export default {
created() {
this.getBreadcrumb()
},
data() {
return {
levelList: null
}
},
methods: {
getBreadcrumb() {
// console.log('this.$route.matched', this.$route.matched);
let matched = this.$route.matched.filter(item => item.name);
const first = matched[];
if (first && (first.name !== '首页' || first.path !== '')) {
matched = [{
name: '首页',
path: '/'
}].concat(matched)
}
this.levelList = matched;
}
},
watch: {
$route() {
this.getBreadcrumb();
}
}
}
breadbar
2)历史访问记录TabView
使用vuex记录app全局的一些状态参数,诸如导航栏是否收起,浏览路径等等
import Cookies from 'js-cookie'; const app = {
state: {
sidebar: {
opened: !+Cookies.get('sidebarStatus')
},
theme: 'default',
livenewsChannels: Cookies.get('livenewsChannels') || '[]',
visitedViews: []
},
mutations: {
TOGGLE_SIDEBAR: state => {
if (state.sidebar.opened) {
Cookies.set('sidebarStatus', );
} else {
Cookies.set('sidebarStatus', );
}
state.sidebar.opened = !state.sidebar.opened;
},
ADD_VISITED_VIEWS: (state, view) => {
if (state.visitedViews.some(v => v.path === view.path)) return
state.visitedViews.push({ name: view.name, path: view.path })
},
DEL_VISITED_VIEWS: (state, view) => {
let index
for (const [i, v] of state.visitedViews.entries()) {
if (v.path === view.path) {
index = i
break
}
}
state.visitedViews.splice(index, )
}
},
actions: {
ToggleSideBar: ({ commit }) => {
commit('TOGGLE_SIDEBAR')
},
addVisitedViews: ({ commit }, view) => {
commit('ADD_VISITED_VIEWS', view)
},
delVisitedViews: ({ commit }, view) => {
commit('DEL_VISITED_VIEWS', view)
}
}
}; export default app;
store/modules/app.js
如上所示,通过visitedViews这个state记录浏览历史记录,需要的时候遍历这个数组即可,watch $route 每一次路由更改时,向数组中压入一条记录
<template>
<div class='tabs-view-container'>
<router-link class="tabs-view" v-for="tag in Array.from(visitedViews)" :to="tag.path" :key="tag.path">
<el-tag :closable="true" :type="isActive(tag.path)?'primary':''" @close='closeViewTabs(tag,$event)'>
{{tag.name}}
</el-tag>
</router-link>
</div>
</template> <script>
export default {
computed: {
visitedViews() {
return this.$store.state.app.visitedViews.slice(-)
}
},
methods: {
closeViewTabs(view, $event) {
this.$store.dispatch('delVisitedViews', view)
$event.preventDefault()
},
generateRoute() {
if (this.$route.matched[this.$route.matched.length - ].name) {
return this.$route.matched[this.$route.matched.length - ]
}
this.$route.matched[].path = '/'
return this.$route.matched[]
},
addViewTabs() {
this.$store.dispatch('addVisitedViews', this.generateRoute())
},
isActive(path) {
return path === this.$route.path
}
},
watch: {
$route() {
this.addViewTabs()
}
}
}
</script> <style rel="stylesheet/scss" lang="scss" scoped>
.tabs-view-container {
display: inline-block;
vertical-align: top;
margin-left: 10px;
.tabs-view {
margin-left: 10px;
}
}
</style>
历史浏览路径组件tabViews实现
3)全屏显示
hmtl5有相关的screenfull的API,只不过兼容性并不好。可以借助第三方库,如https://github.com/sindresorhus/screenfull.js,使用起来其实很简单
<template>
<svg @click='click' class="icon screenfull" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"
t="" viewBox="0 0 1024 1024" version="1.1" p-id="" :fill='fill' :width="width" :height="height">
<path d="M604.157933 512l204.484208 204.484208 82.942037-82.942037c10.364045-10.952446 26.498514-13.83817 40.309054-8.067746 13.249769 5.742794 22.465664 18.99154 22.465664 33.977859l0 258.042008c0 20.168342-16.695241 36.863582-36.863582 36.863582L659.452283 954.357873c-14.986319 0-28.236088-9.215896-33.977859-23.025413-5.770424-13.249769-2.885723-29.384237 8.067746-39.748283l82.942037-82.942037L512 604.157933 307.515792 808.642141l82.942037 82.942037c10.952446 10.364045 13.83817 26.498514 8.067746 39.748283-5.742794 13.809517-18.99154 23.025413-33.977859 23.025413L106.504686 954.357873c-20.168342 0-36.863582-16.695241-36.863582-36.863582L69.641103 659.452283c0-14.986319 9.215896-28.236088 23.025413-33.977859 13.249769-5.770424 29.384237-2.8847 39.748283 8.067746l82.942037 82.942037 204.484208-204.484208L215.357859 307.515792l-82.942037 82.942037c-6.890944 6.918573-16.10684 10.952446-25.911136 10.952446-4.593622 0-9.804297-1.14815-13.83817-2.8847-13.809517-5.742794-23.025413-18.99154-23.025413-33.977859L69.641103 106.504686c0-20.168342 16.695241-36.863582 36.863582-36.863582L364.546693 69.641103c14.986319 0 28.236088 9.215896 33.977859 23.025413 5.770424 13.249769 2.8847 29.384237-8.067746 39.748283l-82.942037 82.942037 204.484208 204.484208L716.484208 215.357859l-82.942037-82.942037c-10.952446-10.364045-13.83817-26.498514-8.067746-39.748283 5.742794-13.809517 18.99154-23.025413 33.977859-23.025413l258.042008 0c20.168342 0 36.863582 16.695241 36.863582 36.863582l0 258.042008c0 14.986319-9.215896 28.236088-22.465664 33.977859-4.593622 1.736551-9.804297 2.8847-14.397918 2.8847-9.804297 0-19.020192-4.033873-25.911136-10.952446l-82.942037-82.942037L604.157933 512z"
p-id="" />
</svg>
</template> <script>
import screenfull from 'screenfull';
export default {
name: 'hamburger',
props: {
width: {
type: Number,
default:
},
height: {
type: Number,
default:
},
fill: {
type: String,
default: '#48576a'
}
},
data() {
return {
isFullscreen: false
}
},
methods: {
click() {
if (!screenfull.enabled) {
this.$message({
message: 'you browser can not work',
type: 'warning'
});
return false;
}
screenfull.toggle();
}
}
}
</script> <style scoped>
.screenfull {
display: inline-block;
cursor: pointer;
vertical-align: -.15em;
}
</style>
screenFull组件实现
二、一些常用的第三方库
1)富文本编辑器:tinyMCE
2)markdown编辑器:simplemde-markdown-editor,markdown的转换使用了shutdown
3)json编辑器(代码编辑器): CodeMirror
4)列表拖拽:vue.draggalbe(基于sortable)
三、一些常用的文本过滤方法(包括时间格式化方法等)
function pluralize(time, label) {
if (time === ) {
return time + label
}
return time + label + 's'
}
export function timeAgo(time) {
const between = Date.now() / - Number(time);
if (between < ) {
return pluralize(~~(between / ), ' minute')
} else if (between < ) {
return pluralize(~~(between / ), ' hour')
} else {
return pluralize(~~(between / ), ' day')
}
} export function parseTime(time, cFormat) {
if (arguments.length === ) {
return null;
} if ((time + '').length === ) {
time = +time *
} const format = cFormat || '{y}-{m}-{d} {h}:{i}:{s}';
let date;
if (typeof time == 'object') {
date = time;
} else {
date = new Date(parseInt(time));
}
const formatObj = {
y: date.getFullYear(),
m: date.getMonth() + ,
d: date.getDate(),
h: date.getHours(),
i: date.getMinutes(),
s: date.getSeconds(),
a: date.getDay()
};
const time_str = format.replace(/{(y|m|d|h|i|s|a)+}/g, (result, key) => {
let value = formatObj[key];
if (key === 'a') return ['一', '二', '三', '四', '五', '六', '日'][value - ];
if (result.length > && value < ) {
value = '' + value;
}
return value || ;
});
return time_str;
} export function formatTime(time, option) {
time = +time * ;
const d = new Date(time);
const now = Date.now(); const diff = (now - d) / ; if (diff < ) {
return '刚刚'
} else if (diff < ) { // less 1 hour
return Math.ceil(diff / ) + '分钟前'
} else if (diff < * ) {
return Math.ceil(diff / ) + '小时前'
} else if (diff < * * ) {
return '1天前'
}
if (option) {
return parseTime(time, option)
} else {
return d.getMonth() + + '月' + d.getDate() + '日' + d.getHours() + '时' + d.getMinutes() + '分'
}
} /* 数字 格式化*/
export function nFormatter(num, digits) {
const si = [
{ value: 1E18, symbol: 'E' },
{ value: 1E15, symbol: 'P' },
{ value: 1E12, symbol: 'T' },
{ value: 1E9, symbol: 'G' },
{ value: 1E6, symbol: 'M' },
{ value: 1E3, symbol: 'k' }
];
for (let i = ; i < si.length; i++) {
if (num >= si[i].value) {
return (num / si[i].value + 0.1).toFixed(digits).replace(/\.+$|(\.[-]*[-])+$/, '$1') + si[i].symbol;
}
}
return num.toString();
} export function html2Text(val) {
const div = document.createElement('div');
div.innerHTML = val;
return div.textContent || div.innerText;
} export function toThousandslsFilter(num) {
return (+num || ).toString().replace(/^-?\d+/g, m => m.replace(/(?=(?!\b)(\d{})+$)/g, ','));
}
filters.js
在main.js中引入:
import * as filters from './filters'; // 全局vue filter
Object.keys(filters).forEach(key => {
Vue.filter(key, filters[key])
});
vue后台_实战篇的更多相关文章
- vue后台_登录权限
登录权限控制包含着这么几个方面的含义: 1)不同的权限对应不同的路由 2)侧边栏需要根据不同的权限,异步生成 登录:使用用户名和密码,登录成功后返回用户的token(防止XSS攻击),将此token存 ...
- vue后台_纯前端实现excel导出/csv导出
之前的文件下载功能一般是由前后端配合实现,由于项目需要,纯前端实现了一把excel的导出功能: 一.excel导出 1.安装依赖库 xlsx:这是一个功能强大的excel处理库,但是上手难度也很大,还 ...
- vue+uni-app商城实战 | 第一篇:【有来小店】微信小程序快速开发接入Spring Cloud OAuth2认证中心完成授权登录
一. 前言 本篇通过实战来讲述如何使用uni-app快速进行商城微信小程序的开发以及小程序如何接入后台Spring Cloud微服务. 有来商城 youlai-mall 项目是一套全栈商城系统,技术栈 ...
- 一步步带你做vue后台管理框架(三)——登录功能
系列教程<一步步带你做vue后台管理框架>第三课 github地址:vue-framework-wz 线上体验地址:立即体验 <一步步带你做vue后台管理框架>第一课:介绍框架 ...
- caffe框架下目标检测——faster-rcnn实战篇操作
原有模型 1.下载fasrer-rcnn源代码并安装 git clone --recursive https://github.com/rbgirshick/py-faster-rcnn.git 1) ...
- 新书上线:《Spring Boot+Spring Cloud+Vue+Element项目实战:手把手教你开发权限管理系统》,欢迎大家买回去垫椅子垫桌脚
新书上线 大家好,笔者的新书<Spring Boot+Spring Cloud+Vue+Element项目实战:手把手教你开发权限管理系统>已上线,此书内容充实.材质优良,乃家中必备垫桌脚 ...
- 基于 abp vNext 和 .NET Core 开发博客项目 - 博客接口实战篇(五)
系列文章 基于 abp vNext 和 .NET Core 开发博客项目 - 使用 abp cli 搭建项目 基于 abp vNext 和 .NET Core 开发博客项目 - 给项目瘦身,让它跑起来 ...
- 二、Redis基本操作——String(实战篇)
小喵万万没想到,上一篇博客,居然已经被阅读600次了!!!让小喵感觉压力颇大.万一有写错的地方,岂不是会误导很多筒子们.所以,恳请大家,如果看到小喵的博客有什么不对的地方,请尽快指正!谢谢! 小喵的唠 ...
- 无线安全专题_攻击篇--MAC泛洪攻击
上一篇讲解了无线安全专题_攻击篇--干扰通信,没在首页待多长时间就被拿下了,看来之后不能只是讲解攻击实战,还要进行技术原理和防御方法的讲解.本篇讲解的是局域网内的MAC泛洪攻击,这种攻击方式主要目的是 ...
随机推荐
- [NOIP2018模拟赛10.23]发呆报告
闲扯 考场看了眼题目感觉很难,一个小时敲完了所有暴力...嗯然后就在那里发呆什么事也没做 T3考场上把数据结构想了个遍都不会完成1操作,现在看这种思路其实之前也接触过... 比较玄学的一件事情就是T1 ...
- Android中ListView的使用
1.主要概念 ListView用于将大数据集以列表的形式展示. ListView可以看成一个容器,它有如下继承链: View <- ViewGroup <- AdapterView < ...
- vs-code 的常用插件
最近编辑器转移至VS-Code上面了,为什么抛弃sublime呢,因为,sublime在项目逐渐变大的过程中(项目已上万行,还在不停继续变大),sublime会出现卡顿,反应缓慢,甚至未响应状态,基于 ...
- # URL异常检测
(Isolation Forest无监督)这个算法是随机森林的推广. iTree树构造:随机选一个属性,再随机选该特征的一个值,对样本进行二叉划分,重复以上操作. iTree构建好了后,就可以对数据进 ...
- linux环境安装docker,部署应用
安装: 1.Docker要求CentOS系统的内核版本高于 3.10 ,通过 uname -r 命令查看你当前的内核版本是否支持安账docker 2.更新yum包:sudo yum update 3. ...
- [LeetCode] 784. 字母大小写全排列 ☆☆☆(回溯、深度优先遍历)
https://leetcode-cn.com/problems/letter-case-permutation/solution/shen-du-you-xian-bian-li-hui-su-su ...
- nohub
nohup command > myout.file 2>&1 & nohup command > /dev/null 2>&1 &
- MVC方式显示数据(数据库)
新建实体数据模型 选择ADO.NET实体数据模型,名称改为数据库名 因为使用现有数据库,所以选择来自数据库的EF设计器,只演示所以只选择一个表,空模型可后期增加表 选择从数据库更新模型 新建数据库连接 ...
- vue 的虚拟 DOM 有什么好处?
vue 中的虚拟DOM有什么好处?快! 首先了解浏览器显示网页经历的5个过程 1.解析标签,生成元素树(DOM树) 2.解析样式,生成样式树 3.生成元素与样式的关系 4.生成元素的显示坐标 5.显示 ...
- MySQL数据库的基本认识与操作
Mysql是一个数据库,但是我们安装的mysql数据库服务,服务就会有状态,启动,停止,重启.我们使用mysql必须保证mysql启动. 使用mysql数据库需要连接数据库 Mysql -u -p - ...