简述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 相关文章推荐
JavaScript日期时间格式化函数分享
May 05 Javascript
JS实现可展开折叠层的鼠标拖曳效果
Oct 09 Javascript
AngularJS自定义指令实现面包屑功能完整实例
May 17 Javascript
Vue组件库发布到npm详解
Feb 17 Javascript
Element-UI Table组件上添加列拖拽效果实现方法
Apr 14 Javascript
react native 原生模块桥接的简单说明小结
Feb 26 Javascript
详解微信小程序开发用户授权登陆
Apr 24 Javascript
egg.js的基本使用和调用数据库的方法示例
May 18 Javascript
echarts.js 动态生成多个图表 使用vue封装组件操作
Jul 19 Javascript
在vue中使用防抖函数组件操作
Jul 26 Javascript
微信小程序入门之指南针
Oct 22 Javascript
node.js如何操作MySQL数据库
Oct 29 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
国王的咖啡这么大来头,名字的由来是什么
2021/03/03 咖啡文化
Apache环境下PHP利用HTTP缓存协议原理解析及应用分析
2010/02/16 PHP
PHP加密解密字符串汇总
2015/04/26 PHP
php基于Fleaphp框架实现cvs数据导入MySQL的方法
2016/02/23 PHP
PHP实现活动人选抽奖功能
2017/04/19 PHP
PHP与Web页面的交互示例详解一
2020/08/04 PHP
jQuery UI Dialog控件中的表单无法正常提交的解决方法
2010/12/19 Javascript
你必须知道的JavaScript 变量命名规则详解
2013/05/07 Javascript
jQuery实现的个性化返回底部与返回顶部特效代码
2015/10/30 Javascript
JavaScript实现ASC转汉字及汉字转ASC的方法
2016/01/23 Javascript
基于javascript html5实现3D翻书特效
2016/03/14 Javascript
JS基于面向对象实现的拖拽功能示例
2016/12/20 Javascript
微信小程序技巧之show内容展示,上传文件编码问题
2017/01/23 Javascript
浅谈Node.js CVE-2017-14849 漏洞分析(详细步骤)
2017/11/10 Javascript
vue+swiper实现侧滑菜单效果
2017/12/28 Javascript
详解React native fetch遇到的坑
2018/08/30 Javascript
Web安全之XSS攻击与防御小结
2018/12/13 Javascript
vue封装一个简单的div框选时间的组件的方法
2019/01/06 Javascript
微信小程序学习总结(一)项目创建与目录结构分析
2020/06/04 Javascript
vue 保留两位小数 不能直接用toFixed(2) 的解决
2020/08/07 Javascript
[53:23]Secret vs Liquid 2018国际邀请赛淘汰赛BO3 第二场 8.25
2018/08/29 DOTA
python错误:AttributeError: 'module' object has no attribute 'setdefaultencoding'问题的解决方法
2014/08/22 Python
python修改操作系统时间的方法
2015/05/18 Python
详解django三种文件下载方式
2018/04/06 Python
django Serializer序列化使用方法详解
2018/10/16 Python
Python实现获取汉字偏旁部首的方法示例【测试可用】
2018/12/18 Python
jupyter lab文件导出/下载方式
2020/04/22 Python
学习Python需要哪些工具
2020/09/04 Python
基于CSS3实现的漂亮Menu菜单效果代码
2015/09/10 HTML / CSS
用CSS3的box-reflect来制作倒影效果
2016/11/15 HTML / CSS
简单的大学生自我鉴定
2014/02/18 职场文书
今冬明春火灾防控工作方案
2014/05/29 职场文书
医学专业大学生求职信
2014/07/12 职场文书
英语课外活动总结
2014/08/27 职场文书
python opencv人脸识别考勤系统的完整源码
2021/04/26 Python
python实现黄金分割法的示例代码
2021/04/28 Python