手摸手,带你用vue撸后台 系列三(实战篇)

完整项目地址:vue-element-admin
系类文章一:手摸手,带你用vue撸后台 系列一(基础篇)
系类文章二:手摸手,带你用vue撸后台 系列二(登陆权限篇)
系类文章三:手摸手,带你用vue撸后台 系列三(实战篇)
系类文章四:手摸手,带你用vue撸后台 系列四(vueAdmin 一个极简的后台基础模板)
系类文章:手摸手,带你优雅的使用 icon
系类文章:手摸手,带你封装一个vue componentjavascript

前言

在前面两篇文章中已经把基础工做环境构建完成,也已经把后台核心的登陆和权限问题完成了,如今手摸手,一块儿进入实操。php

Element

去年十月份开始用 vue 作管理后台的时候绝不犹豫的就选择了 element-ui,那时候 vue2.0 刚发布也没多久,市面上也没有不少其它的 vue2.0 的 ui 框架可供选择。虽然 element-ui 也有不少的不足,前期的bug也很多,但我仍是选择了它,简单说一下我选择element-ui的缘由吧:css

  • 有大厂背书 : 虽然核心开发只有两三我的,但至少不用担忧哪天就不维护,带着小姨子跑路了
  • 持续迭代 : element-ui发版至今release了四十多个版本,以前平均都是一周一个小版本更新(是否是不当心暴露了它bug多的问题/(ㄒoㄒ)/~~)(ps: 至2017.12.4 已经迭代了74个版本,还保持着较高更新频率)。
  • 生态圈优异,社区活跃 :其 contributors已经有250多人(前期我有饶有兴致的贡献过几个pr,参与过七八十个issue),社区里也有不少基于element-ui 的拓展组件,也有不少相关的 qq 讨论群或者 gitter
  • 社区的承认:目前Element已是vue相关最多star的开源项目了,体现出了社区对其的承认。

说了这么多优势,做为一个资深element-ui用户仍是有些要抱怨的~和react老大哥 Ant Design 相比仍是有必定的差距的,无论是组件的丰富性,参数的可配性仍是文档的完整性,亦或是UI的交互和美观度。不过 ant 也是通过了近9k次commit的不断打磨,才有了今天。我也相信 element-ui也会愈来愈好的。html

这里还有一些其它的框架(只讨论pc端的框架)你们能够自行选择:前端

  • ivew 一国人我的写的框架,美观度和交互性都不错,有种介于Element和Ant之间的感受,以前和element团队小小的撕了一下,有兴趣的本身去围观吧,框架仍是很不作的,一我的能作出这样,也是很不容易的。做者公开信件
  • vue-admin 也是一个不错的选择,代码写的和不错,官方也出了一个admin的架子,也很值得借鉴
  • vue-material 一个material design vue框架库
  • vuetify 又是一个material design vue框架库
  • Keen-UI 又又是一个material design vue框架库
  • CoreUI-Free-Bootstrap-Admin-Template 和之前的Bootstrap同样,搭好了一个完整的架子,你们能够进行二次拓展,它有vue,react,angular多个版本
  • Framework7-Vue 我的感受这是本人体验到如今移动端体验最好的框架。不过Framework7-Vue感受还不是很完善,还须要观望一段时间。并且它有本身的路由规则,因此不能使用 vue-router,这点仍是很不方便的。

简单列举了一些主流的框架,不得不感慨如今vue的生态圈真是太繁荣了,上述框架楼主并无深刻使用过,很差发表太多建议,你们自行甄别适合本身业务的框架吧。vue


这里开始咱们会开始介绍一些结合Element的开发经验。java

基于Element的动态换肤

有些产品就是这么残忍,能完成需求就不错了,还要让咱们作动态换肤。Element官网上也提供了自定义主题的方案
同时也提供了一个在线自定义主题的demonode

是否是很酷,做者也说明了实现的方案 地址,大概思路:react

  1. 先把默认主题文件中涉及到颜色的 CSS 值替换成关键词
  2. 根据用户选择的主题色生成一系列对应的颜色值
  3. 把关键词再换回刚刚生成的相应的颜色值
  4. 直接在页面上加 style 标签,把生成的样式填进去

