Vue项目中最新用到的一些实用小技巧


Posted in Javascript onNovember 06, 2018

写在前面

在最近的 Vue 项目中,为了完成需求使用了一些小技巧,做个笔记,或许也能帮到道友。

阅读重点

需求一:为路径配置别名

在开发过程中,我们经常需要引入各种文件,如图片、CSS、JS等,为了避免写很长的相对路径(../),我们可以为不同的目录配置一个别名。

找到 webpack.base.config.js 中的 resolve 配置项,在其 alias 中增加别名,如下:

创建一个 CSS 文件,随便写点样式:

.avatar
 display: flex;
 justify-content: center;
 align-items: center;

.avatar-img
 padding 20px
 border solid 1px #ccc
 border-radius 5px

接着,在我们需要引入的文件中就可以直接使用了:

<template>
 <div class="avatar">
 <img class="avatar-img" src="~img/avatar.png" alt="">
 </div>
</template>

<script>
 export default {
 name: "Home"
 }
</script>

<style scoped lang="stylus">
 @import "~css/avatar";
</style>

需要注意的是,如果不是通过 import 引入则需要在别名前加上 ~,效果如下:

Vue项目中最新用到的一些实用小技巧

需求二:要求实现在生产包中直接修改api地址

这个需求,怎么说呢,反正就是需求,就想办法实现吧。

假设有一个 apiConfig.js 文件,用于对 axios 做一些配置,如下:

import axios from 'axios';

axios.defaults.timeout = 10000;
axios.defaults.retry = 3;
axios.defaults.retryDelay = 2000;
axios.defaults.responseType = 'json';
axios.defaults.withCredentials = true;
axios.defaults.headers.post["Content-type"] = "application/json";

// Add a request interceptor
axios.interceptors.request.use(function (config) {
 // Do something before request is sent
 return config;
}, function (error) {
 // Do something with request error
 return Promise.reject(error);
});

// Add a response interceptor
axios.interceptors.response.use(function (response) {
 // Do something with response data
 return response;
}, function (error) {
 // Do something with response error
 return Promise.reject(error);
});

export default axios

在 static 文件夹中增加一个 config.json 文件,用于统一管理所有的 api 地址:

{
 "base": "/api",
 "static": "//static.com/api",
 "news": "//news.com.api"
}

打开 main.js,写入下列代码:

// The Vue build version to load with the `import` command
// (runtime-only or standalone) has been set in webpack.base.conf with an alias.
import Vue from 'vue'
import App from './App'
import router from './router'
import ElementUI from 'element-ui';
import 'element-ui/lib/theme-chalk/index.css';
import axios from 'js/apiConfig'; //import直接引入,不用添加~

Vue.config.productionTip = false;
Vue.use(ElementUI);

/* eslint-disable no-new */
let startApp = function () {
 let randomStamp = new Date().getTime();
 axios.get(`/static/config.json?t=${randomStamp}`).then((data) => {
 axios.defaults.baseURL = data.base; //设置一个默认的根路径
 Vue.prototype.$axios = axios;
 Vue.prototype.$apiURL = data; //将所有路径配置挂载到 Vue 原型上
 /* eslint-disable no-new */
 new Vue({
 el: '#app',
 router,
 components: {App},
 template: '<App/>'
 });
 })
};
startApp();

就是先用 axios 获取 api 文件,然后再初始化。

需求三:由后台根据用户权限值返回菜单

菜单是树形结构(PS:就算不是树形结构,你也得处理成树形结构),我这里使用的是 ElementUI ,参考了道友的这篇文章,实现如下:

新建一个 Menu.vue 文件,写入如下代码:

