Vue学习

Vue 渐进式的js框架。

组件化和双向绑定。

大纲

1
2
3
4
5
6
7
8
9
参考:https://cn.vuejs.org/
1. 模板语法, 条件渲染,列表渲染,事件处理。
2. 组件基础, 插槽slot,生命周期 created mounted destroyed以及他们的beforexxx事件。
3. 一些属性: 普通属性, 计算属性, 侦听属性, 过滤器filters。
4. 父子组件传值。props, this.$parent, this.$refs.refName, this.$emit()
5. 单文件组件。template script style
6. async和await的使用(和promise的区别), 进阶: 动画和过渡。以及vuex和router等等。
7. 另外还可以使用一些样式库 semantic-ui element-ui等等。
8. 可以上手开发了。。。。

示例一

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
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
<!DOCTYPE html>
<html>

<head>
<meta charset="utf-8" />
<title>Page Title</title>
<link rel="stylesheet" type="text/css" media="screen" href="main.css" />
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
</head>

<body>
<div id="example">
<p>origin message: "{{ message }}"</p>
<p>computed reversed message "{{reversedMessage}}"</p>
<p>call methods : "{{sayHi()}}"</p>
<p>{{this.fullName}}</p>
<button @click="changeFirstName('wang')">修改为wang</button>
<button-counter></button-counter>
</div>

<div id="testif">
<p v-if='show'>hello dottie</p>
<p v-else>hello daejong</p>
<button v-on:click='toggleShow'>toggle</button>
<p v-show='show'>hhhhh</p>
<button-counter username='china' password='i love you '></button-counter>
<hr>
<!-- 使用v-bind动态传值。 -->
<button-counter v-for='post in posts' v-bind:username='post.id' v-bind:password='post.title'></button-counter>
</div>


</body>
<script>

Vue.component('button-counter', {
props: ['username', 'password'], //外部传值。
data: function() {
//使用return表示每个使用者获取的是一份独立的拷贝。
return {
count: 0
}
},
methods: {
AddCount: function() {
this.count++;
}
},
template:'<button @click="AddCount()">you click me {{this.count}} times {{username}}, {{password}}</button>'
})

var testif = new Vue({
el: '#testif',
data: {
show: true,
posts: [
{ id: 1, title: 'My journey with Vue' },
{ id: 2, title: 'Blogging with Vue' },
{ id: 3, title: 'Why Vue is so fun' }
]
},
methods: {
toggleShow: function() {
this.show = !this.show
}
}
});


var example = new Vue({
el: '#example',
data: {
//普通属性。
message: 'hello',
firstName: 'lin',
lastName: 'dazhong',
// fullName: 'lin dazhong'
},
methods: {
sayHi: function () {
return this.message + " dottie";
},
changeFirstName: function (val) {
this.firstName = val;
}
},
computed: {
//计算属性的getter方式。这里的计算属性vm.reversedMessage依赖于vm.message, 一旦vm.message发生变化。所有的计算属性都发生变化。
reversedMessage: function () {
//this指向vm实例, 这里不能用箭头函数,否则this的指向会有问题。
return this.message.split('').reverse().join('');
},
//计算属性不能与data里面的属性名一致。 否则data的属性会覆盖掉计算属性,
//一般都是计算属性依赖于data的属性。
fullName: {
get: function () {
return this.firstName + ' ' + this.lastName;
}
// ,set: function() {
// //执行其他操作。
// }
}
},
watch: {
//一般这里监听的属性是普通属性,当然也可以监听计算属性(这里可以直接在计算属性里面做)。
// firstName: function(val) {
// this.fullName = val + ' ' + this.lastName;
// },
// lastName: function(val) {
// this.fullName = this.firstName + ' ' + val;
// }
fullName: function () {
this.message = "123";
}
}
})
</script>

</html>

示例二

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
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>Page Title</title>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
</head>
<body>
<div id="app" v-bind:style='{fontSize: postFontSize + "em"}'>
{{ alertColor | appendHello}}
<post-block
v-for='post in posts'
<!-- v-bind:key='' v-bind:title='' 可以动态绑定值, 如果值是静态的就直接用key='' title='' -->
v-bind:key='post.id'
v-bind:post='post'
v-on:enlarge-text='enlargeFont'
>slot slot</post-block>