我看完以为真的仍是有点复杂的。有没有简单的方案呢?
让咱们思考一下,让咱们本身写动态换肤该怎么写呢?最多见的方法就是写两套主题,一套叫day theme ,一套叫night themenight theme主题 都在一个.night-theme的命名空间下,咱们动态的在bodyadd .night-themeremove .night-theme。这就是最简单的动态换肤。因此咱们也能不能顺着这个思路,基于 element-ui 实现动态换肤呢?webpack

首先咱们下载官方经过的 Theme generator ,一个专门用来生成Element主题的工具。按照文档,咱们生成了须要的主题。


以后就是咱们要作的事情了,将这个主题的每一个元素外面包裹一个class 来作命名空间。
咱们这里用到了gulp-css-wrap这个神器,轻轻松松就完成了咱们想要的结果

var path = require('path')
var gulp = require('gulp')
var cleanCSS = require('gulp-clean-css');
var cssWrap = require('gulp-css-wrap');

var customThemeName='.custom-theme'

gulp.task('css-wrap', function() {
  return gulp.src( path.resolve('./theme/index.css'))
    .pipe(cssWrap({selector:customThemeName}))
    .pipe(cleanCSS())
    .pipe(gulp.dest('dist'));
});

gulp.task('move-font', function() {
  return gulp.src(['./theme/fonts/**']).pipe(gulp.dest('dist/fonts'));
});

gulp.task('default',['css-wrap','move-font']);

这样就获得了一个以.custom-theme为命名空间的自定义主题了,以后咱们在项目中引入主题

//main.js
import 'assets/custom-theme/index.css'

咱们在换肤的地方toggleClass(document.body, 'custom-theme')一直toggle body 的 class就能够了。咱们就简单实现了动态换肤效果。


不过这种模式实现换肤也是有一个弊端的,它等于把这两个主题都打包在了项目里,若是你的项目主题须要七八种,这种模式就不适合了。咱们就须要动态的加载css,下面就是最简单的动态添加css的例子,固然你能够封装一下,增长成功或者失败回调,判断是否加载过改资源等等就不展开了。

var head = document.getElementsByTagName('HEAD').item(0);
var style = document.createElement('link');
style.href = 'style.css';
style.rel = 'stylesheet';
style.type = 'text/css';
head.appendChild(style);

更新(2017.12)

element-ui 官方更新了2.0版本,同时也提供了一个新的换肤思路。
文档


侧边栏

这里又有谈一下导航栏的问题,本项目里的侧边栏是根据 router.js 配置的路由而且根据权限动态生成的,这样就省去了写一遍路由还要手动再写一次侧边栏这种麻烦事,但也遇到了一个问题,路由可能会有多层嵌套,不少人反馈本身的侧边栏会有三级,甚至还有五级的。因此重构了一下侧边栏,使用了递归组件,这样无论你多少级,都能愉快的显示了。代码

侧边栏高亮问题: 不少人在群里问为何本身的侧边栏不能跟着本身的路由高亮,其实很简单,element-ui官方已经给了default-active因此咱们只要

:default-active="$route.path"

default-active一直指向当前路由就能够了,就是这么简单。

点击侧边栏 刷新当前路由

在用 spa(单页面开发) 这种开发模式以前,大部分都是多页面后台,用户每次点击侧边栏都会从新请求这个页面,用户渐渐养成了点击侧边栏当前路由来刷新页面的习惯。但如今 spa 就不同了,用户点击当前高亮的路由并不会刷新view,由于vue-router会拦截你的路由,它判断你的url并无任何变化,因此它不会触发任何钩子或者是view的变化。issue地址,社区也对该问题展开了激烈讨论。

尤大原本也说要增长一个方法来强刷view,但后来他又改变了心意/(ㄒoㄒ)/~~。但须要就摆在这里,咱们该怎么办呢?他说了不改变current URL 就不会触发任何东西,那我可不能够强行触发东西你?上有政策, 下有对策咱们变着花来hack。方法也很简单,经过不断改变urlquery来触发view的变化。咱们监听侧边栏每一个link 的 click事件,每次点击都给router push 一个不同的query 来确保会从新刷新view。

clickLink(path) {
  this.$router.push({
    path,
    query: {
      t: +new Date() //保证每次点击路由的query项都是不同的,确保会从新刷新view
    }
  })
}

