认识Vue.js

Vue是一套用于构建用户界面的渐进式框架

安装方式

  • 直接CDN引入
    1
    2
    3
    4
    <!-- 开发环境版本,包含了有帮助的命令行警告 -->
    <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
    <!-- 生产环境版本,优化了尺寸和速度 -->
    <script src="https://cdn.jsdelivr.net/npm/vue"></script>
  • 下载和引入(直接右键将链接另存为即可)开发版本 生产版本
  • npm安装

MVVM

定义

MVVM(Model–view–viewmodel)是一种软件架构模式。

MVVM有助于将图形用户界面的开发与业务逻辑或后端逻辑(数据模型)的开发分离开来,这是通过置标语言或GUI代码实现的。MVVM的视图模型是一个值转换器,这意味着视图模型负责从模型中暴露(转换)数据对象,以便轻松管理和呈现对象。在这方面,视图模型比视图做得更多,并且处理大部分视图的显示逻辑。视图模型可以实现中介者模式,组织对视图所支持的用例集的后端逻辑的访问。

Vue中的MVVM

Vue的生命周期

简单入门

Hello,Vue!

{{message}}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<body>
<div id="app">
{{message}}
</div>
<script>
//let 变量 const 常量
//编程范式:声明式编程
const app = new Vue({
//用于挂载数据的元素
el: '#app',
data: {
message: 'Hello,Vue!'
}
})
</script>
</body>

简单遍历v-for

  • {{item}}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<body>
<div id="app">
<ul>
<li v-for="item in books">
{{item}}
</li>
</ul>
</div>
<script>
const app = new Vue({
el:'#app',
data:{
books:['西游记','水浒传','三国演义','红楼梦']
}
})
</script>
</body>

点击事件v-on:click

当前计数:{{counter}}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<body>
<div id="app">
<h2>当前计数:{{counter}}</h2>
<button class="vue-button" v-on:click="counter--">-</button>
<button class="vue-button" v-on:click="counter++">+</button>
</div>
<script>
const app3 = new Vue({
el:'#app',
data:{
counter:0
}
})
</script>
</body>
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
<body>
<div id="app">
<h2>当前计数:{{counter}}</h2>
<button class="vue-button" @click="sub">-</button>
<button class="vue-button" @click="add">+</button>
</div>
<script>
const app = new Vue({
el:'#app',
data:{
counter:0
},
methods:{
add:function () {
console.log('add');
this.counter++;
},
sub:function () {
console.log('sub');
this.counter--;
}
}
})
</script>
</body>

按html渲染v-html

{{url}}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
<body>
<div id="app">
<h1>{{url}}</h1>
<h1 v-html="url"></h1>
</div>
<script>
let app = new Vue({
el:'#app',
data:{
url:'<a href="https://baidu.com">百度一下</a>'
},
})
</script>
</body>

不对内容进行渲染v-pre

{{url}}
1
2
3
4
5
6
7
8
9
10
11
12
13
<body>
<div id="app">
<h1 v-pre>{{url}}</h1>
</div>
<script>
let app = new Vue({
el:'#app',
data:{
url:'<a href="https://baidu.com">百度一下</a>'
},
})
</script>
</body>

v-cloak

  • cloak(斗篷)
  • vue解析后v-cloak属性会消失
  • 刷新页面以查看效果
{{url}}
{{url}}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
<body>
<style>
[v-cloak] {
display: none;
}
</style>
<div id="app">
<h1 v-cloak>{{url}}</h1>
<h1>{{url}}</h1>
</div>
<script>
//vue解析后v-cloak属性会消失
setTimeout(() => {
let app = new Vue({
el: '#app',
data: {
url: '<a href="https://baidu.com">百度一下</a>'
},
})
}, 1000);
</script>
</body>

属性绑定v-bind

基本使用

