Vue 2 难点汇总
数据侦听 Vue.$watch
watch提供了观察和响应实例上数据变动的办法,当有一些数据需要跟随其他数据变化而变化时,如子组件某个数据依赖来自于父组件的prop计算。很直观的会想到计算这功能和计算属性十分类似。Vue建议用户使用计算属性,除非如下情况:
(1)当要执行的操作是异步操作时,
(2)相应事件是开销较大的操作时。
watch: {
axios.get('https://yesno.wtf/api')
.then(function (response) {
vm.answer = _.capitalize(response.data.answer)
})
.catch(function (error) {
vm.answer = 'Error! Could not reach the API. ' + error
})
}
}
}
当观察的值发生改变时, 观察者会接收到两个参数:(1) 新值,(2)原先的值。 值得注意的是, watch在组件第一次被挂载时不会触发, 只有值被改变时才触发。
watch: {
}
}
data选项为什么是一个函数?
Vue官网第一课描述的data选项就是一个对象,为什么在编写组件的时候却要定义成一个函数?
我们知道对象是引用类型,而组件最大的特性就是可复用性,当一个组件被多次复用却指向同一个引用类型数据,组件间将无独立性而言。因此,将data选项定义成一个函数,是为了利用函数的私有作用域特性实现不同组件间数据私有的效果
计算属性缓存 及 劫持setter
一个需要计算的数据,通常有: (1)计算属性获取,(2)定义一个方法实现。虽然实现结果相同,但前者优势在于计算属性是基于它们的依赖进行缓存的。也就是说:
(1)计算属性依赖不改变,计算就不会触发,改变了才重新触发计算;而调用方法总会再次执行函数
(2)当依赖不是响应式依赖时, 计算属性将永远不会触发计算。如
computed: {
}
}
计算属性默认只有 getter,常规用法其实是调用了计算属性的getter方法。若在需要时也可以提供一个setter,此时, 需要将计算属性定义为一个对象,setter的含义与原生JS的类似
computed: {
return this.val
},
set (newVal) { // setter
return newVal.split('').reverse().join('')
}
}
}
v-if 惰性、缓存 及 使用 <template>
我们知道,v-if能决定DOM结构存不存在,而v-show只是控制了DOM元素的display属性,当页面切换频率不高时,Vue建议使用v-if。
所谓的惰性,就是当遇到条件为非真时直接跳过,只有第一次遇到真值才开始渲染条件块。
而缓存,官网给出解释如下:
Vue 会尽可能高效地渲染元素,通常会复用已有元素而不是从头开始渲染。
也就是说,假设页面原本渲染了一个input标签,而状态改变后也有一个input标签,Vue检查到新老标签标签名和属性列表都相同。将保留已渲染的标签继续使用。
这种缓存机制是Vue默认的,想修改这种动作,只要给标签加上具有唯一值的key属性即可,
<input placeholder="Enter your username" key="username-input">
正常情况下,v-if会被设置在一个标签元素内使用,当遇到前后两个或多个兄弟标签都需要使用相同状态值来判断是否渲染时,可以一个无状态不可见标签<template>来包裹,Vue在构建DOM时会将其丢弃,并正确的将v-if作用到相应的标签上。
<template v-if="real">
</template>
v-if 与 v-for 优先级
根据Vue的风格指南,不建议将v-if和v-for放在一起使用,我们来探索一下为什么.
它们一起使用的场景无非就有两个
(1)希望通过v-if控制v-for代码块是否显示。这种情况下一般v-if变量是个状态量,与v-for循环变量无关。
(2)希望通过循环变量中的某个属性的真假值,来控制该项是否应该被循环渲染出来
这两种用法有什么问题?在Vue语法中有个规则:循环体中,v-for属性优先级高于其他属性。也就是说:
场景(1): v-if的渲染会发生在循环之后,列表优先生成,这就无法提前阻止循环列表的渲染。这与我们初衷想要决定循环块是否渲染产生冲突。解决办法是:使用<template>标签包裹并在这里设置v-if控制
场景(2): 如果存在不该被渲染的项,这个项就不应该出现在循环变量中,Vue建议使用计算属性过滤数组。因此也不再需要v-if
v-for 作用于对象
循环不止作用于数组,同样可作用于所有可迭代类型变量中。
在遍历对象时,通常是按 Object.keys() 的结果遍历,但是不能保证它的结果在不同的 JavaScript 引擎下是一致的。
</div>
v-for渲染后的数组缓存替换规则
Vue 包含一组观察数组的变异方法(mutation method),它们会触发视图更新。包括: push()、pop()、shift()、unshift()、splice()、sort()、reserve()等。这些方法都会改变原数组。
同样还包含非变异方法,如filter()、concat()、slice()。他们不改变原数组,而是返回一个新数组。
如果我们对已渲染过后的数组进行非变异方法操作,直觉上列表会重新渲染,其实不然。
Vue 为了使得 DOM 元素得到最大范围的重用而实现了一些智能的、启发式的方法,所以用一个含有相同元素的数组去替换原来的数组是非常高效的操作。
exa.items = exa.items.filter(function (item) {
冻结双向数据绑定
如果初始渲染后不想让视图层响应模型层变化, 可以使用v-once标签属性, 告知被包含在该标签内部的所有数据绑定不要响应视图更新
<span v-once>这个数据不会发生改变: {{ message }}</span>
绑定一段 HTML
Vue在html部分, 无论是利用双大括号{{ }}还是v-model绑定的值都会被解释为普通文本。如果需要绑定一段 HTML,可以使用v-html
<p v-html="htmlCode"></p>
修饰符
(1) .prevent / .stop / .passive
如果你遇到过在页面执行一个Click事件,触发了两次函数调用,你则需要检查一下是否由事件冒泡引起的。 在DOM2级, DOM3级事件标准中, 浏览器接受一个点击交互后, 产生事件流会有两个过程,捕获和冒泡。 过程如下:

为解决该问题,Vue提供了修饰符.prevent 可以告诉v-on指令对于触发的事件调用event.preventDefault() 来阻止浏览器的默认行为。 .stop则是调用event.stopPropagation() 来阻止目标元素的冒泡事件
.passive不能和.prevent一同使用,它会屏蔽.prevent的冒泡效果。.passive主要使用在移动端,它能提高其性能
(2)键盘修饰符 .enter / .tab / .delete ...
Vue提供监听键盘按键键值的办法,方便我们监听键盘事件。一般情况下,直接使用键值修饰,如enter键的键值为13,则使用办法为:
<input @click.13="handleClick"></input>
Vue为方便记忆,绑定了常用键名与键值的关系可直接使用键名绑定
<input @click.enter="handleClick"></input>
常用的有:.enter,.tab,.delete,.esc,.space,.up,.down,.left,.right也可以用通过config.keyCodes 对象自定义按键修饰符别名:
// 可以使用 `v-on:keyup.f1`
(3)鼠标修饰符
鼠标修饰符限制处理函数仅响应特定的鼠标按钮,包括.left,.right,.middle。
动态样式绑定 :class
Vue允许动态切换一个样式, 支持两种语法: 对象形式 | 数组形式
- 对象办法:键表示样式类名,值为 Truthy 表示添加该样式
<div class="wrap" :class="{ borderTop: boolean, active: isActive }"></div>
(2)给:class传递一个数组,表示应用一组样式
<div :class="[ classA, classB ]"></div>
当
v-bind:style使用需要添加浏览器引擎前缀的 CSS 属性时,如transform,Vue.js 会自动侦测并添加相应的前缀。
事件绑定传参
如下,前者使用监听事件,而后者是内联处理器
<div id="example">
</div>
表单输入绑定
对于普通元素如<div> {{ message }} </div>等并没有真正表现出Vue双向数据绑定的魅力,其只展现了从ViewModel层发生变化后反馈到View层的单方面特性。而表单输入的双向数据绑定还增加了用户交互使得View层发生改变并响应到ViewModel层,真正体现了“双向”功能。
v-model可以在表单元素<input>, <textarea>及<select>上创建双向数据绑定。Vue会根据空间类型自动选取正确的方法更新元素。值得注意的是,v-model会忽略所有表单元素的value, chekcd, selected特性的初始值而总是将Vue实例的数据data选项作为数据来源。也就是说,不能通过特性自身赋值绑定到v-model上,而需要在data中手动赋初始值
- 对于单行多行输入框,经
v-model绑定过后的元素中增加内容不会生效,Vue只读绑定中的内容。 - 单个复选框,
v-model绑定到布尔值;而多个复选框则绑定到同一个数组 - 单选按钮,绑定到同一个字符串,其值是
value所对应的值 - 下拉选择菜单,单选时绑定到一个值上,多选时绑定到一个数组
# 单选下拉框去掉 multiple属性即可
{{ opt .text }}
</option>
</select>
<span>Array: {{ selected }}</span>
表单绑定修饰符
- .lazy:将
input触发的更新延迟至change触发
<input v-model.lazy="msg" >
- .number:将用户输入的内容转化为数字,否则总是返回字符串。设置
type属性移动端可以调起数字键盘。如果这个值无法被parseFloat()解析,则会返回原始的值
<input v-model.number="age" type="number">
- .trim:自动过滤用户输入的首尾空白字符
<input v-model.trim="msg">
Vue.$emit参数,及与 v-on 事件命名规范
在刚开始开发时可能会思考为什么prop没有子向父传递。不幸运的是,prop的逆向会给数据流向带来巨大的维护和理解困难,这也是为什么Vue封装了$emit的模式 触发事件来取而代之的原因
this.$emit('method-name', param)
第一个参数是抛出的事件名,对应父级v-on事件名,第二个参数是要带出的数据,该数据使用$event捕获
<Children @click="$emit('enlarge-text', 0.1)"> Enlarge text </Children >
<blog @enlarge-text="postFontSize += $event"></blog>
通常父组件中会绑定给一个属性,该属性定义为一个方法且它的第一个参数就是被带出来的数据
enlargeText (num) {
this.postFontSize += num
}
【注意】不同于组件和prop,经$emit抛出的事件名不会被用作一个JavaScript变量 名或属性名,所以就没有理由使用camelCase(驼峰式)或PascalCase(短线式)。因为HTML大小写不明感因素,v-on事件监听器在DOM模板中实质上会被自动转换为全小写,所以驼峰式命名规则将全部失效无法监听。建议使用短线式或全小写,特别是前者
<my-component v-on:my-event="handleEmit"></my-component> // 禁止使用myEvent
动态组件
比如我们有一个tab栏,其中有三个tab页,点击不同tab页需切换至不同的组件下,此时非常适合使用is来指定不同的组件达到动态组件效果,如下
Vue.component('tab-home', {
...
new Vue({
el: '#demo',
data: {
currentTab: 'Home',
tabs: ['Home', 'Posts', 'Archive']
},
computed: {
currentTabComponent () {
return 'tab-' + this.currentTab.toLowerCase()
}
}
})
<component :is="currentTabComponent"></component>
Prop传递数据防脏
所有的 prop都使得其父子组件形成一个单向下行绑定,父级prop的更新会流动到子组件中,但反过来不行。这种设计办法是为了防止子组件意外改变父组件的状态,从而导致你的应用的数据流向难以理解。另外,如果该数据还被其他子组件使用,也将受影响,产生洪水式灾难。因此不应该在子组件中设计修改prop数据的操作。
在Javascript中对象和数组都是通过引用传入的,因此对于引用类型的prop来说,在子组件中修改数据本身将直接改变父级的数据。
常见的试图改变prop的操作有一下两种情形:
- 接收的
prop作为一个初始值,这个子组件接下来希望将其作为一个本地的prop数据来使用。这种情况下应该使用子组件中的data来拷贝一份prop数据数据
prop: [ 'initialNum' ],
num: this.initialNum
}
}
接收的prop作为原始的值需要进行格式转换。这种情况下,应该使用计算属性来实现
props: ['size'],
当不需要对prop做改变只是进行使用时可以不用data拷贝,但也需要注意使用,曾经遇到将 == 写成 =,花了不少时间找bug。当系统比较庞大时这种问题不好找,所以大家一定要细心实在不行就多做个data拷贝。
prop自定义检查函数
Vue允许在进行prop传值时对值进行验证,type可以验证数据类型,default可以设置当未传入时的默认值。除此之外,还允许开发者们自定义验证函数
function CheckName (firstName, lastName) {
}
验证办法如下
prop: {
Prop与自身属性重名问题
当使用ElementUI或Bootstrap这些第三方插件时,往往他们定义有自己的属性,如果开发者们自定义的prop属性与其发生重名时,Vue在大多数情况下,从外部提供给组件的值会替换掉组件内部设置好的值。
即假设存在传入type="text" 就会替换掉本身type="date" 类型,原来的就会被破坏。庆幸的是, class和style会智能一些,即两边的值会合并起来
Prop实现‘双向绑定’效果 .sync修饰符
Vue不是不建议子组件改变父组件属性吗?为什么还要给prop做"双向绑定"?我第一想法就是这样的。
其实他只是作为一种语法糖存在,并且具有可替代办法。他的应用场景就是:prop的值如果需要根据子组件的操作响应修改,则可以使用该语法糖
Vue 2 难点汇总的更多相关文章
- Vue 相关难点汇总
1. 父子组件的双向数据绑定,所以在子组件是不允许修改父组件的属性的. // 解决办法 // 在子组件data中定义一个父组件传递过来的副本,再把该副本利用this.$emit("" ...
- Vue开源项目库汇总
最近做了一个Vue开源项目库汇总,里面集合了OpenDigg 上的优质的Vue开源项目库,方便移动开发人员便捷的找到自己需要的项目工具等,感兴趣的可以到GitHub上给个star. UI组件 elem ...
- Vue 开源项目库汇总(转)
最近做了一个Vue开源项目库汇总,里面集合了OpenDigg 上的优质的Vue开源项目库,方便移动开发人员便捷的找到自己需要的项目工具等,感兴趣的可以到GitHub上给个star.https://gi ...
- Vue 面试题汇总
Vue 面试题汇总 refs xgqfrms 2012-2020 www.cnblogs.com 发布文章使用:只允许注册用户才可以访问!
- vue插件大全汇总
Vue是一个构建数据驱动的 web 界面的渐进式框架.Vue.js 的目标是通过尽可能简单的 API 实现响应的数据绑定和组合的视图组件特别整理了常用的vue插件,来了个大汇总,方便查找使用,便于工作 ...
- vue常用插件汇总
UI-框架element - 饿了么出品的Vue2的web UI工具套件 mint-ui - Vue 2的移动UI元素 iview - 基于 Vuejs 的开源 UI 组件库 Keen-UI - 轻量 ...
- 实用的vue插件大汇总
Vue是一个构建数据驱动的 web 界面的渐进式框架.Vue.js 的目标是通过尽可能简单的 API 实现响应的数据绑定和组合的视图组件特别整理了常用的vue插件,来了个大汇总,方便查找使用,便于工作 ...
- vue cli 常见问题汇总
以下是本人在用vue cli 开发项目里遇到的最基本的问题及解决方案汇总.没啥很多技术性的东西,各位看个乐呵就行~ 1.vue-cli 创建的项目各文件夹的含义 注意:通过vue-cli 4 创建的项 ...
- vue各种插件汇总
https://blog.csdn.net/wh8_2011/article/details/80497620(copy) Vue是什么? Vue.js(读音 /vjuː/, 类似于 view) 是一 ...
随机推荐
- golang 命令行参数
package main import ( "fmt" "flag" ) func main() { //定义几个变量,用于接收命令行的参数值 var user ...
- 找不到windows.h源文件
一.找不到源文件window.h 今天在网上下了个程序,在公司用VS2015能打开,在家用VS2017却打不开,提示找不到源文件window.h,因为引用了这个头文件,但是却找不到 解决方案: 右侧解 ...
- 地不安装Oracle,plsql远程连接数据库
由于Oracle的庞大,有时候我们需要在只安装Oracle客户端如plsql.toad等的情况下去连接远程数据库,可是没有安装Oracle就没有一切的配置文件去支持.最后终于发现一个很有效的方法,Or ...
- 调试R代码中出现的常用的函数
1. 字符串连接函数 paste的一般使用格式为: paste(..., sep = " ", collapse = NULL) ...表示一个或多个R可以被转化为字符型的对象:s ...
- pytest相关资源收集
pytest官网 https://docs.pytest.org/en/latest/getting-started.html 官网推荐的plugin https://docs.pytest.org/ ...
- KDD2015,Accepted Papers
Accepted Papers by Session Research Session RT01: Social and Graphs 1Tuesday 10:20 am–12:00 pm | Lev ...
- 二.使用JDBC对数据库CRUD
一.statement对象介绍 Jdbc中的statement对象用于向数据库发送SQL语句,想完成对数据库的增删改查,只需要通过这个对象向数据库发送增删改查语句即可. Statement对象的exe ...
- java reference(转)
http://blog.163.com/xubin_3@126/blog/static/112987702200962211145825/ 在Java中的引用类型,是指除了基本的变量类型之外的所有类型 ...
- git day01笔记 常用操作命令 快照 推送 拉取
ansible 批量在远程主机上执行命令或者脚本 git 做版本控制的一个工具 ## git操作命令: 工作区:当前编辑的区域 缓存区:add 之后的区域 本地仓库:commit之后的区域 远程仓 ...
- JAVA高级特性--自动拆箱-装箱,枚举类型
基本数据类型转换为引用类型对象 一个自动装箱的例子 Integer i=10; 相当于 Integer i=new Integer(10); 一个自动拆箱的例子 Integer m=10; int n ...