简述Vue中容易被忽视的知识点


Posted in Javascript onDecember 09, 2019

前言

Vue的学习成本和难度不高,这除了和框架本身的设计理念有关之外,还和Vue完善的官方文档有着密不可分的关系,相信有很多的开发者和我一样,很长时间没有仔细去看过官方文档了,最近花时间仔细看了一下官方文档,将里面一些容易忽视的点整理出来和大家分享。

容易忽视的点

箭头函数的使用

ES6的普及使得箭头函数的使用更加频繁,但是在Vue中不要在选项属性或者回调上使用箭头函数,举个例子:

new Vue({
 el: '#app',
 data: {
  show: true
 },
 created: () => {
  console.log(this.show)
 },
})

将created钩子写成箭头函数,这里的this将不再指向Vue对象,在浏览器中将会指向window对象,这是因为箭头函数并没有this,this会作为变量一直向上级词法作用域查找,直到找到为止

指令动态参数

Vue从2.6.0开始,可以用方括号括起来的JavaScript表达式作为一个指令参数,举个例子:

<div id="app">
 <input v-on:[event] = "doSomething">
 <button v-on:click="event = 'focus'">change</button>
</div>
new Vue({
 el: '#app',
 data() {
  return {
   event: 'input'
  }
 },
 methods: {
  doSomething () {
   console.log('sss')
  }
 },
})

这里将input的事件监听设置为一个动态的参数event,默认是监听点击事件,当点击change的时候,改为监听focus事件,动态参数预期会求出一个字符串,异常情况下值为null,null值可以用于移除绑定,任何其他非字符串类型的值都会触发一个警告

template中使用方法

methods中提供的方法大多数时候都是用来给其他方法调用的,但是它其实也可以像computed计算属性一样直接写在模版里,举个例子:

<div id="app">{{reversedMessage('hello')}}</div>
var app = new Vue({
 el: '#app',
 methods: {
  reversedMessage: function (message) {
   return message.split('').reverse().join('')
  }
 },
})

有了computed计算属性,为什么还要用methods呢?计算属性是基于响应式依赖进行缓存的,只在相关依赖发生改变时才会重新求值,而methods每次调用都会重新计算,调用methods时可以传参,进行指定计算,但是computed不行,这在遍历数组时十分有用

用key管理可复用元素

Vue会尽可能高效地渲染元素,通常会复用已有元素而不是从头开始渲染。这么做会使 Vue变得非常快,举个例子:

<div id="app">
  <template v-if="loginType === 'username'">
   <label>Username</label>
   <input placeholder="Enter your username">
  </template>
  <template v-else>
   <label>Email</label>
   <input placeholder="Enter your email address">
  </template>
  <button @click="change">change</button>
</div>
var app = new Vue({
 el: '#app',
 data() {
  return {
   loginType: 'username'
  }
 },
 methods: {
  change () {
   this.loginType = this.loginType === 'username' ? 'email' : 'username'
  }
 }
})

上面代码中切换loginType将不会清除用户已经输入的内容,因为两个模版使用了相同的元素,如果不想复用也很简单,只需要添加一个具有唯一值的key属性即可:

<template v-if="loginType === 'username'">
 <label>Username</label>
 <input key="username" placeholder="Enter your username">
</template>
<template v-else>
 <label>Email</label>
 <input key="email" placeholder="Enter your email address">
</template>
<button @click="change">change</button>

现在切换,每次都会重新渲染,但是label元素还是会被复用,因为它没有加唯一key值

v-if与v-for一起使用

Vue的风格指南不推荐同时使用v-if与v-for,当项目中的eslint继承了@vue/standard时,同时使用就会编译报错,但是可以通过在模版上加<!-- eslint-disable -->进行忽略,同时当它们处于同一节点,v-for的优先级比v-if更高,这意味着v-if 将分别重复运行于每个v-for循环中

对象变更检测

在Vue中对于已经创建的实例,不允许动态添加根级别的响应式属性,但是我们知道可以通过Vue.set(object, propertyName, value)方法向嵌套对象添加响应式属性,那如果需要为已有对象赋值多个新属性呢?举个例子:

