搜索
首页web前端js教程Vue使用技巧总结

Vue使用技巧总结

May 15, 2018 pm 01:59 PM
使用技巧总结

这次给大家带来Vue使用技巧总结,Vue使用技巧总结的注意事项有哪些,下面就是实战案例,一起来看一下。

在vue的使用过程中会遇到各种场景,当普通使用时觉得没什么,但是或许优化一下可以更高效更优美的进行开发。下面有一些我在日常开发的时候用到的小技巧,在下将不定期更新~

1. 多图表resize事件去中心化

1.1 一般情况

有时候我们会遇到这样的场景,一个组件中有几个图表,在浏览器resize的时候我们希望图表也进行resize,因此我们会在父容器组件中写:

mounted() {
 setTimeout(() => window.onresize = () => {
 this.$refs.chart1.chartWrapperDom.resize()
 this.$refs.chart2.chartWrapperDom.resize()
 // ... 
 }, 200)
destroyed() { window.onresize = null }

这样子图表组件如果跟父容器组件不在一个页面,子组件的状态就被放到父组件进行管理,为了维护方便,我们自然希望子组件的事件和状态由自己来维护,这样在添加删除组件的时候就不需要去父组件挨个修改

1.2 优化

这里使用了lodash的节流throttle函数,也可以自己实现,这篇文章也有节流的实现可以参考一下。 以Echarts为例,在每个图表组件中:

computed: {
 /**
 * 图表DOM
 */
 chartWrapperDom() {
 const dom = document.getElementById('consume-analy-chart-wrapper')
 return dom && Echarts.init(dom)
 },
 /**
 * 图表resize节流,这里使用了lodash,也可以自己使用setTimout实现节流
 */
 chartResize() {
 return _.throttle(() => this.chartWrapperDom && this.chartWrapperDom.resize(), 400)
 }
},
mounted() {
 window.addEventListener('resize', this.chartResize)
},
destroyed() {
 window.removeEventListener('resize', this.chartResize)
}

2. 全局过滤器注册

2.1 一般情况

官方注册过滤器的方式:

export default {
 data () { return {} },
 filters:{
 orderBy (){
 // doSomething
 },
 uppercase () {
 // doSomething
 }
 }
}

但是我们做项目来说,大部分的过滤器是要全局使用的,不会每每用到就在组件里面去写,抽成全局的会更好些。官方注册全局的方式:

// 注册
Vue.filter('my-filter', function (value) {
 // 返回处理后的值
})
// getter,返回已注册的过滤器
var myFilter = Vue.filter('my-filter')

但是分散写的话不美观,因此可以抽出成单独文件。

2.2 优化

我们可以抽出到独立文件,然后使用Object.keys在main.js入口统一注册 /src/common/filters.js

let dateServer = value => value.replace(/(\d{4})(\d{2})(\d{2})/g, '$1-$2-$3') 
export { dateServer }
/src/main.js
import * as custom from './common/filters/custom'
Object.keys(custom).forEach(key => Vue.filter(key, custom[key]))

然后在其他的.vue 文件中就可愉快地使用这些我们定义好的全局过滤器了

<template>
 <section class="content">
 <p>{{ time | dateServer }}</p> <!-- 2016-01-01 -->
 </section>
</template>
<script>
 export default {
 data () {
 return {
 time: 20160101
 }
 }
 }
</script>

3. 全局组件注册

3.1 一般情况

需要使用组件的场景:

<template>
 <BaseInput v-model="searchText" @keydown.enter="search"/>
 <BaseButton @click="search">
 <BaseIcon name="search"/>
 </BaseButton>
</template>
<script>
 import BaseButton from &#39;./baseButton&#39;
 import BaseIcon from &#39;./baseIcon&#39;
 import BaseInput from &#39;./baseInput&#39;
 export default {
 components: { BaseButton, BaseIcon, BaseInput }
 }
</script>

我们写了一堆基础UI组件,然后每次我们需要使用这些组件的时候,都得先import,然后声明components,很繁琐,这里可以使用统一注册的形式

3.2 优化

我们需要借助一下神器webpack,使用 require.context() 方法来创建自己的 模块 上下文,从而实现自动动态require组件。这个方法需要3个参数:要搜索的文件夹目录、是否还应该搜索它的子目录、以及一个匹配文件的正则表达式。 我们在components文件夹添加一个叫componentRegister.js的文件,在这个文件里借助webpack动态将需要的基础组件统统打包进来。 /src/components/componentRegister.js

import Vue from &#39;vue&#39;
/**
 * 首字母大写
 * @param str 字符串
 * @example heheHaha
 * @return {string} HeheHaha
 */
function capitalizeFirstLetter(str) {
 return str.charAt(0).toUpperCase() + str.slice(1)
}
/**
 * 对符合&#39;xx/xx.vue&#39;组件格式的组件取组件名
 * @param str fileName
 * @example abc/bcd/def/basicTable.vue
 * @return {string} BasicTable
 */
function validateFileName(str) {
 return /^\S+\.vue$/.test(str) &&
 str.replace(/^\S+\/(\w+)\.vue$/, (rs, $1) => capitalizeFirstLetter($1))
}
const requireComponent = require.context(&#39;./&#39;, true, /\.vue$/)
// 找到组件文件夹下以.vue命名的文件,如果文件名为index,那么取组件中的name作为注册的组件名
requireComponent.keys().forEach(filePath => {
 const componentConfig = requireComponent(filePath)
 const fileName = validateFileName(filePath)
 const componentName = fileName.toLowerCase() === &#39;index&#39;
 ? capitalizeFirstLetter(componentConfig.default.name)
 : fileName
 Vue.component(componentName, componentConfig.default || componentConfig)
})

这里文件夹结构:

components
│ componentRegister.js
├─BasicTable
│ BasicTable.vue
├─MultiCondition
│ index.vue

这里对组件名做了判断,如果是index的话就取组件中的name属性处理后作为注册组件名,所以最后注册的组件为: multi-condition 、 basic-table 最后我们在main.js中import 'components/componentRegister.js',然后我们就可以随时随地使用这些基础组件,无需手动引入了~

4. 不同路由的组件复用

4.1 场景还原

当某个场景中vue-router从/post-page/a,跳转到/post-page/b。然后我们惊人的发现,页面跳转后数据竟然没更新?!原因是vue-router"智能地"发现这是同一个组件,然后它就决定要复用这个组件,所以你在created函数里写的方法压根就没执行。通常的解决方案是监听$route的变化来初始化数据,如下:

data() {
 return {
 loading: false,
 error: null,
 post: null
 }
},
watch: {
 &#39;$route&#39;: { // 使用watch来监控是否是同一个路由
 handler: &#39;resetData&#39;,
 immediate: true
 }
},
methods: {
 resetData() {
 this.loading = false
 this.error = null
 this.post = null
 this.getPost(this.$route.params.id)
 },
 getPost(id){ }
}

4.2 优化

那要怎么样才能实现这样的效果呢,答案是给 router-view 添加一个不同的key,这样即使是公用组件,只要url变化了,就一定会重新创建这个组件。

<router-view :key="$route.fullpath"></router-view>

还可以在其后加 + +new Date() 时间戳,保证独一无二

5. 高阶组件

5.1 一般情况

// 父组件
<BaseInput :value="value"
  label="密码"
  placeholder="请填写密码"
  @input="handleInput"
  @focus="handleFocus">
</BaseInput>
// 子组件
<template>
 <label>
 {{ label }}
 <input :value=" value"
  :placeholder="placeholder"
  @focus="$emit(&#39;focus&#39;, $event)"
  @input="$emit(&#39;input&#39;, $event.target.value)">
 </label>
</template>

5.2 优化

1 每一个从父组件传到子组件的props,我们都得在子组件的Props中显式的声明才能使用。这样一来,我们的子组件每次都需要申明一大堆props, 而类似placeholer这种dom原生的property我们其实完全可以使用 $attrs 直接从父传到子,无需声明。方法如下:

<input :value="value"
 v-bind="$attrs"
 @input="$emit(&#39;input&#39;, $event.target.value)">

$attrs 包含了父作用域中不作为 prop 被识别 (且获取) 的特性绑定 (class 和 style 除外)。当一个组件没有声明任何 prop 时,这里会包含所有父作用域的绑定,并且可以通过 v-bind="$attrs" 传入内部组件——在创建更高层次的组件时非常有用。

2 注意到子组件的 @focus="$emit('focus', $event)" 其实什么都没做,只是把event传回给父组件而已,那其实和上面类似,完全没必要显式地申明:

<input :value="value"
 v-bind="$attrs"
 v-on="listeners"/>
computed: {
 listeners() {
 return {
 ...this.$listeners,
 input: event =>
 this.$emit(&#39;input&#39;, event.target.value)
 }
 }
}

$listeners 包含了父作用域中的 (不含 .native 修饰器的)v-on 事件监听器。它可以通过 v-on="$listeners" 传入内部组件——在创建更高层次的组件时非常有用。

需要注意的是,由于我们input并不是BaseInput这个组件的根节点,而默认情况下父作用域的不被认作 props 的特性绑定将会“回退”且作为普通的 HTML 特性应用在子组件的根元素上。所以我们需要设置 inheritAttrs: false ,这些默认行为将会被去掉,以上两点的优化才能成功。

6. 路由根据开发状态懒加载

6.1 一般情况

一般我们在路由中加载组件的时候:

import Login from &#39;@/views/login.vue&#39;
export default new Router({
 routes: [{ path: &#39;/login&#39;, name: &#39;登陆&#39;, component: Login}]
})

当你需要懒加载 lazy-loading 的时候,需要一个个把routes的component改为 () => import('@/views/login.vue') ,甚为麻烦。

当你的项目页面越来越多之后,在开发环境之中使用 lazy-loading 会变得不太合适,每次更改代码触发热更新都会变得非常的慢。所以建议只在生成环境之中使用路由懒加载功能。

6.2 优化

根据Vue的异步组件和Webpack的代码分割功能可以轻松实现组件的懒加载,如:

const Foo = () => import('./Foo.vue')

在区分开发环境与生产环境时,可以在路由文件夹下分别新建两个文件: _import_production.js

module.exports = file => () => import('@/views/' + file + '.vue')

_import_development.js ,这种写法 vue-loader 版本至少v13.0.0以上

module.exports = file => require('@/views/' + file + '.vue').default

而在设置路由的 router/index.js 文件中:

const _import = require(&#39;./_import_&#39; + process.env.NODE_ENV)
export default new Router({
 routes: [{ path: &#39;/login&#39;, name: &#39;登陆&#39;, component: _import(&#39;login/index&#39;) }]
})

这样组件在开发环境下就是非懒加载,生产环境下就是懒加载的了

7 vue-loader小技巧

vue-loader 是处理 *.vue 文件的 webpack loader。它本身提供了丰富的 API,有些 API 很实用但很少被人熟知。例如接下来要介绍的 preserveWhitespace 和 transformToRequire

7.1 用 preserveWhitespace 减少文件体积

有些时候我们在写模板时不想让元素和元素之间有空格,可能会写成这样:

<ul>
 <li>1111</li><li>2222</li><li>333</li>
</ul>

当然还有其他方式,比如设置字体的 font-size: 0 ,然后给需要的内容单独设置字体大小,目的是为了去掉元素间的空格。其实我们完全可以通过配置 vue-loader 实现这一需求。

{
 vue: {
 preserveWhitespace: false
 }
}

它的作用是阻止元素间生成空白内容,在 Vue 模板编译后使用 _v(" ") 表示。如果项目中模板内容多的话,它们还是会占用一些文件体积的。例如 Element 配置该属性后,未压缩情况下文件体积减少了近 30Kb。

7.2 使用 transformToRequire 再也不用把图片写成变量了

以前在写 Vue 的时候经常会写到这样的代码:把图片提前 require 传给一个变量再传给组件。

<template>
 <p>
 <avatar :default-src="DEFAULT_AVATAR"></avatar>
 </p>
</template>
<script>
 export default {
 created () {
  this.DEFAULT_AVATAR = require(&#39;./assets/default-avatar.png&#39;)
 }
 }
</script>

其实通过配置 transformToRequire 后,就可以直接配置,这样vue-loader会把对应的属性自动 require 之后传给组件

{
 vue: {
 transformToRequire: {
  avatar: [&#39;default-src&#39;]
 }
 }
}

于是我们代码就可以简化不少

<template>
 <p>
 <avatar default-src="./assets/default-avatar.png"></avatar>
 </p>
</template>

在 vue-cli 的 webpack 模板下,默认配置是:

transformToRequire: {
 video: [&#39;src&#39;, &#39;poster&#39;],
 source: &#39;src&#39;,
 img: &#39;src&#39;,
 image: &#39;xlink:href&#39;
}

可以举一反三进行一下类似的配置

vue-loader 还有很多实用的 API 例如最近加入的自定义块,感兴趣的各位可以去文档里找找看。

8. render 函数

在某些场景下你可能需要render 渲染函数带来的完全编程能力来解决不太容易解决的问题,特别是要动态选择生成标签和组件类型的场景。

8.1 动态标签

1. 一般情况

比如根据props来生成标签的场景

<template>
 <p>
 <p v-if="level === 1"> <slot></slot> </p>
 <p v-else-if="level === 2"> <slot></slot> </p>
 <h1 v-else-if="level === 3"> <slot></slot> </h1>
 <h2 v-else-if="level === 4"> <slot></slot> </h2>
 <strong v-else-if="level === 5"> <slot></slot> </stong>
 <textarea v-else-if="level === 6"> <slot></slot> </textarea>
 </p>
</template>

其中level是data中的变量,可以看到这里有大量重复代码,如果逻辑复杂点,加上一些绑定和判断就更复杂了,这里可以利用 render 函数来对要生成的标签加以判断。

2. 优化

使用 render 方法根据参数来生成对应标签可以避免上面的情况。

<template>
 <p>
 <child :level="level">Hello world!</child>
 </p>
</template>
<script type=&#39;text/javascript&#39;>
 import Vue from &#39;vue&#39;
 Vue.component(&#39;child&#39;, {
 render(h) {
  const tag = [&#39;p&#39;, &#39;p&#39;, &#39;strong&#39;, &#39;h1&#39;, &#39;h2&#39;, &#39;textarea&#39;][this.level]
  return h(tag, this.$slots.default)
 },
 props: {
  level: { type: Number, required: true } 
 }
 }) 
 export default {
 name: &#39;hehe&#39;,
 data() { return { level: 3 } }
 }
</script>

示例可以查看CodePen

8.2 动态组件

当然render函数还有很多用法,比如要使用动态组件,除了使用 :is 之外也可以使用render函数

d477f9ce7bf77f53fbcf36bec1b69b7a
 e388a4556c0f65e1904146cc1a846bee
 c539f51afea997d450c022535c5ec122嘻嘻65281c5ac262bf6d81768915a4a77ac0
 a1f61091e769d76ce4870ac0cbde50b1哈哈65281c5ac262bf6d81768915a4a77ac0
 f32b48428a809b51f04d3228cdf461fa
 662c885b8db0e1c5a6a7a6a1619b2b437d4dd9c7239aac360e401efe89cbb393
 94b3e26ee717c64999d7867364b1b4a3
21c97d3a051048b8e55e3c8f199a54b2
703b3f3513c6d3751d8aea14b7d8b5e3
 import Vue from 'vue'
 import Xixi from './Xixi'
 import Haha from './Haha'
 
 Vue.component('child', {
 render(h) {
  const tag = ['xixi', 'haha'][this.level]
  return h(tag, this.$slots.default)
 },
 props: { level: { type: Number, required: true } },
 components: { Xixi, Haha }
 })
 
 export default {
 name: 'hehe',
 data() { return { level: 0 } }
 }
2cacc6d41bbb37262a98f745aa00fbf0

相信看了本文案例你已经掌握了方法,更多精彩请关注php中文网其它相关文章!

推荐阅读:

JS实现微信红包随机算法(附代码)

vue判断dom内class使用情况

以上是Vue使用技巧总结的详细内容。更多信息请关注PHP中文网其他相关文章!

声明
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn
JavaScript的角色:使网络交互和动态JavaScript的角色:使网络交互和动态Apr 24, 2025 am 12:12 AM

JavaScript是现代网站的核心,因为它增强了网页的交互性和动态性。1)它允许在不刷新页面的情况下改变内容,2)通过DOMAPI操作网页,3)支持复杂的交互效果如动画和拖放,4)优化性能和最佳实践提高用户体验。

C和JavaScript:连接解释C和JavaScript:连接解释Apr 23, 2025 am 12:07 AM

C 和JavaScript通过WebAssembly实现互操作性。1)C 代码编译成WebAssembly模块,引入到JavaScript环境中,增强计算能力。2)在游戏开发中,C 处理物理引擎和图形渲染,JavaScript负责游戏逻辑和用户界面。

从网站到应用程序:JavaScript的不同应用从网站到应用程序:JavaScript的不同应用Apr 22, 2025 am 12:02 AM

JavaScript在网站、移动应用、桌面应用和服务器端编程中均有广泛应用。1)在网站开发中,JavaScript与HTML、CSS一起操作DOM,实现动态效果,并支持如jQuery、React等框架。2)通过ReactNative和Ionic,JavaScript用于开发跨平台移动应用。3)Electron框架使JavaScript能构建桌面应用。4)Node.js让JavaScript在服务器端运行,支持高并发请求。

