vue notes

vue-notes

vue 学习总结,持续跟进

什么是Vue

vue-notes

Vue 不支持 IE8 及以下版本,因为 Vue 使用了 IE8 无法模拟的 ECMAScript 5 特性。但它支持所有兼容 ECMAScript 5 的浏览器

生命周期钩子

生命周期 描述
beforeCreate 在实例初始化之后,数据观测 (data observer) 和 event/watcher 事件配置之前被调用。
created 在实例创建完成后,属性已绑定。挂载阶段还没开始,DOM还未生成,$el 属性目前不可见。
beforeMount 在挂载开始之前被调用
mounted 模板编译挂载之后(不保证组件已在doucument中)
beforeUpdate 组件更新之前
updated 组件更新之后
activated keep-alive 组件激活时调用
deactivated keep-alive 组件停用时调用
beforeDestroy 实例销毁前调用,在这一步,实例仍然完全可用
destroyed 实例销毁后调用
errorCaptured 当捕获一个来自子孙组件的错误时被调用

注意箭头函数的使用

不在选项属性或者回调上使用箭头函数,因为箭头函数是与父级作用域绑定在一起的,this指向的是最近的普通函数的作用域

1
2
created: () => console.log(this.a); //Uncaught TypeError: Cannot read property of undefined
vm.$watch('a', newValue => this.myMethod()); //Uncaught TypeError: this.myMethod is not a function

计算属性和侦听器

计算属性

  • 当有些数据需要随着其他数据的变动而变动时,数据依赖;
  • 基于它们的依赖进行缓存的,不希望有依赖可使用方法实现;
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    //计算属性默认只有 getter ,不过在需要时你也可以提供一个 setter
    //...
    computed: {
    fullName: {
    // getter
    get: function () {
    return this.firstName + ' ' + this.lastName
    },
    // setter
    set: function (newValue) {
    var names = newValue.split(' ')
    this.firstName = names[0]
    this.lastName = names[names.length - 1]
    }
    }
    }
    //...

侦听器: 当需要的数据在变化时执行异步执行或开销较大的操作


绑定 HTML Class

可同时写固定class和动态class

1
<div :class="[icon, {isActive ? activeClass : ''}]"></div>


条件渲染

1.在 <template> 元素上使用 v-if 条件渲染分组

1
2
3
<template v-if>
<div>template元素不会渲染到页面上</div>
</template>

2.用 key 管理可复用的元素

1
2
3
4
5
6
7
8
9
10
<!--这两个元素是完全独立的,不要复用它们-->
<!--如果不使用 key 两个模板使用了相同的元素,<input> 不会被替换掉——仅仅是替换了它的 placeholder-->
<template v-if="loginType === 'username'">
<label>Username</label>
<input placeholder="Enter your username" key="username-input">
</template>
<template v-else>
<label>Email</label>
<input placeholder="Enter your email address" key="email-input">
</template>

3.v-if=’null、undefined 或 false’ 表示为 fasle


列表渲染

1.可用 of 替代 in, 因为它更接近 JavaScript 迭代器的用法

1
<div v-for="item of items"></div>

2.一个对象的 v-for
在遍历对象时,是按 Object.keys() 的结果遍历,但是不能保证它的结果在不同的 JavaScript 引擎下是一致的。

1
2
3
4
5
object: {
firstName: 'John',
lastName: 'Doe',
age: 30
}

1
2
3
<div v-for="(value, key, index) in object">
{{ index }}. {{ key }}: {{ value }}
</div>
1
2
3
4
//结果
0.firstName: John
1.lastName: Doe
2.age: 30

3.数组更新检测

1
2
3
4
5
6
7
8
9
var example1 = new Vue({
el: '#example-1',
data: {
items: [
{ message: 'Foo' },
{ message: 'Bar' }
]
}
})

  • 变异方法:触发视图更新
    包括: pop(), push(), shift(), unshift(), splice(), sort(), reverse()

    1
    example1.items.push({ message: 'AOA' })
  • 替换数组: 用一个含有相同元素的数组去替换原来的数组是非常高效的操作
    包括: filter(), concat(), slice(), 总是返回一个新数组

    1
    2
    3
    example1.items = example1.items.filter(function (item) {
    return item.message.match(/Foo/)
    })
  • 注意事项: 由于 JavaScript 的限制,Vue 不能检测以下变动的数组

  1. 当你利用索引直接设置一个项时,响应式:
    Vue.set(vm.items, indexOfItem, newValue)vm.$set(vm.items, indexOfItem, newValue)
  2. 当你修改数组的长度时: vm.items.splice(newLength)

4.对象更改检测注意事项
还是由于 JavaScript 的限制,Vue 不能检测对象属性的添加或删除

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
var vm = new Vue({
data: {
userProfile: {
name: 'Anika'
}
}
})

//添加单个属性
Vue.set(vm.userProfile, 'age', 27);
vm.$set(vm.userProfile, 'age', 27);

//添加多个属性
vm.userProfile = Object.assign({}, vm.userProfile, {
age: 27,
height: 188
})

5.显示过滤/排序结果

  • 计算属性
    1
    <li v-for="n in evenNumbers">{{ n }}</li>
1
2
3
4
5
6
7
8
9
10
data: {
numbers: [ 1, 2, 3, 4, 5 ]
},
computed: {
evenNumbers: funciton() {
return this.numbers.filter(function (num) {
return num % 2 === 0;
})
}
}
  • methods
    1
    <li v-for="n in even(numbers)">{{ n }}</li>
1
2
3
4
5
6
7
8
9
10
data: {
numbers: [ 1, 2, 3, 4, 5 ]
},
methods: {
even(numbers) {
return numbers.filter(function (num) {
return num % 2 === 0;
})
}
}

