目录
- 4.1 vue更新数组或者对象时触发视图更新的方法
- 4.2 解决非工程化项目初始化页面闪动问题
- 4.3 v-for产生的列表,实现active的切换
- 4.4 v-model语法糖的使用
- 4.5 v-slot 指令 (插槽 vue2.6更新)
- 4.1 vue更新数组或者对象时触发视图更新的方法
- 触发视图更新的方法有如下几种
1. Vue.set 响应式新增与修改数据
可以设置对象或数组的值,通过key或数组索引,可以触发视图更新
target:要更改的数据源(可以是对象或者数组)
key:要更改的具体数据
value :重新赋的值
- 数组修改
Vue.set(array, indexOfItem, newValue)
this.array.$set(indexOfItem, newValue)
- 对象修改
Vue.set(obj, keyOfItem, newValue)
this.obj.$set(keyOfItem, newValue)
2. Vue.delete
删除对象或数组中元素,通过key或数组索引,可以触发视图更新
- 数组修改
Vue.delete(array, indexOfItem)
this.array.$delete(indexOfItem)
- 对象修改
Vue.delete(obj, keyOfItem)
this.obj.$delete(keyOfItem)
3. 数组对象直接修改属性,可以触发视图更新
this.array[0].show = true;
this.array.forEach(function(item){
item.show = true;
});
4. splice方法修改数组,可以触发视图更新
this.array.splice(indexOfItem, 1, newElement)
5. 数组整体修改,可以触发视图更新
var tempArray = this.array;
tempArray[0].show = true;
this.array = tempArray;
6. 用Object.assign或lodash.assign可以为对象添加响应式属性,可以触发视图更新
//Object.assign的单层的覆盖前面的属性,不会递归的合并属性
this.obj = Object.assign({},this.obj,{a:1, b:2})
//assign与Object.assign一样
this.obj = _.assign({},this.obj,{a:1, b:2})
//merge会递归的合并属性
this.obj = _.merge({},this.obj,{a:1, b:2})
7. Vue包含一组观察数组变异的方法,使用它们改变数组也会触发视图更新
push() 向数组的末尾添加一个或多个元素,并返回新的长度。
pop() 删除最后一个元素,把数组长度减 1,并且返回它删除的元素的值。
shift() 把数组的第一个元素从其中删除,并返回第一个元素的值。
unshift() 向数组的开头添加一个或更多元素,并返回新的长度。
splice() 向/从数组中添加/删除项目,然后返回被删除的项目。 该方法会改变原始数组。
sort() 对数组的元素进行排序。
reverse() 颠倒数组中元素的顺序。
不变异的方法:
filter()
concat()
slice()
他们返回的是一个新数组,使用这些方法时,可以用新数组来替换原始数组
原理:
-- Vue 在检测到数组变化时,并不是直接重新渲染整个列表,而是最大化复用DOM元素。替换的数组中,含有相同元素的项不会被重新渲染,
因此可以大胆的用新数组来替换旧数组,不用担心性能问题。
-- 值得注意的是:
以下变动的数组中Vue是不能检测到的,也不会触发视图更新。
1.通过索引直接设置项, 比如this.books[3]={...}
2.修改数组长度, 比如 this.books.length = 1;
两个问题都可以用splice来解决:
第一个问题 还可以用 set方法 this.$set(this.books,3,{...})
- 4.2 解决非工程化项目初始化页面闪动问题
vue页面在加载的时候闪烁花括号{}},v-cloak指令和css规则如[v-cloak]{display:none}一起用时,这个指令可以隐藏未编译的Mustache标签直到实例准备完毕。
/*css样式*/
[v-cloak] {
display: none;
}
<!--html代码-->
<div id="app" v-cloak>
<ul>
<li v-for="item in tabs">{{item.text}}</li>
</ul>
</div>
- 4.3 v-for产生的列表,实现active的切换
<div v-for="(desc,tableIndex) in descriptions.firstface">
<ul class="controller-checkboxs clearfix" >
<li
@click="currentIndex=index,currentTable=tableIndex"
class="controller-checkbox-item"
:class="{active:index===currentIndex&&tableIndex==currentTable}"
v-for="(ctrlValue,index) in desc.args">
</li>
</ul>
</div>
- 4.4 v-model语法糖的使用
<input type="text" v-model="mes">
此时mes值就与input的值进行双向绑定
实际上上面的代码是下面代码的语法糖。
<input v-bind:value="mes" v-on:input="mes= $event.target.value"/>
要理解这行代码,首先你要知道 input 元素本身有个 oninput 事件,这是 HTML5 新增加的,类似 onchange ,每当输入框内容发生变化,就会触发 oninput ,把最新的value传递给 mes。从而实现了v-model
v-model用在组件上的时候
我们知道v-model可以实现数据的双向绑定,但是,如果说这是一个复杂的输入框,在项目中也经常使用。此时我们我们就把这个输入框封装成组件,那怎么利用v-mode让父组件的值与子组件input框里的值双向绑定起来。看下面的例子
1:父组件 <InputBox v-model="mes"></InputBox> 根据上面讲的v-model语法糖,所以 InputBox那行代码也可以写成 <InputBox v-bind:value="value" v-on:input="mes= $event.target.value"></InputBox>
2:子组件
所以说:1:接受一个value prop 2:在有新的值时触发input事件并将新值作为参数 。这样,我们就可以看到子组件和父组件的值就可以联动起来。但是我们看到v-model中的事件是input,如果碰到单选复选按钮这种check事件,那我们就需要去自定义v-model
v-model自定义
父组件
<InputCheckout v-model="foo"></InputCheckout>
<InputBox v-bind:value="value" v-on:input="mes= $event.target.value"></InputBox>
但是单选复选框不会触发input事件,只会触发change事件。所以在子组件我们需要自定义v-model。我们来看看代码哈
- 4.5 v-slot使用
https://juejin.im/post/5c64e11151882562e4726d98这个介绍的不错
Vue 为具名和范围插槽引入了一个全新的语法,即我们今天要讲的主角:v-slot 指令。目的就是想统一 slot 和 scope-slot 语法,使代码更加规范和清晰。
//默认插槽
<baz v-slot ="baz">
{{baz}}
</ baz >
//嵌套默认插槽
//组件提供的范围变量也在该组件本身上声明
<foo v-slot="foo">
<bar v-slot="bar">
<baz v-slot="baz">
{{ foo }} {{ bar }} {{ baz }}
</baz>
</bar>
</foo>
//具名域槽
<my-name>
<template v-slot:one="{ msg }">
{{ msg }}
</template>
</my-name>
//混用插槽
<foo>
<template v-slot:one="one">
<bar v-slot="bar">
<div>{{ one }} {{ bar }}</div>
</bar>
</template>
<template v-slot:two="two">
<bar v-slot="bar">
<div>{{ two }} {{ bar }}</div>
</bar>
</template>
</foo>
插槽内容的解构赋值
在 Vue 代码内部,我们传递的 slotProps 其实就是函数的一个单一参数:
function (slotProps) {
// ... slot content ...
}
意味着 v-slot 的值只要满足函数参数定义的 JavaScript 表达式的都可以接受。
<current-user v-slot="{ user }">
{{ user.firstName }}
</current-user>
以重命名解构变量:
<current-user v-slot="{ user: person }">>
{{ person.firstName }}
</current-user>
甚至可以自定义回退内容,以便在未定义插值情况下使用:
<current-user v-slot="{ user = { firstName: 'Guest' } }">>
{{ user.firstName }}
</current-user>
动态插槽名称
<base-layout>
<template v-slot:[dynamicSlotName]>
...
</template>
</base-layout>
命名插槽简写
可以使用 # 代替 v-slot。例如, v-slot:header 简写成 #header:
base-layout>
<template #header>
<h1>Here might be a page title</h1>
</template>
<p>A paragraph for the main content.</p>
<p>And another one.</p>
<template #footer>
<p>Here's some contact info</p>
</template>
</base-layout>
和其他指令一样,只有在提供参数时才能使用简写形式,下面的写法是无效的
<!-- 将会触发一个控制台警告 -->
<current-user #="{ user }">
{{ user.firstName }}
</current-user>
也就是说,如果你想使用简写语法,则务必指定插值的名字:
<current-user #default="{ user }">
{{ user.firstName }}
</current-user>