<script>
 export default {
 name: "MenuItem",
 props: {
 data: {
 type: Array
 },
 collapse: {
 type: Boolean
 }
 },
 methods: {
 //生成菜单项
 createMenuItem(data, createElement) {
 return data.map(item => {
  if (item.children && item.children.length) {
  return createElement('el-submenu', {props: {index: item.id.toString()}},
  [
  createElement('template', {slot: 'title'}, [
   createElement('i', {class: item.icon}),
   createElement('span', [item.title]),
   ]
  ),
  this.createMenuItem(item.children, createElement) //递归
  ]
  )
  } else {
  return createElement('el-menu-item', {props: {index: item.path}},
  [
  createElement('i', {class: item.icon}),
  createElement('span', {slot: 'title'}, [item.title]),
  ]
  )
  }
 })
 },
 //选中菜单
 onSelect(key, keyPath) {
 console.log(key, keyPath);
 }
 },
 render(createElement) {
 return createElement(
 'el-menu',
 {
  props: {
  backgroundColor: "#545c64",
  textColor: "#fff",
  activeTextColor: "#ffd04b",
  collapse: this.collapse,
  router:true
  },
  class:'el-menu-vertical-demo',
  on: {
  select: this.onSelect
  }
 },
 this.createMenuItem(this.data, createElement)
 )
 }
 }
</script>

<style scoped lang="stylus">
 .el-menu-vertical-demo:not(.el-menu--collapse) {
 width: 200px;
 min-height: 400px;
 }
</style>

这里主要用到两个东西,一个是 render 函数,一个是递归,如果不熟悉 render 函数的道友请点这里。可能有道友会问为什么不用模板,因为······做不到啊?,在 template 中只能有一个根元素,而 Vue 限制了不能对根元素使用 v-for;再者,通过在浏览器中查看代码可以知道,菜单就是 ul 加上 li,如果有了根元素会破坏标签结构(虽然不影响功能,但还是觉得不舒服?)。然后,在需要使用的地方:

<template>
 <el-container>
 <el-aside width="auto">
 <Menu :data="menu" :collapse="isCollapsed"></Menu>
 </el-aside>
 <el-container>
 <el-header>
 <el-button type="text" icon="el-icon-d-arrow-left"
   @click="isCollapsed=!isCollapsed"></el-button>
 <h3>MenuName</h3>
 <span>MeFelixWang</span>
 </el-header>
 <el-main>
 <router-view></router-view>
 </el-main>
 </el-container>
 </el-container>
</template>

<script>
 import Menu from '@/components/Menu';

 export default {
 name: 'App',
 data() {
 return {
 menu: [
  {
  title: '导航一',
  id: 1,
  path: '',
  icon: 'el-icon-search',
  children: [
  {
  title: '导航一杠一', id: 2, path: '', icon: '', children: [
   {title: '导航一杠一杠一', id: 4, path: '/test', icon: '', children: []},
   {
   title: '导航一杠一杠二', id: 5, path: '', icon: '', children: [
   {title: '导航一杠一杠二杠一', id: 6, path: '/6', icon: '', children: []},
   {title: '导航一杠一杠二杠二', id: 7, path: '/7', icon: '', children: []},
   ]
   },
  ]
  },
  {title: '导航一杠二', id: 3, path: '/3', icon: '', children: []}
  ]
  },
  {title: '导航二', id: 8, path: '/8', icon: 'el-icon-setting', children: []},
  {title: '导航三', id: 9, path: '/9', icon: 'el-icon-document', children: []},
  {
  title: '导航四', id: 10, path: '', icon: 'el-icon-date', children: [
  {title: '导航四杠一', id: 11, path: '/11', icon: '', children: []},
  {
  title: '导航四杠二', id: 12, path: '', icon: '', children: [
   {title: '导航四杠二杠一', id: 14, path: '/14', icon: '', children: []}
  ]
  },
  {title: '导航四杠三', id: 13, path: '/13', icon: '', children: []},
  ]
  },
 ],
 isCollapsed: false
 }
 },
 methods: {
 handleOpen(key, keyPath) {
 console.log(key, keyPath);
 },
 handleClose(key, keyPath) {
 console.log(key, keyPath);
 }
 },
 components: {
 Menu
 }
 }