事件处理

1.事件修饰符

  • .stop: 阻止单击事件继续传播
  • .prevent: 提交事件不再重载页面
  • .capture: 添加事件监听器时使用事件捕获模式,即元素自身触发的事件先在此处理,然后才交由内部元素进行处理
  • .self: 只当在 event.target 是当前元素自身时触发处理函数, 即事件不是从内部元素触发的
  • .once: 点击事件将只会触发一次
  • .passive: 尤其能够提升移动端的性能, 不和.prevent一起使用

2.按键修饰符

  • .enter 回车键 <input @keyup.enter="submit">
  • .delete 捕获“删除”和“退格”键

v-model修饰符

.lazy: 使用 change 事件进行同步

1
2
<!-- 在“change”时而非“input”时更新 -->
<input v-model.lazy="msg">

.number: 自动将用户的输入值转为数值类型

1
<input v-model.number="age" type="number">

.trim: 自动过滤用户输入的首尾空白字符

1
<input v-model.trim="msg">

v-model等价于

1
2
3
4
5
6
<input v-model="searchText">
<!--等价于-->
<input
v-bind:value="searchText"
v-on:input="searchText = $event.target.value"
>


组件

1.data必须是一个函数,每个实例可以维护一份被返回对象的独立的拷贝

2.通过事件向父级组件发送消息: $emit(‘方法名字’, 参数), 通过方法名触发事件并传值

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
<!--应用页面-->
<div>
<div :style="{ fontSize: postFontSize + 'em' }">
<blog-post
v-for="post of posts"
:key="post.id"
:post="post"
@enlarge-text='enlarge'>
</blog-post>
</div>
<custom-input v-model="searchText"></custom-input>
</div>
<script>
//组件模板
Vue.component('blog-post', {
props: ['post'],
template: `
<div>
<p>{{post.title}}</p>
<button @click="$emit('enlarge-text', 0.1)">
Enlarge text
</button>
<div v-html="post.contet"></div>
</div>
`
})
//v-model
Vue.component('custom-input', {
props: ['value'],
template: `
<input
v-bind:value="value"
v-on:input="$emit('input', $event.target.value)"
>
`
})

//vue实例
var vm = new Vue({
el: '#app',
data: {
posts: [
{ id: 1, title: 'My journey with Vue', contet: 'sdfasdfad' },
{ id: 2, title: 'Blogging with Vue', contet: 'sdfasdfad22' },
{ id: 3, title: 'Why Vue is so fun', contet: 'sdfasdfads1111' }
],
postFontSize: 1,
searchText: ''
},
methods: {
enlarge(e) {
this.postFontSize += e; //e: 0.1
}
}
})
</script>

3.插槽<slot></slot>

  • 作用域插槽

例如一个<todo-list>组件模板可能包含了以下代码:

1
2
3
4
5
6
7
8
9
<ul>
<li v-for="todo in todos" :key="todo.id">
<!-- 我们为每个 todo 准备了一个插槽,将 `todo` 对象作为一个插槽的 prop 传入。-->
<slot v-bind:todo="todo">
<!-- 回退的内容 -->
{{ todo.text }}
</slot>
</li>
</ul>

现在当我们使用 <todo-list> 组件的时候,我们可以选择为待办项定义一个不一样的 <template> 作为替代方案,并且可以通过 slot-scope 特性从子组件获取数据

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<todo-list :todos="todos">
<template slot-scope="slotProps">
<span v-if="slotProps.todo.isComplete"></span>
{{ slotProps.todo.text }}
</template>
</todo-list>

<!-- ES2015解构赋值 -->
<todo-list :todos="todos">
<template slot-scope="{ todo }">
<span v-if="todo.isComplete"></span>
{{ todo.text }}
</template>
</todo-list>

4.动态组件is

1
2
<!-- 组件会在 `currentTabComponent` 改变时改变 -->
<component v-bind:is="currentTabComponent"></component>

5.基础组件的自动化全局注册

6.自定义事件

  • 始终使用 kebab-case 的事件名

    1
    2
    3
    4
    5
    6
    7
    8
    <my-component @my-event="doSomething"></my-component>

    Vue.component('my-component', {
    props: [],
    template: `
    <div @click="$emit('my-event')"></div>
    `
    })
  • 将原生事件绑定到组件

  1. $attrs属性: 使用 v-bind="$attrs", 将父组件中不被认为 props特性绑定的属性传入子组件中,通常配合 interitAttrs 选项一起使用
  2. $listeners属性

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    <base-input label="vue啊" value='ddd' v-model='getValue'></base-input>

    Vue.component('base-input', {
    inheritAttrs: false,
    props: ['label', 'value'],
    computed: {
    inputListeners: function() {
    var vm = this
    // `Object.assign` 将所有的对象合并为一个新对象
    return Object.assign({},
    // 我们从父级添加所有的监听器
    this.$listeners,
    // 然后我们添加自定义监听器,
    // 或覆写一些监听器的行为
    {
    // 这里确保组件配合 `v-model` 的工作
    input: function(event) {
    vm.$emit('input', event.target.value)
    }
    }
    )
    }
    },
    template: `
    <label>
    {{ label }}
    <input
    v-bind="$attrs"
    v-bind:value="value"
    v-on="inputListeners"
    >
    </label>
    `
    })
  3. .sync修饰符

待续

本文标题:vue notes

文章作者:AngellinaZ

发布时间:2018年09月11日 - 14:09

最后更新:2018年09月27日 - 16:09

许可协议: 署名-非商业性使用-禁止演绎 4.0 国际 转载请保留原文链接及作者。

-------------本文结束感谢您的阅读-------------