<div id="app">{{user.name}}-{{user.age}}-{{user.sex}}</div>
var app = new Vue({
 el: '#app',
 data() {
  return {
   user: {
    name: 'xxx'
   }
  }
 },
 created() {
  this.user = Object.assign({}, this.user, {
   age: 18,
   sex: 'name'
  })
 },
})

可以用Object.assign为这个对象重新赋值,这样就能添加多个新的响应式属性

内联方法访问原始DOM事件

有时在模版中调用方法时,我们需要向方法中传参数,但是同时又要传递原始的DOM事件,怎么处理呢?举个例子:

<div id="app">
 <button @click="share('share info', $event)">share</button>
</div>
var app = new Vue({
 el: '#app',
 data() {
  return {
   user: {
    name: 'xxx'
   }
  }
 },
 methods: {
  share (info, event) {
   console.log(info, event)
  }
 },
})

如例子所示,可以用特殊变量$event把它传入方法

once、passive事件修饰符

Vue中提供了多个事件修饰符, once、passive是后面新增的两个,once用于限定事件只触发一次,passive用于修饰的事件发生后立即触发,用于提升移动端性能

表单输入修饰符

.lazy

在默认情况下,v-model在每次input事件触发后将输入框的值与数据进行同步,可以添加lazy修饰符,从而转变为使用change事件进行同步,举个例子:

<input placeholder="lazy" v-model.lazy="msg" @input="input" @change="change">

.number

如果想自动将用户的输入值转为数值类型,可以给v-model添加number修饰符,这通常很有用,因为即使在type="number"时,HTML输入元素的值也总会返回字符串。如果这个值无法被 parseFloat()解析,则会返回原始的值,举个例子:

<input placeholder="number" v-model.number="age" @input="input">

.trim

如果要自动过滤用户输入的首尾空白字符,可以给v-model添加trim修饰符,举个例子:

<input placeholder="trim" v-model.trim="trim" @input="input">

子组件替换/合并已有的特性

在Vue中对于绝大多数特性来说,从外部提供给组件的值会替换掉组件内部设置好的值。所以如果传入type="text"就会替换掉 type="date"并把它破坏!庆幸的是,class和 style特性会稍微智能一些,即两边的值会被合并起来,从而得到最终的值,举个例子:

<div id="app">
 <base-input type="text" class="out"></base-input>
</div>
Vue.component('base-input', {
 template: `<input type="date" placeholder="replace" class="default">`
})
new Vue({
 el: '#app',
})

在上例中input的type值为date,class为deafault,在使用子组件时,向子组件中传入type="text" class="out",此时input的type值会被替换为text,class值会被合并为"default out",那么如果想要禁用属性继承怎么办呢?可以在组件的选项中设置inheritAttrs:false,举个例子:

Vue.component('base-input', {
 inheritAttrs: false,
 template: `<input type="date" placeholder="replace" class="default">`
})

但是inheritAttrs:false选项不会影响style和class的绑定,因此style和class还是会合并

.sync修饰符

在有些情况下,可能需要对一个 prop进行“双向绑定”。不幸的是,真正的双向绑定会带来维护上的问题,因为子组件可以修改父组件,且在父组件和子组件都没有明显的改动来源,因此Vue提供了sync修饰符,举个例子:

<div id="app">
 <span>{{title}}</span>
 <text-document v-bind:title.sync="title"></text-document>
</div>
Vue.component('text-document', {
 props: ['title'],
 template: `<button @click="change">change</button>`,
 methods: {
  change () {
   this.$emit('update:title', 'change')
  }
 },
})
new Vue({
 el: '#app',
 data() {
  return {
   title: 'default'
  }
 }
})

当调用this.$emit('update:title', 'change'),父组件中的title就会改变

总结

这篇文章对Vue中一些容易忽视的点进行了简单的总结,希望看完之后能对大家有所帮助。也希望大家多多支持三水点靠木。