<alert-error ref='alertRef' v-bind:alertcolor='alertColor'>用户名错误</alert-error>
<button @click='callAlertRef'>callAlertRef</button>
</div>
</body>
<script>

//这些组件是全局注册的。也就是说它们在注册之后可以用在任何新创建的 Vue 根实例 (new Vue) 的模板中。
//定义组件。可以复用。
Vue.component('post-block', {
props: ['post'],
data: function() {
return {

}
},
template: `<div class='postBlock'>
<h2>{{post.title}}</h2>
<p>{{post.content}}</p>
// 与父类通信,调用父类的方法。
<button v-on:click='$emit("enlarge-text", 0.1)'>放大字体</button>
<slot></slot>
</div>`
});

Vue.component('alert-error', {
props: ['alertcolor'],
data: function() {
return {
msg: "alert-alert"
}
},
template: `
<div class='demo-alert'>
<strong>Error</strong>
{{alertcolor}}
{{msg}}
<slot></slot>
</div>
`
});

//在vue中可以使用组件。
var app = new Vue({
el: '#app',
data: {
posts: [
{ id: 1, title: 'My journey with Vue',content:"hello dottie" },
{ id: 2, title: 'Blogging with Vue',content:"hello daejong" },
{ id: 3, title: 'Why Vue is so fun',content:"hello china" }
],
postFontSize: 1,
alertColor: 'red'
},
methods: {
enlargeFont: function(val) {
this.postFontSize += val;
},
callAlertRef: function() {
this.$refs.alertRef.msg = 'alert-alert-alert';
}
},
filters: {
appendHello: function(val) {
return val + " hello";
}
}
})

</script>
</html>

单文件组件的vue

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
// 可以指定lang='jade'等等
<template>
<p>{{ msg }}</p>
</template>

<script>
// 可以引入其他组件或者工具等等。
import OtherComponent from './OtherCompoent.vue'
export default {
// 外部传值。
props: [],
// 普通属性。
data() {
return {
msg: 'hello dottie'
}
},
//限制可以在该组件中可以使用的外部组件。 等价于 'OtherComponent': OtherComponent
components: {
OtherComponent
},
methods: {
// 普通方法。
},
computed: {
// 计算属性
},
watch: {
// 侦听属性
},
filters: {
// 定义过滤器, 在插值 {{ msg | filter1 | filter}}
appendHello: function(msg) {
return msg + " hello";
}
},
// 一般放到created里面就可以了,这样可以及早发请求获取数据,
// 如果有依赖dom必须存在的情况,就放到mounted(){this.$nextTick(() => { /* code */ })}里面
created: {
//template还没渲染成html, 这里操作dom会失败。
},
mounted: {
//template已经渲染成html,且已经挂载在dom中。可以使用this.$nextTick(function() {}) 保证this.$el在dom中。
}
}
</script>

// 可以指定样式的使用范围,使用scoped表示样式只能在组件中使用。
// 也可以指定lang = scss, less等。
<style scoped>

</style>

async 和 await

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
function sleep(n) {
var start = new Date().getTime();
while (true)
// js是单线程机制, 这里的效果等价sleep。不过仍然有弊端(就是此时执行js代码的线程停止工作了),最好用http请求等耗时操作。
if (new Date().getTime() - start > n) break;
}

function getData() {
sleep(4000);
return 'dottie';
}

//await必须在async中使用, async是表示该函数是异步的, await保证函数内部执行时同步的。
// async和await关键字成为最新的方式,解决回调。成为js语言的官方特性。基于promise和generator做了简单的封装。
// 另一个好处是,可以使用promise不能使用的try catch
async function logger() {
try {
let name = await getData();
console.log(name);
} catch (error) {
console.log(error)
}
}

logger();
console.log('hello...');

后续

开发项目:
vuex + vue + vue-router + element-ui等等。