v-bind可以往元素的属性中绑定数据,也可以动态地根据数据为元素绑定不同的样式。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<body>
<div id="app">
<img v-bind:src="url" alt="">
<!-- 语法糖写法 -->
<img :src="url" alt="">
</div>
<script>
const app = new Vue({
el:'#app',
data() {
return {
url:'https://gitee.com/ETFTS/biliemoji/raw/master/emojis/4cd1024d0c2ecee93224477946656d32c1705ccf.png@50w_50h.webp'
}
},
})
</script>
</body>

对象写法

{{message}}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
<body>
<style>
.v-class-1{
color: red;
}
.v-class-2{
color: green;
}
</style>
<div id="app">
<h1 :class="{'v-class-1':bool1,'v-class-2':bool2}">{{message}}</h1>
<button class="vue-button" @click="bool1=!bool1;bool2=!bool2">点我</button>
</div>
<script>
const app = new Vue({
el:'#app',
data:{
message:'hello world',
bool1:true,
bool2:false
}
})
</script>
</body>

数组写法

{{message}}
{{message}}
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
<body>
<style>
.v-class-1{
color: red;
}
.v-class-2{
text-decoration: underline;
}
</style>
<div id="app">
<h1 :class="getClasses()">{{message}}</h1>
<h1 :class="[class1,class2]">{{message}}</h1>
</div>
<script>
const app = new Vue({
el:'#app',
data:{
message:'hello world',
class1:'v-class-1',
class2:'v-class-2',
},
methods: {
getClasses:function () {
return [this.class1,this.class2]
}
},
})
</script>
</body>

v-bindv-for使用示例

目的:点击列表中的元素该元素会显示为红色

  • {{m}}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
<body>
<style>
.v-onclick{color: red;}
</style>
<div id="app">
<ul>
<li v-for="(m,i) in books" @click="bookClick(i)" :class="{'v-onclick':currentIndex === i}">{{m}}</li>
</ul>
</div>
<script>
const app = new Vue({
el:'#app',
data:{
books:['西游记','水浒传','三国演义','红楼梦'],
currentIndex:0
},
methods: {
bookClick: function (i) {
this.currentIndex=i;
}
},
})
</script>
</body>

购物车的简单实现

编号 书籍名称 出版日期 价格 购买数量 操作
{{item.id}} {{item.name}} {{item.time}} {{item.price | priceFilter}} {{item.count}}
总价格:{{totalPrice | priceFilter}}
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
<body>
<style>
table,th,td,td {
border-collapse: collapse;
border: solid 1px;
padding: 5px 15px;
}
</style>
<div id="app">
<table>
<tr>
<th>编号</th>
<th>书籍名称</th>
<th>出版日期</th>
<th>价格</th>
<th>购买数量</th>
<th>操作</th>
</tr>
<tr v-for="(item,index) in books">
<td>{{item.id}}</td>
<td>{{item.name}}</td>
<td>{{item.time}}</td>
<td>{{item.price | priceFilter}}</td>
<td>
<button class="vue-button" @click="decrementCount(index)" :disabled="item.count <= 1">-</button>
{{item.count}}
<button class="vue-button" @click="incrementCount(index)">+</button>
</td>
<td><button class="vue-button" @click="removeBook(index)">移除</button></td>
</tr>
</table>
<h2>总价格:{{totalPrice | priceFilter}}</h2>
</div>
<script>
const app = new Vue({
el: '#app',
data: {
books: [
{ id: 1, name: '《西游记》', time: '2006-9', price: 85.00, count: 1 },
{ id: 2, name: '《水浒传》', time: '2006-2', price: 95.00, count: 1 },
{ id: 3, name: '《三国演义》', time: '2006-10', price: 100.00, count: 1 },
{ id: 4, name: '《红楼梦》', time: '2006-3', price: 55.00, count: 1 },
]
},
methods: {
incrementCount(index) {
this.books[index].count++;
},
decrementCount(index) {
this.books[index].count--;
},
removeBook(index) {
this.books.splice(index, 1)
}
},
computed: {
totalPrice() {
let sum = 0;
for (const book of this.books) {
sum += book.price * book.count;
}
return sum;
}
},
filters:{
priceFilter(price){
return '¥ '+price.toFixed(2)
}
}
})
</script>
</body>