Python vs. JavaScript:比较用例和应用程序Python vs. JavaScript:比较用例和应用程序Apr 21, 2025 am 12:01 AM

Python更适合数据科学和自动化,JavaScript更适合前端和全栈开发。1.Python在数据科学和机器学习中表现出色,使用NumPy、Pandas等库进行数据处理和建模。2.Python在自动化和脚本编写方面简洁高效。3.JavaScript在前端开发中不可或缺,用于构建动态网页和单页面应用。4.JavaScript通过Node.js在后端开发中发挥作用,支持全栈开发。

C/C在JavaScript口译员和编译器中的作用C/C在JavaScript口译员和编译器中的作用Apr 20, 2025 am 12:01 AM

C和C 在JavaScript引擎中扮演了至关重要的角色,主要用于实现解释器和JIT编译器。 1)C 用于解析JavaScript源码并生成抽象语法树。 2)C 负责生成和执行字节码。 3)C 实现JIT编译器,在运行时优化和编译热点代码,显着提高JavaScript的执行效率。

JavaScript在行动中:现实世界中的示例和项目JavaScript在行动中:现实世界中的示例和项目Apr 19, 2025 am 12:13 AM

JavaScript在现实世界中的应用包括前端和后端开发。1)通过构建TODO列表应用展示前端应用,涉及DOM操作和事件处理。2)通过Node.js和Express构建RESTfulAPI展示后端应用。