但这也有一个弊端就是 url 后面有一个很难看的 query 后缀如 xxx.com/article/list?t=1496832345025,但我司用户们表示能接受。。。只能暂时这样hack了,不知道你们有没有更好的方法,学习学习。


Table

通过好几个版本的迭代,element-ui 的table组件已经能知足大部分业务需求了。不过rowSpan colSpan表格行/列合并如今并非支持(element-ui2.0版本以后开始支持)。官方对此功能的更新状况能够关注这个issue

这里我着重讲一下table表格几个经常使用的业务形态。

Table 拖拽排序


这里主要是基于Sortable

import Sortable from 'sortablejs'
let el = document.querySelectorAll('.el-table__body-wrapper > table > tbody')[0]
let sortable = Sortable.create(el)

在table mounted以后申明Sortable.create(el) table的每行tr就能够随意拖拽了,麻烦的目前咱们的排序都是基于dom的,咱们的数据层list并无随之改变。因此咱们就要手动的来管理咱们的列表。

this.sortable = Sortable.create(el, {
  onEnd: evt => { //监听end事件 手动维护列表
    const tempIndex = this.newList.splice(evt.oldIndex, 1)[0];
    this.newList.splice(evt.newIndex, 0, tempIndex);
  }
});

这样咱们就简单的完成了 table 拖拽排序。这里若是不是基于 dom 的排序推荐使用Vue.Draggable完整代码


Table 内联编辑

table内联编辑也是一个常见的需求。


其实也很简单,当咱们拿到 list 数据以后先洗一下数据,每一条数据里面插入一个edit[ true or false ]判断符,来表示当前行是否处于编辑状态。以后就是经过v-show动态切换不一样的相应view就能够了。完整代码

<el-table-column min-width="300px" label="标题">
  <template scope="scope">
    <el-input v-show="scope.row.edit" size="small" v-model="scope.row.title"></el-input>
    <span v-show="!scope.row.edit">{{ scope.row.title }}</span>
  </template>
</el-table-column>
<el-table-column align="center" label="编辑" width="120">
  <template scope="scope">
    <el-button v-show='!scope.row.edit' type="primary" @click='scope.row.edit=true' size="small" icon="edit">编辑</el-button>
    <el-button v-show='scope.row.edit' type="success" @click='scope.row.edit=false' size="small" icon="check">完成</el-button>
  </template>
</el-table-column>

Table 常见坑

经过dialog来编辑,新建,删除table的元素这种业务场景相对于前面说的两种更加的常见。并且也有很多的小坑。
首先咱们要明确一个点 vue 是一个MVVM框架,咱们传统写代码是命令式编程,拿到table这个dom以后就是命令式对dom增删改。而咱们如今用声明式编程,只用关注data的变化就行了,因此咱们这里的增删改都是基于list这个数组来的。这里咱们还要明确一点vue 列表渲染注意事项

因为 JavaScript 的限制, Vue 不能检测如下变更的数组:
* 当你利用索引直接设置一个项时,例如: vm.items[indexOfItem] = newValue

因此咱们想改变table中第一条数据的值,经过this.list[0]=newValue这样是不会生效的。

解决方案:
// Array.prototype.splice`
example1.items.splice(indexOfItem, 1, newValue)

因此咱们能够经过

//添加数据
this.list.unshift(this.temp);

//删除数据 
const index = this.list.indexOf(row); //找到要删除数据在list中的位置
this.list.splice(index, 1); //经过splice 删除数据

//修改数据
const index = this.list.indexOf(row); //找到修改的数据在list中的位置
this.list.splice(index, 1,this.updatedData); //经过splice 替换数据 触发视图更新

这样咱们就完成了对table的增删改操做,列表view也自动响应发生了变化。这里在修改数据的时候还有一个小坑须要主要
当咱们拿到须要修改行的数据时候不能直接将它直接赋值给dialog,否则会发生下面的问题。


如上图所示,咱们在dialog里面改变状态的时候,遮罩下面的table里面该行的状态也在那里跟着一只变化着。缘由想必你们都猜到了。赋值的数据是一个objec引用类型共享一个内存区域的。因此咱们就不能直接连等复制,须要从新指向一个新的引用,方案以下:

//赋值对象是一个obj
this.objData=Object.assign({}, row) //这样就不会共用同一个对象

//数组咱们也有一个巧妙的防范
newArray = oldArray.slice(); //slice会clone返回一个新数组

