入门
https://cn.vuejs.org/
轻量级的前端界面框架
2016.10 发布最新 2.0 版本,更强大,更快速
数据渲染/数据同步
组件化/模块化
其他功能:路由、ajax,数据流
Vue实例
每个 Vue 应用都是通过用 Vue 函数创建一个新的 Vue 实例开始的:
| new Vue({
el: '#app',
data: {
message: 'Hello Vue.js!'
}
})
|
| var my = new Vue({
el: '#app',
template: '<div>{{ fruit }}</div>',
data: {
fruit: 'apple',
}
})
|
| <div id="app"></div>
<script type="text/javascript">
new Vue({
el: '#app',
template: "<p>hello world --- {{ word }} </p>",
data: {
word: 'data content'
}
})
</script>
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23 | <!DOCTYPE html>
<html lang="zh">
<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">
{{ message }}
</div>
<script type="text/javascript">
var app = new Vue({
el: '#app',
data: {
message: 'Hello Vue!'
}
})
</script>
</body>
</html>
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 | <!DOCTYPE html>
<html lang="zh">
<head>
<meta charset="UTF-8">
<title>Vue 入门</title>
<script src="./vue.js"></script>
</head>
<body>
<div id="root">{{ msg }}</div>
<script>
new Vue({ // 创建一个实例
el: "#root", // 接管 id=root 的内容,与 id 为 root 的 DOM 做绑定
data: { // 实例中的数据
msg: "hello world"
}
})
</script>
</body>
</html>
|
1
2
3
4
5
6
7
8
9
10
11
12 | <div id="app">{{ content }}</div>
<script>
var vm = new Vue({
el: "#app",
data: {
content: 'hello world'
}
})
setTimeout(function() {
vm.$data.content = 'bye world'
}, 2000)
</script>
|
MVVM 模式
MVP 模式:
Model(数据层,封装了核心数据和逻辑功能的模型)
View(视图层,负责显示)
Presenter(封装了视图的所有操作和响应用户的输入、输出和事件等,View 并不直接使用 Model,它们之间的通信是通过 Presenter 来进行的,所有的交互都发生在 Presenter 内部)
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 | <!DOCTYPE html>
<html lang="zh">
<head>
<meta charset="UTF-8">
<title>TodoList Jquery</title>
<script src="https://cdn.bootcss.com/jquery/3.4.1/jquery.js"></script>
</head>
<body>
<!-- 视图层 -->
<div>
<input id="input" type="text">
<button id="btn">提交</button>
<ul id="list"></ul>
</div>
<script>
function Page() {
}
// Presenter 控制器 视图和模型的中转站
// 基本上都是在做 DOM 操作
$.extend(Page.prototype, {
init: function() {
this.bindEvents()
},
bindEvents: function() {
var btn = $('#btn');
btn.on('click', $.proxy(this.handleBtnClick, this))
},
handleBtnClick: function() {
var inputElem = $("#input");
var inputValue = $("#input").val();
var ulElem = $("#list");
ulElem.append('<li>' + inputValue + '</li>');
inputElem.val('');
}
})
var page = new Page();
page.init();
</script>
</body>
</html>
|
MVVM
ViewModel 是 Vue 内置的,只要关注 View 和 Model 就可以了
注意力主要放在 Model 层,面向数据编程(MVP 主要面向 DOM 操作)
MVVM 模式和 MVC 模式一样,主要目的是分离视图(View)和模型(Model)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24 | <!-- View 层 -->
<div id="app">
<input type="text" v-model="inputValue">
<button v-on:click="handleBtnClick">提交</button>
<ul>
<li v-for="item in list">{{ item }}</li>
</ul>
</div>
<script>
// Model 层
var app = new Vue({
el: "#app",
data: {
list: [],
inputValue: ''
},
methods: {
handleBtnClick: function() {
this.list.push(this.inputValue)
this.inputValue = ''
}
}
})
</script>
|
挂载点、模板、实例之间的关系
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24 | <!DOCTYPE html>
<html lang="zh">
<head>
<meta charset="UTF-8">
<title>Vue 入门</title>
<script src="./vue.js"></script>
</head>
<body>
<!-- Vue 实例的挂载点 -->
<div id="root">
<!-- 挂载点内部的内容称为模板 -->
</div>
<script>
new Vue({ // 创建一个实例
el: "#root", // 接管 id=root 的内容,与 id 为 root 的 DOM 做绑定
template: '<h1>hello {{ msg }}</h1> ',
data: { // 实例中的数据
msg: " world"
}
})
</script>
</body>
</html>
|
数据、事件和方法
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 | <div id="root">
<!-- 插值表达式 -->
<h1> {{ number }}</h1>
<h1 v-text="number"></h1>
<h1 v-html="number"></h1>
<h1 v-text="content"></h1>
<h1 v-html="content"></h1>
</div>
<script>
new Vue({
el: "#root",
data: {
msg: " world",
number: 123,
content: '<h1>hello</h1>'
}
})
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 | <div id="root">
<div v-on:click="handleClick"> {{ content }}</div>
</div>
<script>
new Vue({
el: "#root",
data: {
content: 'hello'
},
methods: {
handleClick: function() {
alert(123);
}
}
})
</script>
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 | <div id="root">
<div v-on:click="handleClick"> {{ content }}</div>
</div>
<script>
new Vue({
el: "#root",
data: {
content: 'hello'
},
methods: {
handleClick: function() {
this.content = "world"
}
}
})
</script>
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 | <div id="root">
<!-- 使用 @ 绑定 -->
<div @click="handleClick"> {{ content }}</div>
</div>
<script>
new Vue({
el: "#root",
data: {
content: 'hello'
},
methods: {
handleClick: function() {
this.content = "world"
}
}
})
|
属性绑定和双向绑定
| <div id="root">
<div v-bind:title="'nocliantro ' + title">hello world</div>
</div>
<script>
new Vue({
el: "#root",
data: {
title: "this is hello world"
}
})
</script>
|
使用冒号 : 代替 v-bind:
| <div id="root">
<div :title="'nocliantro ' + title">hello world</div>
</div>
<script>
new Vue({
el: "#root",
data: {
title: "this is hello world"
}
})
</script>
|
双向绑定
1
2
3
4
5
6
7
8
9
10
11
12
13
14 | <div id="root">
<div :title="title">hello world</div>
<input v-model="content">
<div> {{ content }} </div>
</div>
<script>
new Vue({
el: "#root",
data: {
title: "this is hello world",
content: 'this is content'
}
})
</script>
|
计算属性和侦听器
计算属性
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 | <div id="root">
姓:<input v-model='firstName'>
名:<input v-model='lastName'>
<div> {{ fulltName }} </div>
</div>
<script>
new Vue({
el: "#root",
data: {
firstName: '',
lastName: ''
},
computed: {
fulltName: function() {
return this.firstName + ' ' + this.lastName;
}
}
})
|
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 | <div id="root">
姓:<input v-model='firstName'>
名:<input v-model='lastName'>
<div> {{ fulltName }} </div>
<div> {{ count }} </div>
</div>
<script>
new Vue({
el: "#root",
data: {
firstName: '',
lastName: '',
count: 0,
},
computed: {
fulltName: function() {
return this.firstName + ' ' + this.lastName;
}
},
watch: {
firstName: function() {
this.count++;
},
lastName: function() {
this.count++;
}
}
})
|
侦听计算属性
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 | <div id="root">
姓:<input v-model='firstName'>
名:<input v-model='lastName'>
<div> {{ fulltName }} </div>
<div> {{ count }} </div>
</div>
<script>
new Vue({
el: "#root",
data: {
firstName: '',
lastName: '',
count: 0,
},
computed: {
fulltName: function() {
return this.firstName + ' ' + this.lastName;
}
},
watch: {
fulltName: function() {
this.count++;
},
}
})
</script>
|
v-if,v-show与v-for
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 | <div id="root">
<div v-if="show">hello world</div>
<button @click="handleClick">toggle</button>
</div>
<script>
new Vue({
el: "#root",
data: {
show: true
},
methods: {
handleClick: function() {
this.show = !this.show
}
}
})
</script>
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 | <div id="root">
<div v-show="show">hello world</div>
<button @click="handleClick">toggle</button>
</div>
<script>
new Vue({
el: "#root",
data: {
show: true
},
methods: {
handleClick: function() {
this.show = !this.show
}
}
})
</script>
|
v-if 如果为 false,会直接移除相应标签,v-show 为 false 会设置显示为 none,v-show 一般会效率高一些
v-for 加 key 值可以提升性能,要求 key 值不能相同
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21 | <div id="root">
<div v-show="show">hello world</div>
<button @click="handleClick">toggle</button>
<ul>
<li v-for="(item, index) of list" :key="index">{{ item }}</li>
</ul>
</div>
<script>
new Vue({
el: "#root",
data: {
show: true,
list: [1, 2, 3]
},
methods: {
handleClick: function() {
this.show = !this.show
}
}
})
</script>
|
组件
组件系统是 Vue 的另一个重要概念,因为它是一种抽象,允许我们使用小型、独立和通常可复用的组件构建大型应用。仔细想想,几乎任意类型的应用界面都可以抽象为一个组件树:
在 Vue 里,一个组件本质上是一个拥有预定义选项的一个 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 | <!DOCTYPE html>
<html lang="zh">
<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="example">
<my-component></my-component>
</div>
<script type="text/javascript">
// 定义
var MyComponent = Vue.extend({
template: '<div>A custom component!</div>'
})
// 注册
Vue.component('my-component', MyComponent)
// 创建根实例
new Vue({
el: '#example'
})
</script>
</body>
</html>
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15 | <div id="app">
hello
<my-header></my-header>
</div>
<script type="text/javascript">
Vue.component('my-header', {
template: '<p>this is my header</p>'
})
new Vue({
el: '#app',
data: {
word: 'data content'
}
})
</script>
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 | <div id="app">
hello
<my-header2></my-header2>
</div>
<script type="text/javascript">
var myHeader = Vue.component('my-header', {
template: '<h1>this is my header</h1>'
})
new Vue({
el: '#app',
data: {
word: 'data content'
},
components: {
'my-header2': myHeader
}
})
</script>
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24 | <div id="app">
hello
<my-header></my-header>
</div>
<script type="text/javascript">
var myHeaderChild = Vue.component('my-header', {
template: '<p>I am my header child</p>',
})
var myHeader = Vue.component('my-header', {
template: '<p>this is my header <my-header-child></my-header-child></p>',
components: {
'my-header-child': myHeaderChild
}
})
new Vue({
el: '#app',
data: {
word: 'data content'
},
components: {
'my-header': myHeader
}
})
</script>
|
制作一个极简todolist
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 | <div id="root">
<div>
<input v-model="inputValue">
<button @click="handleSubmit">提交</button>
</div>
<ul>
<li v-for="(item, index) of list" :key="index">
{{ item }}
</li>
</ul>
</div>
<script>
new Vue({
el: "#root",
data: {
inputValue: '',
list: []
},
methods: {
handleSubmit: function() {
this.list.push(this.inputValue)
this.inputValue = ''
}
}
})
</script>
|
组件的拆分
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 | <div id="root">
<div>
<input v-model="inputValue">
<button @click="handleSubmit">提交</button>
</div>
<ul>
<todo-item
v-for="(item, index) of list"
:key="index"
:content="item"
>
</todo-item>
</ul>
</div>
<script>
Vue.component('todo-item', {
props: ['content'],
template: '<li> {{ content }} </li>',
})
new Vue({
el: "#root",
data: {
inputValue: '',
list: []
},
methods: {
handleSubmit: function() {
this.list.push(this.inputValue)
this.inputValue = ''
}
}
})
</script>
|
每一个组件都是一个实例
删除功能
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 | <div id="root">
<div>
<input v-model="inputValue">
<button @click="handleSubmit">提交</button>
</div>
<ul>
<todo-item
v-for="(item, index) of list"
:key="index"
:content="item"
:index="index"
@delete="handleDelete"
>
</todo-item>
</ul>
</div>
<script>
Vue.component('todo-item', {
props: ['content', 'index'],
template: '<li @click="handleClick"> {{ content }} {{ index }} </li>',
methods: {
handleClick: function() {
this.$emit('delete', this.index)
}
}
})
new Vue({
el: "#root",
data: {
inputValue: '',
list: []
},
methods: {
handleSubmit: function() {
this.list.push(this.inputValue)
this.inputValue = ''
},
handleDelete: function(index) {
this.list.splice(index, 1)
}
}
})
</script>
|
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 | <!DOCTYPE html>
<html lang="zh">
<head>
<meta charset="UTF-8">
<title>Todolist</title>
<script src="./vue.js"></script>
</head>
<body>
<div id="app">
<input type="text" v-model="inputValue">
<button @click="handleBtnClick">提交</button>
<ul>
<!-- <li v-for="item in list">{{ item }}</li> -->
<todo-item :content="item"
:index="index"
v-for="(item, index) in list"
@delete="handleItemDelete">
</todo-item>
</ul>
</div>
<script>
// Vue.component("TodoItem", {
// props: ['content'],
// template: "<li>{{ content }}</li>"
// })
var TodoItem = {
props: ['content', 'index'],
template: "<li @click='handleItemClick'>{{ content }}</li>",
methods: {
handleItemClick: function() {
this.$emit("delete", this.index);
}
}
}
var app = new Vue({
el: "#app",
components: {
TodoItem: TodoItem,
},
data: {
list: [],
inputValue: ''
},
methods: {
handleBtnClick: function() {
this.list.push(this.inputValue)
this.inputValue = ''
},
handleItemDelete: function(index) {
this.list.splice(index, 1)
}
}
})
</script>
</body>
</html>
|