JavaScript和Web:核心功能和用例JavaScript和Web:核心功能和用例Apr 18, 2025 am 12:19 AM

JavaScript在Web开发中的主要用途包括客户端交互、表单验证和异步通信。1)通过DOM操作实现动态内容更新和用户交互;2)在用户提交数据前进行客户端验证,提高用户体验;3)通过AJAX技术实现与服务器的无刷新通信。

了解JavaScript引擎:实施详细信息了解JavaScript引擎:实施详细信息Apr 17, 2025 am 12:05 AM

理解JavaScript引擎内部工作原理对开发者重要,因为它能帮助编写更高效的代码并理解性能瓶颈和优化策略。1)引擎的工作流程包括解析、编译和执行三个阶段;2)执行过程中,引擎会进行动态优化,如内联缓存和隐藏类;3)最佳实践包括避免全局变量、优化循环、使用const和let,以及避免过度使用闭包。

See all articles

热AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智能驱动的应用程序,用于创建逼真的裸体照片

AI Clothes Remover

AI Clothes Remover

用于从照片中去除衣服的在线人工智能工具。

Undress AI Tool

Undress AI Tool

免费脱衣服图片

Clothoff.io

Clothoff.io

AI脱衣机

Video Face Swap

Video Face Swap

使用我们完全免费的人工智能换脸工具轻松在任何视频中换脸!

热工具

螳螂BT

螳螂BT

Mantis是一个易于部署的基于Web的缺陷跟踪工具,用于帮助产品缺陷跟踪。它需要PHP、MySQL和一个Web服务器。请查看我们的演示和托管服务。

EditPlus 中文破解版

EditPlus 中文破解版

体积小,语法高亮,不支持代码提示功能

ZendStudio 13.5.1 Mac

ZendStudio 13.5.1 Mac

功能强大的PHP集成开发环境

安全考试浏览器

安全考试浏览器

Safe Exam Browser是一个安全的浏览器环境,用于安全地进行在线考试。该软件将任何计算机变成一个安全的工作站。它控制对任何实用工具的访问,并防止学生使用未经授权的资源。

SublimeText3 Mac版

SublimeText3 Mac版

神级代码编辑软件(SublimeText3)