</script>

<style lang="stylus">
 *
 margin 0
 padding 0

 html, body, .el-container, .el-aside
 height 100%

 .el-aside
 background-color rgb(84, 92, 100)

 .el-menu
 border-right solid 1px rgb(84, 92, 100)

 .el-header
 display flex
 justify-content space-between
 align-items center
 background-color aliceblue
 .el-button--text
 color: #606266;
 i
 font-weight bold
</style>

效果如下:

Vue项目中最新用到的一些实用小技巧

需求四:这个 Select 选项是树形结构,一定得是树形结构

树形结构就树形结构吧,不就是样式嘛,改改应该就可以了。

<template>
 <div>
 <el-select v-model="tree" placeholder="请选择活动区域">
 <el-option v-for="(item,index) in options" :key="index" :label="item.label" :value="item.id"
   :style="{paddingLeft:(item.level*10+20)+'px'}" :class="item.level?'is-sub':''"></el-option>
 </el-select>
 选择的是:{{tree}}
 </div>
</template>

<script>
 export default {
 name: "Home",
 data() {
 return {
 tree: '',
 options: [],
 originData: [
  {
  label: '这是根一', id: 1, children: [
  {label: '这是茎一一', id: 2, children: []},
  {label: '这是茎一二', id: 3, children: []},
  {
  label: '这是茎一三', id: 4, children: [
   {label: '这是叶一三一', id: 6, children: []},
   {label: '这是叶一三二', id: 7, children: []},
  ]
  },
  {label: '这是茎一四', id: 5, children: []},
  ]
  },
  {
  label: '这是根二', id: 8, children: [],
  },
  {
  label: '这是根三', id: 9, children: [
  {label: '这是茎三一', id: 10, children: []},
  {
  label: '这是茎三二', id: 11, children: [
   {label: '这是叶三二一', id: 12, children: []}
  ]
  },
  ],
  },
 ]
 }
 },
 created() {
 this.options = this.decomposeTree(this.originData, 0);
 },
 methods: {
 //分解树形结构
 decomposeTree(array, level) {
 let tmpArr = [];

 (function decompose(arr, lev) {
  for (let i = 0; i < arr.length; i++) {
  let tmpObj = {};
  let item = arr[i];
  item.level = lev;
  tmpObj = Object.assign({}, item);
  tmpArr.push(tmpObj);
  if (item.children) {
  decompose(item.children, lev + 1); //递归
  }
  delete tmpObj.children; //删掉其 children,避免数据过大(不删也可以,也许后面有用呢)
  }

 })(array, level);

 return tmpArr;
 }
 }
 }
</script>

<style scoped lang="stylus">
 .is-sub:before
 content '- '
</style>

因为 option 接收的是一个一维数组,所以通过递归展平树形结构,在展平的时候设置每项的层级,通过层级来设置缩进及前缀符号,效果如下:

Vue项目中最新用到的一些实用小技巧

之所以这样做,是因为是管理系统,简单有效,没必要因为这一个组件引个新的插件或者自己写一个(以后用得着的除外哈);也可以用 input 加上 tree 控件来模拟(PS:最终还是引入了一个插件,哈哈?)。

最后叨叨
本文是我最近用到的一些小技巧,如果道友们有更好的实现方法,欢迎在评论区留言讨论,文中错误也欢迎指出,共同学习

以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,谢谢大家对三水点靠木的支持。