Javascript 相关文章推荐
提高代码性能技巧谈—以创建千行表格为例
Jul 01 Javascript
JS 参数传递的实际应用代码分析
Sep 13 Javascript
appendChild() 或 insertBefore()使用与区别介绍
Oct 11 Javascript
利用CSS、JavaScript及Ajax实现高效的图片预加载
Oct 16 Javascript
jquery 操作两个select实现值之间的互相传递
Mar 07 Javascript
javascript 回调函数详解
Nov 11 Javascript
谈谈因Vue.js引发关于getter和setter的思考
Dec 02 Javascript
BootStrap学习笔记之nav导航栏和面包屑导航
Jan 03 Javascript
bootstrap multiselect 多选功能实现方法
Jun 05 Javascript
详解Angular5 服务端渲染实战
Jan 04 Javascript
浅谈Vue下使用百度地图的简易方法
Mar 23 Javascript
JavaScript修改注册表实例代码
Jan 05 Javascript
vue路由传参三种基本方式详解
Dec 09 #Javascript
vue使用nprogress实现进度条
Dec 09 #Javascript
javascript数组元素删除方法delete和splice解析
Dec 09 #Javascript
vue vant Area组件使用详解
Dec 09 #Javascript
JS中的模糊查询功能
Dec 08 #Javascript
详解一些适用于Node.js的命名约定
Dec 08 #Javascript
微信域名检测接口调用演示步骤(含PHP、Python)
Dec 08 #Javascript
You might like
php数字转汉字代码(算法)
2011/10/08 PHP
克隆一个新项目的快捷方式
2013/04/10 PHP
在JQuery dialog里的服务器控件 事件失效问题
2010/12/08 Javascript
面向对象的Javascript之一(初识Javascript)
2012/01/20 Javascript
JavaScript闭包实例讲解
2014/04/22 Javascript
IE6-IE9中tbody的innerHTML不能赋值的解决方法
2014/06/05 Javascript
jQuery中next()方法用法实例
2015/01/07 Javascript
结合代码图文讲解JavaScript中的作用域与作用域链
2016/07/05 Javascript
预防网页挂马的方法总结
2016/11/03 Javascript
assert()函数用法总结(推荐)
2017/01/25 Javascript
微信小程序 设置启动页面的两种方法
2017/03/09 Javascript
Vue2 配置 Axios api 接口调用文件的方法
2017/11/13 Javascript
微信小程序开发之改变data中数组或对象的某一属性值
2018/07/05 Javascript
基于Three.js实现360度全景图片
2018/12/30 Javascript
巧妙运用v-model实现父子组件传值的方法示例
2019/04/07 Javascript
JavaScript实现浏览器网页自动滚动并点击的示例代码
2020/12/05 Javascript
[01:09:13]DOTA2-DPC中国联赛 正赛 CDEC vs XG BO3 第三场 1月19日
2021/03/11 DOTA
django实现分页的方法
2015/05/26 Python
Python数据类型详解(一)字符串
2016/05/08 Python
python中matplotlib实现最小二乘法拟合的过程详解
2017/07/11 Python
python实现堆和索引堆的代码示例
2018/03/19 Python
对python3 一组数值的归一化处理方法详解
2018/07/11 Python
Python查找最长不包含重复字符的子字符串算法示例
2019/02/13 Python
搞清楚 Python traceback的具体使用方法
2019/05/13 Python
python粘包问题及socket套接字编程详解
2019/06/29 Python
tensorflow -gpu安装方法(不用自己装cuda,cdnn)
2020/01/20 Python
Python类型转换的魔术方法详解
2020/12/23 Python
详解Python中openpyxl模块基本用法
2021/02/23 Python
美国高端婴童品牌:Hanna Andersson
2016/10/30 全球购物
全球在线商店:BerryLook
2019/04/14 全球购物
工艺员岗位职责
2014/02/11 职场文书
四风个人对照检查材料思想汇报
2014/09/25 职场文书
大学生暑期社会实践证明范本
2014/10/24 职场文书
2015年社区流动人口工作总结
2015/05/12 职场文书
新闻稿件写作技巧
2015/07/18 职场文书
分布式锁为什么要选择Zookeeper而不是Redis?看完这篇你就明白了
2021/05/21 Redis