Tabs

tab在后台项目中也比较经常使用的。假设咱们有四个tab选项,每一个tab都会向后端请求数据,但咱们但愿一开始只会请求当前的tab数据,并且tab来回切换的时候不会重复请求,只会实例化一次。首先咱们想到的就是用v-if 这样的确能作到一开始不会挂载后面的tab,但有一个问题,每次点击这个tab组件都会从新挂载一次,这是咱们不想看到的,这时候咱们就能够用到<keep-alive>了。

keep-alive 包裹动态组件时,会缓存不活动的组件实例,而不是销毁它们。 它是一个抽象组件:它自身不会渲染一个 DOM 元素,也不会出如今父组件链中。

因此咱们就能够这样写tabs了

<el-tabs v-model="activeTab">
  <el-tab-pane label="简介及公告" name="announcement">
    <announcement />
  </el-tab-pane>
  <el-tab-pane label="资讯" name="information">
    <keep-alive>
      <information v-if="activeTab=='information'" />
    </keep-alive>
  </el-tab-pane>
  <el-tab-pane label="直播流配置" name="stream">
    <keep-alive>
      <stream v-if="activeTab=='stream'" />
    </keep-alive>
  </el-tab-pane>
</el-tabs>

Select 选择器

Select 选择器直接使用没有什么太多问题,但不少时候咱们须要经过Select来回显一些数据,当咱们<el-select v-model="objValue"> select 绑定一个obj value回显就会很蛋疼了,它要求必须保持同一个引用issue。这就意味着,咱们回显数据的时候想先要找到该数据在arr中的位置,再回塞:demo。这还不是在远程搜索的状况下,若是是远程搜索的状况还要当疼。
这里推荐一下vue-multiselect 它能完美的解决前面Element select的问题。目前也是vue component 中比较好用的一个,ui也很是的好看,建议你们能够尝试性用一下,真的很是的不错。


Upload 上传

Upload自己没什么好说的,文档写的蛮清楚了。这里主要说一下怎么将Upload组件和七牛直传结合在一块儿。

这里咱们选择api直传的方式,就是咱们首先要经过后端(go,node,php均可以)文档生成七牛上传必要的token(上传凭证)和key(资源的最终名称)。
因此如今只要想办法讲token和key塞进post请求里面就能够了,好在官方也提供了这个方法。


。但怎么才能先异步的拿到token再将它塞入请求里呢?


这时候咱们又发现了before-upload 这个钩子还支持promise简直合咱们的心意。
但咱们写着写着怎样才能动态的改变以前的dataObj呢?经过看源码发现咱们能够_self._data这样子拿到咱们想要的数据。线上代码

<template>
  <el-upload
      action="https://upload.qbox.me"
      :data="dataObj"
      drag
      :multiple="true"
      :before-upload="beforeUpload">
    <i class="el-icon-upload"></i>
    <div class="el-upload__text">将文件拖到此处,或<em>点击上传</em></div>
  </el-upload>
</template>
<script>
    import { getToken } from 'api/qiniu'; // 获取七牛token 后端经过Access Key,Secret Key,bucket等生成token
    // 七牛官方sdk https://developer.qiniu.com/sdk#official-sdk
    export default{
      data() {
        return {
          dataObj: { token: '', key: '' },
          image_uri: [],
          fileList: []
        }
      },
      methods: {
        beforeUpload() {
          const _self = this;
          return new Promise((resolve, reject) => {
            getToken().then(response => {
              const key = response.data.qiniu_key;
              const token = response.data.qiniu_token;
              _self._data.dataObj.token = token;
              _self._data.dataObj.key = key;
              resolve(true);
            }).catch(err => {
              console.log(err)
              reject(false)
            });
          });
        }
      }
    }
</script>

jsx

在使用Element的时候,官方提供了不少能够本身写render function的地方,但因为Element内部都是用jsx 写render function的,因此demo也都是jsx,但不少人本身项目中实际上是没有安装的,致使报错。但说真的用createElement裸写render 函数仍是有些蛋疼。咱们要用jsx,首先要安装 babel-plugin-transform-vue-jsx 安装方法以下:

npm install\
  babel-plugin-syntax-jsx\
  babel-plugin-transform-vue-jsx\
  babel-helper-vue-jsx-merge-props\
  babel-preset-es2015\
  --save-dev