阶段尝试

  • {{question.title}} {{question.answer}}
  • {{question.title}} {{question.answer}}
  • {{question.title}} {{question.answer}}
  • {{titleSplit}}
  • {{question.answer}}
  • {{question.title}} {{question.answer}}
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
<body>
<style>
* {
margin: 0;
padding: 0;
font-size: 14px;
}

.question li {
list-style: none;
}

.question li:first-child {
font-weight: bold;
}

.line-input{
border: 0;
outline: 0;
border-bottom: solid 1px;
max-width: 5em;
}
</style>
<div id="app">
<ul v-for="(question,qIndex) in questions">
<!-- 单选 -->
<div class="question" v-if="question.type===0">
<li>{{question.title}} {{question.answer}}</li>
<li v-for="(selection,sIndex) in question.selections">
<input type="radio" :id="'q'+qIndex+'-'+sIndex" :name="'q'+qIndex" :value="'ABCD'[sIndex]"
v-model.lazy="question.answer">
<label :for="'q'+qIndex+'-'+sIndex">{{'ABCD'[sIndex] + '.'}}{{selection}}</label>
</li>
</div>
<!-- 多选 -->
<div class="question" v-else-if="question.type===1">
<li>{{question.title}} {{question.answer}}</li>
<li v-for="(selection,sIndex) in question.selections">
<input type="checkbox" :id="'q'+qIndex+'-'+sIndex" :name="'q'+qIndex" :value="'ABCD'[sIndex]"
v-model.lazy="question.answer">
<label :for="'q'+qIndex+'-'+sIndex">{{'ABCD'[sIndex] + '.'}}{{selection}}</label>
</li>
</div>
<!-- 判断 -->
<div class="question" v-else-if="question.type===2">
<li>{{question.title}} {{question.answer}}</li>
<li v-for="(selection,sIndex) in ['正确','错误']">
<input type="radio" :id="'q'+qIndex+'-'+sIndex" :name="'q'+qIndex" :value="[true,false][sIndex]"
v-model.lazy="question.answer">
<label :for="'q'+qIndex+'-'+sIndex">{{selection}}</label>
</li>
</div>
<!-- 填空 -->
<div class="question" v-else-if="question.type===3">
<li>
<span v-for="(titleSplit,tIndex) in question.title.split('__')">
{{titleSplit}}
<input type="text" :id="'q'+qIndex+'-'+tIndex" :name="'q'+qIndex" v-if="tIndex<question.title.split('__').length-1" v-model.lazy="question.answer[tIndex]" class="line-input" :title="question.answer[tIndex]">
</span>
</li>
{{question.answer}}
</div>
<!-- 简答 -->
<div class="question" v-else-if="question.type===4">
<li>{{question.title}} {{question.answer}}</li>
<textarea :name="'q'+qIndex" v-model.lazy="question.answer"></textarea>
</div>
<!-- END -->
</ul>
</div>
<script>
const app = new Vue({
el: '#app',
data: {
questions: [
{
type: 0,
title: '选择题(单选)',
selections: ['单选选项1', '单选选项2', '单选选项3', '单选选项4'],
t_answer: 'A',
answer:''
},
{
type: 1,
title: '选择题(多选)',
selections: ['多选选项1', '多选选项2', '多选选项3', '多选选项4'],
t_answer: ['A', 'B', 'C'],
answer:[]
},
{
type: 2,
title: '判断题',
t_answer: true,
answer:''
},
{
type: 3,
title: '填空题:阿斯达四大__阿斯达四大__奥术大师大所多__阿斯达四大__啊啊啊啊',
t_answer: ['答案1', '答案2', '答案3', '答案4'],
answer:[]
},
{
type: 4,
title: '简答题',
t_answer: 'asdas',
answer:''
}
]
}
})
</script>
</body>