Vue 学习笔记
使用 vue 一段时间了,但是并没有系统的总结过所学习的知识,所以特意新建一篇文章总结一下 vue 中比较重要的知识点,以便之后方便翻阅复习。
数据的响应式
Vue 实例被创建时,data对象所有的属性会被加入到Vue 的响应式系统中。 当data中的属性发生变化,视图也会跟着发生变化。 如果一个值,一开始不会使用,但是之后会使用,可以为这个值设置一个类型相同的初始值
data: {
newTodoText: '',//字符串类型初始值
visitCount: 0,//数字类型初始值
hideCompletedTodos: false,//布尔类型初始值
todos: [],//数组类型初始值
obj: {}//对象类型初始值
error: null//不存在数据的初始值
}
如果没有设置初始值,在Vue实例创建后为data添加属性,此时的属性是非响应式的 除非使用
Vue.set(vm.someObject, 'b', 2)
//or
this.$set(this.someObject,'b',2)
关于对象
对于一个对象类型,使用obj.prop = 'xxx' 新添加属性是非响应式的 如果要添加响应式的属性,可以使用this.$set或重新赋值新对象的方法
// obj:{
// a:1,
// b:2
// }
//向obj种添加单个属性c
this.$set(this.obj,'c',3)
//向obj中添加c和d属性
this.obj = Object.assign({},this.obj,{c:3,d:4})
关于数组
和对象不同,大多数的数组方法都会触发视图更新 如push() pop() splice() sort() 等 也有些方法不会变更原始数组,那么可以直接把整个数组替换掉
// numbers: [ 1, 2, 3, 4, 5 ]
this.numbers = this.numbers.filter(number => number>3)
数组依然有两种情况是非响应的
- 直接使用索引修改一个数组项时 this.items[indexOfItem] = newValue
- 修改数组长度 this.items.length = 1
对于第一种情况可以使用vm.set
// numbers: [ 1, 2, 3, 4, 5 ]
//无法使用索引直接修改
//this.numbers[3] = 123456
//应该使用
this.$set(this.numbers,3,123456)
// or
this.numbers.splice(3,1,123456)
对于第二种情况则使用数组的splice
// numbers: [ 1, 2, 3, 4, 5 ]
//无法直接修改数组长度
// this.numbers.length = 2
//应该使用
this.numbers.splice(2)
关于数组对象
如过有一个列表,要控制每个列表的显隐
第一种情况 sourceData:[ {id:1,name:'红',show:false}, {id:2,name:'黄',show:false}, {id:3,name:'蓝',show:false}, ],
元数据中就有show这个属性,此时的show为响应式的,此时没有问题。
changeShow(show,record){
//直接修改视图可响应
record.show = !show
}
第二种情况 因为数据是从后台获取,一般先给默认值sourceData:[],然后赋值
//从后台得到数据
this.handleData = [
{id:1,name:'红'},
{id:2,name:'黄'},
{id:3,name:'蓝'},
]
//处理一下后台的数据
this.handleData = sourceData.map(item=>{
item.show = false
return item
})
此时的show属性是非响应的,id和name属性是响应的,因为show属性是后加给对象的,vue没有跟踪,解决方法也非常简单
第一种解决方法,添加对象新属性的时候重新赋予一个新的对象
this.handleData = sourceData.map(item=>{
item = Object.assign({},item,{show:false})
return item
})
第二个方法,使用数组的响应式方法
changeShow(show,record){
//直接修改视图不会响应
record.show = !show
//官方推荐使用方法
this.$set(
this.handleData,
this.handleData.findIndex(item => {
return item.id === record.id
}),
Object.assign({},record,{show:!show})
)
//使用splice
this.handleData.splice(
this.handleData.findIndex(item => {
return item.id === record.id
}),
1,
Object.assign({},record,{show:!show})
)
}
推荐使用第一种,为对象添加新的属性时,不要使用obj.prop = 'xxx',而是使用obj = Object.assign({},obj,{prop:propValue})或this.$set(obj,'propName',propValue),只有在修改对象属性时才使用obj.prop = 'xxx'。
表单输入绑定
v-model 会忽略所有表单元素的 value、checked、selected attribute 的初始值而总是将 Vue实例的数据作为数据 > 来源。你应该通过 JavaScript 在组件的 data 选项中声明初始值。
复选框
单个复选框绑定一个布尔值
<input type="checkbox" v-model="form.checked" value="apple">是否{{form.checked}}
多个复选框绑定一个数组
<input type="checkbox" v-model="form.fruits" value="apple">苹果
<input type="checkbox" v-model="form.fruits" value="banana">香蕉
<input type="checkbox" v-model="form.fruits" value="peach">桃子
单选按钮
单选按钮绑定一个字符串
<input type="radio" value="1" v-model="form.gender">男
<input type="radio" value="2" v-model="form.gender">女
选择框
单选时绑定一个字符串
多选时绑定一个数组
值绑定
对于单个复选框绑定的值为布尔值,也可绑定为字符串
<input
type="checkbox"
v-model="toggle"
true-value="yes"
false-value="no"
>
也可绑定为其他的数据类型
<select v-model="selected">
<option v-bind:value="obj">选项1</option>
</select>
关于组件
在组件中使用v-model
<input v-model="searchText">
等价于
<input
:value="searchText"
@input="searchText = $event.target.value"
>
运用在组件上也是如此
<custom-input
v-model="searchText"
></custom-input>
等价于
<custom-input
:value="searchText"
@input="searchText = $event"
></custom-input>
所以要在子组件中接收value和触发input事件
Vue.component('custom-input',{
props:['value'],
template:`
<div>
<input :value="value" @input="$emit('input',$event.target.value)" />
</div>
`
})
自定义组件的 v-model
一个组件上的 v-model 默认会利用名为 value 的 prop 和名为 input 的事件
如果是复选框,单选框可能需要监听不同的prop和事件,比如监听复选框的checked的prop和change的事件
Vue.component('child-component',{
model: {
prop: 'checked',
event: 'change'
},
props: {
checked: Boolean
},
template: `
<div>
<input
type="checkbox"
:checked="checked"
@change="$emit('change', $event.target.checked)"
>
</div>
`
})
动态组件
<component :is="currentComponent"></component>
Vue.component('home-co',{
template:`<h1>Home Page</h1>`
})
Vue.component('archive-co',{
template:`<h1>Archive Page</h1>`
})
Vue.component('post-co',{
template:`<h1>Post Page</h1>`
})
const app = new Vue({
el:'#app',
data(){
return {
text:'',
currentComponent:'archive-co'
}
}
})
将原生事件绑定到组件
组件的某个特定的元素监听原生事件
Vue.component('base-input', {
inheritAttrs: false,
props: ['label', 'value'],
computed: {
inputListeners: function () {
var vm = this
return Object.assign({},
this.$listeners,
{
input: function (event) {
vm.$emit('input', event.target.value)
}
}
)
}
},
template: `
<label>
{{ label }}
<input
v-bind="$attrs"
:value="value"
v-on="inputListeners"
>
</label>
`
})
.sync修饰符
<child-component :message.sync="message"></child-component>
等于
<child-component :message="message" @update:message="message = $event"></child-component>
sync相当于一个缩写,以下是一个简单的例子
Vue.component('parent-component',{
data(){
return{
message:'旧消息',
}
},
template:`
<child-component :message="message" @update:message="message = $event"></child-component>
`
})
Vue.component('child-component',{
props:{
message:{
type:String,
required:false,
default:''
}
},
template:`<div>
子组件:{{message}}
<button @click="$emit('update:message','新消息')">按钮</button>
</div>`
})
Prop
传入一个对象的所有 property
数据对象
post: {
id: 1,
title: 'My Journey with Vue'
}
绑定数据
<blog-post v-bind="post"></blog-post>
相当于
<blog-post
v-bind:id="post.id"
v-bind:title="post.title"
></blog-post>
单向数据流
注意在 JavaScript 中对象和数组是通过引用传入的,所以对于一个数组或对象类型的 prop 来说,在子组件中改变变更这个对象或数组本身将会影响到父组件的状态。