.babelrc:文件

{
  "presets": ["es2015"],
  "plugins": ["transform-vue-jsx"]
}

这样咱们就能够愉快的使用 jsx 写render function了。


element 常见问题

click事件不触发问题:一直有人在群里问<el-input @click="handlenClick">Click Me</el-input>怎么不触发click事件,虽然element文档还有完善的空间但这种问题你们还真要本身好好认真看一下官方的FAQ了。

官方说明了全部的原生事件必须添加 .native 修饰符。

修改element样式问题: 用ui组件总免不了须要对它作一些个性化定制的需求,因此咱们就要覆盖element的一些样式。
首先咱们要了解一下vue scoped是什么,不少人很是喜欢用scoped,妈妈不再用担忧样式冲突问题了,其实scoped也没有很神秘的,它就是基于PostCss的,加了一个做用局的概念。

//编译前
.example {
  color: red;
}
//编译后
.example[_v-f3f3eg9] {
  color: red;
}

它和咱们传统的命名空间的方法避免css冲突没有什么本质性的区别。
如今咱们来讲说怎么覆盖element-ui样式。因为element-ui的样式咱们是在全局引入的,因此你想在某个view里面覆盖它的样式就不能加scoped,但你又想只覆盖这个页面的element样式,你就可在它的父级加一个class,以用命名空间来解决问题。

.aritle-page{ //你的命名空间
    .el-tag { //element-ui 元素
      margin-right: 0px;
    }
}

建议向楼主同样专门建一个scss文件里专门自定义element-ui的各类样式。线上代码

其它关于element相关的东西真的没有什么好说的了,人家文档和源码就放在那里,有问题就去看文档,再去issue里找找,再去看看源码,大部分问题都能解决了。给一个诀窍其实大部分诡异的问题均可以经过加一个key或者
Vue.nextTick来解决。。


富文本

管理后台富文本也是一个很是重要的功能,楼主在这里也踩了很多的坑。楼主在项目里最终选择了 tinymce

这里在简述一下推荐使用tinymce的缘由:tinymce 是一家老牌作富文本的公司(这里也推荐 ckeditor,也是一家一直作富文本的公司,新版本很不错),它的产品经受了市场的承认,无论是文档仍是配置的自由度都很好。在使用富文本的时候有一点也很关键就是复制格式化,以前在用一款韩国人作的富文本summernote被它的格式化坑的死去活来,但 tinymce 的去格式化至关的好,它还有一个增值项目就是powerpaste,那是无比的强大,支持从word里面复制各类东西,都不会有问题。富文本还有一点也很关键,就是拓展性。楼主用tinymce写了好几个插件,学习成本和容易度都不错,很方便拓展。最后一点就是文档很完善,基本你想获得的配置项,它都有。tinymce也支持按需加载,你能够经过它官方的build页定制本身须要的plugins。
我再来分析一下市面上其它的一些富文本:

  • summernote 先来讲一个我绝对不推荐的富文本。这是一个韩国人开源的富文本(固然不推荐的理由不是由于这个),它对不少富文本业界公认的默认行为理解是反起到而行的,并且只为用了一个dialog的功能,引入了boostrap,一堆人抗议就是不改。格式化也是差劲。。反正不要用!不要用!不要用!
  • ckeditor ckeditor也是一家老牌作富文本的公司,楼主旧版后台用的就是这个,今年也出了5.0版本,ui也变美观了很多,至关的不错,并且它号称是插件最丰富的富文本了。推荐你们也能够试用一下。
  • quill 也是一个很是火的富文本,长相很不错。基于它写插件也很简单,api设计也很简单。楼主不选择它的缘由是它对图片的各类操做不友善,并且很难改。若是对图片没什么操做的用户,推荐使用。
  • medium-editor 大名鼎鼎的medium的富文本(非官方出品),但完成度仍是不很不错,拓展性也不错。不过我以为大部分用户仍是会不习惯medium这种写做方式的。
  • Squire 一个比较轻量的富文本,压缩完才11.5kb,相对于其它的富文原本说是很是的小了,推荐功能不复杂的建议使用。
  • wangEditor 一个国人写的富文本,用过感受仍是不错的。不过毕竟是我的的,不像专门公司作富文本的,配置型和丰富性不足。前端几大禁忌就有富文本 为何都说富文本编辑器是天坑?,不过我的能作成这样子很不容易了。
  • 百度UEditor 没有深刻使用过,只在一个angular1X的项目简单用过,不过说着的ui真的很差看,不符合当今审美了,官方也已经好久没跟新过了。