Javascript 相关文章推荐
兼容多浏览器的字幕特效Marquee的通用js类
Jul 20 Javascript
Extjs学习笔记之五 一个小细节renderTo和applyTo的区别
Jan 07 Javascript
js 获取Listbox选择的值的代码
Apr 15 Javascript
(jQuery,mootools,dojo)使用适合自己的编程别名命名
Sep 14 Javascript
javascript中String类的subString()方法和slice()方法
May 24 Javascript
angularJS 入门基础
Feb 09 Javascript
理解Javascript的call、apply
Dec 16 Javascript
jQuery+css实现的时钟效果(兼容各浏览器)
Jan 27 Javascript
JSON 必知必会 观后记
Oct 27 Javascript
Angular 4 依赖注入学习教程之FactoryProvider的使用(四)
Jun 04 Javascript
微信小程序列表中item左滑删除功能
Nov 07 Javascript
express启用https使用小记
May 21 Javascript
详解Vue内部怎样处理props选项的多种写法
Nov 06 #Javascript
微信小程序实现选项卡效果
Nov 06 #Javascript
Vue props 单向数据流的实现
Nov 06 #Javascript
给localStorage设置一个过期时间的方法分享
Nov 06 #Javascript
移动端H5页面返回并刷新页面(BFcache)的方法
Nov 06 #Javascript
学习使用ExpressJS 4.0中的新Router的用法
Nov 06 #Javascript
vue项目上传Github预览的实现示例
Nov 06 #Javascript
You might like
smarty模板嵌套之include与fetch性能测试
2010/12/05 PHP
完美解决phpexcel导出到xls文件出现乱码的问题
2016/10/29 PHP
PHP7如何开启Opcode打造强悍性能详解
2018/05/11 PHP
PHP面向对象程序设计之对象克隆clone和魔术方法__clone()用法分析
2019/06/12 PHP
javascript 支持链式调用的异步调用框架Async.Operation
2009/08/04 Javascript
javascript 自动填写表单的实现方法
2010/04/09 Javascript
基于Jquery的温度计动画效果
2010/06/18 Javascript
JavaScript打字小游戏代码
2011/12/26 Javascript
动态创建script在IE中缓存js文件时导致编码的解决方法
2014/05/04 Javascript
JQuery教学之性能优化
2014/05/14 Javascript
nodejs实现黑名单中间件设计
2014/06/17 NodeJs
node+express+ejs制作简单页面上手指南
2014/11/26 Javascript
js实现用户离开页面前提示是否离开此页面的方法(包括浏览器按钮事件)
2015/07/18 Javascript
jQuery实现动画效果circle实例
2015/08/06 Javascript
JavaScript设置表单上传时文件个数的方法
2015/08/11 Javascript
jQuery获取元素父节点的方法
2016/06/21 Javascript
jQuery多选框选择数量限制方法
2017/02/08 Javascript
利用Javascript实现简单的转盘抽奖
2017/02/13 Javascript
ES6基础之 Promise 对象用法实例详解
2019/08/22 Javascript
解决layui的radio属性或别的属性没显示出来的问题
2019/09/26 Javascript
微信小程序后端无法保持session的原因及解决办法问题
2020/03/20 Javascript
初学python数组的处理代码
2011/01/04 Python
利用Python的Flask框架来构建一个简单的数字商品支付解决方案
2015/03/31 Python
在Python下进行UDP网络编程的教程
2015/04/29 Python
python 用下标截取字符串的实例
2018/12/25 Python
简洁自适应404页面HTML好看的404源码
2020/12/16 HTML / CSS
XML文档定义有几种形式?它们之间有何本质区别?解析XML文档有哪几种方式?
2016/01/12 面试题
商务英语专业毕业生自荐信
2013/11/05 职场文书
初中三年学生的学习自我评价
2013/11/13 职场文书
生日邀请函范文
2014/01/13 职场文书
社团活动总结模板
2014/06/30 职场文书
银行授权委托书样本
2014/10/13 职场文书
2014年信访维稳工作总结
2014/12/08 职场文书
拾金不昧感谢信范文
2015/01/21 职场文书
导游词之唐山景点
2019/12/18 职场文书
python实现图片九宫格分割的示例
2021/04/25 Python