Vue常用操作和技巧
Vue常用操作和技巧
进行Vue开发近2年的经验,总结出一些比较常用的开发技巧,当然Vue本身也在不断的迭代更新,所以本文档在大量实践总结后,仍会进行不断更新
自定义文件快捷路径
减少不必要的文件路径的输入,更跨界的路径引入方式
resolve: {
extensions: ['.js','.vue','json'],
lias: {
'@': resolve('src'),
'assets': resolve('src/assets'),
'utils': resolve('src/utils'),
'components': resolve('src/components'),
// ... 引入需要配置的即可
}
}
使用:
import { getUrlParams } from 'utils';
import { HeadTop } from 'components/HeadTop';
// ...
CSS预处理器全局变量的配置
前端项目开发前,合格的UI设计师一般都会给出整个项目最基本的几种配色:主题色,包括按钮,背景,边框,等等。这些样式颜色的配置我们其实并不需要在每个文件中都重复书写,或者说重复引入某一color.css文件
借助webpack的配置可以解决这一问题
vue-cli2.0配置
build/utils.js文件下修改
sass: generateLoaders('sass').concat({
loader: 'sass-resources-loader',
options: {
resources: path.resolve(__dirname, '../src/style/_variable.sass'),
}
})
less: generateLoaders('less').concat({
loader: 'sass-resources-loader',
options: {
resources: path.resolve(__dirname, '../src/style/_variable.less'),
}
})
scss: generateLoaders('scss').concat({
loader: 'sass-resources-loader',
options: {
resources: path.resolve(__dirname, '../src/style/_variable.scss')
}
}),
scss和less选择其一即可,主要根据项目的选择的预处理决定
vue-cli3.0配置
根目录新建vue.config.js
module.expoerts = {
css:{
loaderOptions:{
sass:{
// 注意:在 sass-loader v8 中,这个选项名是 "prependData"
additionalData:`@import "@/src/style/_variable.sass";@import "@/src/style/_theme.sass"`
},
// 默认情况下 `sass` 选项会同时对 `sass` 和 `scss` 语法同时生效
// 因为 `scss` 语法在内部也是由 sass-loader 处理的
// 但是在配置 `prependData` 选项的时候
// `scss` 语法会要求语句结尾必须有分号,`sass` 则要求必须没有分号
// 在这种情况下,我们可以使用 `scss` 选项,对 `scss` 语法进行单独配置
scss: {
additionalData: `@import "@/src/style/_variable.scss";@import "@/src/style/_theme.scss"`
},
less: {
additionalData: `@import "@/src/style/_variable.less";@import "@/src/style/_theme.less"`
}
}
}
}
// 如果sass-loader是v8以下则需要更改写法
module.expoerts = {
css:{
loaderOptions:{
sass:{
data:`@import "@/src/style/_variable.sass";@import "@/src/style/_theme.sass"`
}
}
}
}
// 如果是其他版本
module.exports = {
css:{
loaderOptions:{
sass:{
perpenData:`@import "@/src/style/_variable.sass";@import "@/src/style/_theme.sass"`
}
}
}
}
补充
配置过程中,如果缺少很多依赖,根据提示自行下载即可
配置完成后,在项目的任何文件中都可以使用我们在_variable.*文件中的变量。
配置方法很多,如果对webpack有一定的了解,可自行配置~
required.context()
在目录结构有规则的情况下,我们可以免去一些不必要的引入操作
入参
/**
* @description 模块的批量引入
* @params {String,Boolean,Reg } 目录,是否检索子目录,正则
*/
require.context(directory,useSubdirectories,regExp);
情景
引入Store模块时
// bad
import aaStore from './modules/xx';
import bbStore from './modules/bb';
const store = new Vuex.store({
modules: {
aaStore,
bbStore
}
})
// good
const modulesFiles = require.context('./modules', true, /\.js$/)
const modules = modulesFiles.keys().reduce((modules, modulePath) => {
const moduleName = modulePath.replace(/^\.\/(.*)\.\w+$/, '$1')
const value = modulesFiles(modulePath)
modules[moduleName] = value.default
return modules
}, {})
const store = new Vuex.store({
modules: {
...modules
}
})
在页面中引入组件时
const path = require('path')
const files = require.context('../components', false, /\.vue$/)
const modules = {}
files.keys().forEach((key) => {
const name = path.basename(key, '.vue')
modules[name] = files(key).default || files(key)
})
components: { ...modules }
在模块化开发的项目中,它确实是一个非常实用的一个工具!
Object.freeze()
Vue通过object.defineProperty()对数据劫持来实现视图响应数据的变化,如果我们的组件知识为了展示数据
那么为了更快的响应我们可以取消劫持
export default {
data: () => ({
list: [],
}),
created() {
this.$axios.get('xxxx').then(res => {
this.list = Object.freeze(list)
})
},
methods: {
// 此处做的操作都不能改变list的值
},
}
页面中的固定的常量数据如下拉框数据等都可以通过此方法来做一部分的优化
路由懒加载
在需要时加载路由,介绍不必要的资源浪费和空间占用
// require法
component: resolve=>(require(['@/components/HelloWorld'],resolve))
// import
component: () => import('@/components/HelloWorld')
如果您使用的是 Babel,你将需要添加 syntax-dynamic-import
插件,才能使 Babel 可以正确地解析语法。
vIF和vFor同时使用
避免v-if和v-for同时使用是为了避免糟糕的性能浪费及其它的未知问题
但需求有时候却避不开,我们可以这么去改进
// bad
<template>
<ul v-for="item in list" v-if="item.isShow" :key="item.id">
<li>{{ item.name }}</li>
</ul>
</template>
// good
<template>
<ul v-for="item in filterList" :key="item.id">
<li>{{ item.name }}</li>
</ul>
</template>
computed: {
filterList: () => {
return this.list.filter(item => item.isShow);
}
}
图片懒加载
项目中大量展示列表和图片时,我们可以借助vue-lazyload插件来实现一定的性能优化
npm install vue-lazyload --save-dev
// main.js
import VueLazyload from 'vue-lazyload';
Vue.use(VueLazyload,{
preLoad: 1.3,
error: '@/assets/images/global/error.png',
loading: '@/assets/images/global/loading.gif',
attempt: 1
});
使用:
<img v-lazy="item.img" :key="item.img" />
样式穿透
通过scoped锁定了当前组件的样式只能供当前组件使用,但是一些三方的组件的样式,我们仍需要去更改,我们就可以通过样式穿透来实现优雅的处理
Less
<style scoped lang="less">
/deep/.el-button {
height: 60px;
}
</style>
Scss
<style scoped lang="scss">
::v-deep.el-button {
height: 60px;
}
</style>
Stylus
<style scoped lang="stylus">
>>>.el-button {
height: 60px;
}
</style>
本地图片资源的引入
正常情况下,在使用本地资源作为背景图时,会因为webpack找不到路径不识别而报错
background-image: url(~@assets/images/xxx.png);
通过添加~符号webpack将会把这个路径作为依赖模块去解析,前提是我们在alias中进行过配置
install
优雅的使用install,可以很大程度减少main.js文件的臃肿
通常项目中,会有全局的指令,全局的组件,全局的工具方法,我们并不需要分开在main.js中一个一个的引入,通过install的使用可以解决此问题
/global
/components
index.js
/utils
index.js
/directives
index.js
/filters
index.js
index.js
组件,工具,指令,过滤器我们一般都会分别导出
// components/index.js
export { component1 } from './components1.vue'
export { component2 } from './components2.vue'
// utils/index.js
export { method1 } from './method1.js';
export { method2 } from './method2.js';
// directives/index.js
export { directive1 } from './directive1.js';
export { directive2 } from './directive2.js';
// filters/index.js
export { filter1 } from './filter1.js';
export { filter2 } from './filter2.js';
然后我们在globa/index.js下就可以通过使用install来进行全局的注册
import * as Directives from './directives';
import * as Components from './components';
import * as Utils from './utils';
import * as Filters from './filters';
export default {
install: (Vue) => {
for (let name in Object.keys(Components)) {
Vue.component(Components[name]['name'], Components[name]);
}
for (let name in Directives) {
Vue.directive(name, Directives[name]);
}
for (let name in Filters) {
Vue.filter(name,Filters[name])
}
Object.assign(Vue.prototype.$utils ? Vue.prototype.$utils : {}, Utils);
}
};
data数据重置
表单的提交过程中,如果想重置表单,除了一些三方库提供的方法外,vue本身也是有比较的好的方法来进行重置的
export default {
data: () => ({
form: {
input: ''
}
}),
methods: {
resetForm() {
this.form = this.$options.data().form;
}
}
}
本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!