楼主列举了不少富文本但并无列举任何 vue 相关的富文本,主要是由于富文本真的比想象中复杂,在前面的文章里也说过了,其实用 vue 封装组件很方便的,不必去用人家封装的东西什么vue-quill vue-editor这种都只是简单包了一层,没什么难度的。还不如本身来封装,灵活性可控性更强一点。还有一点基于 vue 真没什么好的富文本,不像 react 有 facebook 出的 draft-js,ory 出的 editor,这种大厂出的产品。

固然你也能够选择一些付费的富文本编辑器,做者本身公司里面有一个项目就使用了 froala-editor 这款编辑器。无论是美观和易用性都是不错的,公司买的是专业版,一年也就 $349 ,价格也是很合理的,但其实省去的程序员开发陈本可能远不止这个价钱。

Tinymce

这里来简单讲一下在本身项目中使用 Tinymce 的方法。

因为目前使用 npm 安装 Tinymce 方法比较负责复杂并且还有一些问题(往后可能会采用该模式)。

目前采用全局引用的方式。代码地址:static/tinymce static目录下的文件不会被打包, 在 index.html 中引入。

使用
因为富文本不适合双向数据流,因此只会 watch 传入富文本的内容一次变化,只会就不会再监听了,若是以后还有改变富文本内容的需求。
能够经过 this.refs.xxx.setContent() 来设置

源码也很简单,有任何别的需求均可以在 @/components/Tinymce/index.vue 中自行修改。


Markdown

markdown 咱们这里选用了 simplemde-markdown-editor ,简单的用vue封装了一下地址,若是需求方能接受 markdown 就必定要用 markdown,坑真心会比富文本少不少。这里咱们用markdown作了编辑器,还须要一个能解析的的东西。能够你传给后端让后端帮你转化,也能够前端本身来,这里推荐一个转化库showdown。使用方法:

import('showdown').then(showdown => { //用了 Dynamic import
  const converter = new showdown.Converter();//初始化
  this.html = converter.makeHtml(this.content)//转化
})

用法也很简单两行代码就完成了markdown to html,固然它还有不少个性画的配置,你们有需求自行研究吧。


导出excel

这里先明确一点,若是你的业务需求对导出文件的格式没有什么要求,不建议导出成xlsx格式的,直接导出成csv的就行了,真的会简单不少。建立一个a标签,写上data:text/csv;charset=utf-8头,再把数据塞进去,encodeURI(csvContent)一下就行了,详情就不展开了,你们能够借鉴这个stackoverflow回答
咱们重点说一下转xlsx,咱们这里用到了js-xlsx,一个功能很强大excel处理库,只是下载各类格式excel,还支持读取excel,但上手难度也很是大,至关的复杂,其中涉及很多二进制相关的东西。不过好在官方给了咱们一个demo例子,咱们写不来还抄不来么,因而咱们就借鉴官方的例子来改造了一下,具体原理就不详细说了,真的很复杂。。。
重点是咱们怎么使用!首先咱们封装一个Export2Excel.js
它又依赖三个库

require('script-loader!file-saver'); //保存文件用
require('script-loader!vendor/Blob'); //转二进制用
require('script-loader!xlsx/dist/xlsx.core.min'); //xlsx核心

因为这几个文件不支持import引入,因此咱们须要`script-loader`来将他们挂载到全局环境下。

它暴露了两个接口export_table_to_excelexport_json_to_excel,咱们经常使用export_json_to_excel由于更加的可控一点,咱们能够自由的洗数据。

handleDownload() {
  require.ensure([], () => { // 用 webpack Code Splitting xlsl仍是很大的
    const { export_json_to_excel } = require('vendor/Export2Excel');
    const tHeader = ['序号', '文章标题', '做者', '阅读数', '发布时间']; // excel 表格头
    const filterVal = ['id', 'title', 'author', 'pageviews', 'display_time'];
    const list = this.list;
    const data = this.formatJson(filterVal, list); // 自行洗数据 按序排序的一个array数组
    export_json_to_excel(tHeader, data, '列表excel');
  })
},
formatJson(filterVal, jsonData) {
  return jsonData.map(v => filterVal.map(j => v[j]))
}

完整显示线上代码


ECharts

管理后台图表也是常见得需求。这里图表就只推荐ECharts,功能齐全,社区demo也丰富gallery。我仍是那个观点,大部分插件建议你们仍是本身用vue来包装就行了,真的很简单。ECharts支持webpack引入,图省事能够将ECharts整个引入var echarts = require('echarts');不过ECharts仍是不小的,咱们大部分状况只是用到不多一部分功能,我平时习惯于按需引入的。

// 引入 ECharts 主模块
var echarts = require('echarts/lib/echarts');
// 引入柱状图
require('echarts/lib/chart/bar');
// 引入提示框和标题组件
require('echarts/lib/component/tooltip');
require('echarts/lib/component/title');

webpack中使用ECharts文档
ECharts按需引入模块文档
接下来咱们就要在vue中声明初始化ECharts了。由于ECharts初始化必须绑定dom,因此咱们只能在vue的mounted生命周期里初始化。

mounted() {
  this.initCharts();
},
methods: {
  this.initCharts() {
    this.chart = echarts.init(this.$el);
    this.setOptions();
  },
  setOptions() {
    this.chart.setOption({
      title: {
        text: 'ECharts 入门示例'
      },
      tooltip: {},
      xAxis: {
        data: ["衬衫", "羊毛衫", "雪纺衫", "裤子", "高跟鞋", "袜子"]
      },
      yAxis: {},
      series: [{
        name: '销量',
        type: 'bar',
        data: [5, 20, 36, 10, 10, 20]
      }]
    })
  }
}

就这样简单,ECharts就配置完成了,这时候你想说个人data是远程获取的,或者说我动态改变ECharts的配置该怎么办呢?咱们能够经过watch来触发setOptions方法

//第一种 watch options变化 利用vue的深度 watcher,options一有变化就从新setOption
watch: {
  options: {
    handler(options) {
      this.chart.setOption(this.options)
    },
    deep: true
  },
}
//第二种 只watch 数据的变化 只有数据变化时触发ECharts
watch: {
  seriesData(val) {
    this.setOptions({series:val})
  }
}

其实都差很少,仍是要结合本身业务来封装。后面就和平时使用ECharts没有什么区别了。题外话ECharts的可配置项真心多,你们使用的时候可能要花一点时间了解它的api的。知乎有个问题:百度还有什么比较良心的产品?答案:ECharts,可见ECharts的强大与好用。


相同component 不一样参数

建立与编辑
其实后台建立与编辑功能是最多见的了,它区别去前台项目多了改的需求,但大部分建立页面与编辑页面字段和ui几乎是同样的,因此咱们准备公用一个component来对应不一样的页面。有两种常见的方法,来区别建立与编辑。

  1. 经过路由path的方式

这种方式最简单暴力,我本身的项目中使用这种方式,经过约定路径中出现'edit'就判断为编辑模式。比较省力和方便,不过这是要在你们写路径的时候都按照规范来写的前提下。

  1. 经过meta来区分

比较推荐这种方式来区分。

computed: {
  isEdit() {
    return this.$route.meta.isEdit // 根据meta判断
    // return this.$route.path.indexOf('edit') !== -1 // 根据路由判断
  }
},
created() {
  if (this.isEdit) { 
    this.fetchData();
  }
},

就这样简单的实现了多路由复用了一个component,其实不仅是建立和编辑能够这样用,如两个列表的如出一辙,只是一个是内部文章另外一个是调取外部文章都能复用组件,经过meta的方式来判断调取不一样的接口。


占坑

常规占坑,这里是手摸手,带你用vue撸后台系列。
完整项目地址:vue-element-admin
系类文章一:手摸手,带你用vue撸后台 系列一(基础篇)
系类文章二:手摸手,带你用vue撸后台 系列二(登陆权限篇)
系类文章三:手摸手,带你用vue撸后台 系列三(实战篇)
系类文章四:手摸手,带你用vue撸后台 系列四(vueAdmin 一个极简的后台基础模板)
系类文章:手摸手,带你优雅的使用 icon
系类文章:手摸手,带你封装一个vue component
楼主我的免费圈子

相关文章
相关标签/搜索