Vue学习
- 教程:Vue官网打广告那个教程真是不敢恭维
- 菜鸟教程
安装
作为一款构建前端用户界面的JavaScript框架,我们只需要新建.html文件并引入Vue.js文件即可
- Vue官网
- 编辑器使用Sublime或者其他
- 其他的安装方法和应用构建参看教程
基本操作
创建一个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<body>
<!-- 将来 new 的Vue实例,会控制这个元素中的所有内容 -->
<!-- {{var}} 叫做插值表达式,输出data属性中的数据 -->
<div id="app">
<p>{{msg}}</p>
<p>{{msg2}}</p>
<p>{{msg3}}</p>
<p>{{msg4}}</p>
</div>
<!-- 也可以通过vm.msg直接访问data属性中的数据 -->
<script>
// 创建一个Vue的实例
// 当我们导入包之后,在浏览器的内存中,就多了一个 Vue 构造函数
var vm = new Vue({// el、data等可以称之为属性
el: '#app', // 指明要控制页面上的id为app的区域
data: { // 存放 el 中要用到的数据
msg: 'Hello Vue!', // 通过 Vue 提供的指令,很方便的就能把数据渲染到页面上,不需要手动操作DOM元素了
msg2: 'Hello Vue2!',// 前端的Vue之类的框架,不提倡我们去手动操作DOM元素
msg3: 'Hello Vue3!',
msg4: 'Hello Vue4!'
}
})
</script>
</body>代码可以在谷歌浏览器打开,使用自带的开发者查看并调试
v-cloak
可以解决在网速慢的情况下,插值表达式在浏览器中闪烁的问题1
<p v-cloak>{{msg}}</p>
使用
v-text
同样可以解决闪烁的问题,区别在哪?1
2
3
4<div id='app'>
<p v-cloak>从Vue对象获取数据:{{msg}}</p>
<p v-text="msg">从Vue对象获取数据</p>
</div>运行这段代码我们会发现下面的p标签只输出msg变量的值。即插值表达式可以把Vue传递过来的数据和前台用户自己定义的数据结合在一起,但是v-text只能显示Vue对象传递过来的数据,会替换掉节点里已有的内容
v-html
可以解析html的标签并展示1
2
3
4
5
6
7
8
9
10
11<!--这里不会显示标签里的内容“Vue”-->
<div v-html="msg">Vue</div>
<script>
var vm = new Vue({
el: '#app2',
data: {
},
})
</script>v-bind:xxx
绑定Vue实例中的属性v-on:xxx
绑定实例中的方法methods
,即事件监听指令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<!-- 注意: v-bind: 指令可以被简写为 冒号+要绑定的属性 -->
<!-- v-bind 中,可以写合法的JS表达式 -->
<!-- v-bind:title 作用是鼠标放置在按钮上时的提示文字;指定为mytitle后,还可以拼接其他字符串-->
<!-- Vue.js 都提供了完全的 JavaScript 表达式支持 -->
<input type="button" value="按钮" v-bind:title="mytitle + 'hello'">
<!-- 可传参 -->
<input type="button" value="按钮" :title="mytitle" v-on:click="show2">
<!-- v-on: 绑定方法,可以简写为 @ -->
<input type="button" value="按钮@" @click="show3">
<script>
var vm = new Vue({
el: '#app2',
data: {
msg: '123',
mytitle: '这是一个自己定义的title'
},
methods: { // 这个 methods属性中定义了当前Vue实例所有可用的方法
show2: function () {
alert('Hello')
},
show3(){
alert('Hello World');
}
}
})
</script>1
2
3
4
5
6
7
8
9
10
11
12
13
14<div id="app">
<!-- 可以直接操作data属性 -->
<button v-on:click="counter += 1">增加 1</button>
<p>这个按钮被点击了 {{ counter }} 次。</p>
</div>
<script>
new Vue({
el: '#app',
data: {
counter: 0
}
})
</script>
事件修饰符
为 v-on 提供了事件修饰符来处理 DOM 事件细节
.stop
阻止事件冒泡1
2
3<div class="inner" @click="divHandler">
<input type="button" value="戳他" @click.stop="btnHandler">
</div>.prevent
阻止标签默认行为1
<a href="http://www.baidu.com" @click.prevent="linkClick">有问题去百度</a>
.capture
实现捕获触发事件的机制- 当元素发生冒泡时,先触发带有该修饰符的元素。若有多个该修饰符,则由外而内触发
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15<!--弹出的顺序为:obj1、obj2、obj4、obj3;由于1,2有修饰符,故而先触发事件,然后就是4本身触发,最后冒泡事件。-->
<div id="content">
<div id="obj1" v-on:click.capture="doc">
obj1
<div id="obj2" v-on:click.capture="doc">
obj2
<div id="obj3" v-on:click="doc">
obj3
<div id="obj4" v-on:click="doc">
obj4
</div>
</div>
</div>
</div>
</div>.self
只有点击当前元素时候,才会触发事件处理函数- 可以理解为只会阻止来到自己身上的冒泡事件,不受别人影响,但
.stop
是通知所有冒泡事件
- 可以理解为只会阻止来到自己身上的冒泡事件,不受别人影响,但
.once
只触发一次事件处理函数1
<a href="http://www.baidu.com" @click.prevent.once="linkClick">有问题,先去百度</a>
按键修饰符
监听键盘事件
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18<!-- 记住所有的 keyCode 比较困难,所以 Vue 为最常用的按键提供了别名 -->
<!-- 只有在 keyCode 是 enter 时调用 vm.submit() -->
<input v-on:keyup.enter="submit">
<input @keyup.enter="submit">
//全部别名:
.enter
.tab
.delete (捕获 "删除" 和 "退格" 键)
.esc
.space
.up
.down
.left
.right
.ctrl
.alt
.shift
.meta
v-show
与v-if
的区别1
2
3
4
5<!-- 如果元素涉及到频繁的切换,最好不要使用 v-if, 而是推荐使用 v-show -->
<!-- 如果元素可能永远也不会被显示出来被用户看到,则推荐使用 v-if -->
<h3 v-if="flag">这是用v-if控制的元素</h3>
<!-- 若flag=false,则样式切换为display:none,而不是消失 -->
<h3 v-show="flag">这是用v-show控制的元素</h3>v-model
实现双向绑定- 即同时实现
data
属性中的数据渲染和修改
- 即同时实现
自动绑定表单元素的相关标签
value
值,更新修改1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19<div id="app">
<!-- v-bind 只能实现数据的单向绑定 -->
<input type="text" v-bind:value="msg" style="width:100%;">
<!-- 可以实现 表单元素和 Model 中数据的双向数据绑定 -->
<!-- 注意: v-model 只能运用在 表单元素中 -->
<input type="text" style="width:100%;" v-model="msg">
</div>
<script>
// 创建 Vue 实例,得到 ViewModel
var vm = new Vue({
el: '#app',
data: {
msg: '大家都是好学生,爱敲代码,爱学习,爱思考,简直是完美!'
},
methods: {
}
});
</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<div id="app">
<p>单个复选框:</p>
<input type="checkbox" id="checkbox" v-model="checked">
<!--for 属性规定 label 与哪个表单元素绑定-->
<label for="checkbox">{{ checked }}</label>
<p>多个复选框:</p>
<input type="checkbox" id="baidu" value="Baidu" v-model="checkedNames">
<label for="baidu">Baidu</label>
<input type="checkbox" id="google" value="Google" v-model="checkedNames">
<label for="google">Google</label>
<input type="checkbox" id="taobao" value="Taobao" v-model="checkedNames">
<label for="taobao">taobao</label>
<br>
<span>选择的值为: {{ checkedNames }}</span>
</div>
<script>
new Vue({
el: '#app',
data: {
checked : false,
checkedNames: []
}
})
</script>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20<div id="app">
<select v-model="selected" name="fruit">
<option value="">选择一个网站</option>
<option value="www.baidu.com">Baidu</option>
<option value="www.google.com">Google</option>
</select>
<div id="output">
选择的网站是: {{selected}}
</div>
</div>
<script>
new Vue({
el: '#app',
data: {
selected: ''
}
})
</script>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18<div id="app">
<input type="radio" id="runoob" value="Baidu" v-model="picked">
<label for="runoob">Baidu</label>
<br>
<input type="radio" id="google" value="Google" v-model="picked">
<label for="google">Google</label>
<br>
<span>选中值为: {{ picked }}</span>
</div>
<script>
new Vue({
el: '#app',
data: {
picked : 'Runoob'
}
})
</script>
样式
:class
和:style
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
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
<script src="./lib/vue-2.4.0.js"></script>
<style>
.red {
color: red;
}
.thin {
font-weight: 200;
}
.italic {
font-style: italic;
}
.active {
letter-spacing: 0.5em;
}
</style>
</head>
<body>
<div id="app">
<h1 class="red thin">这是一个很大很大的H1,大到你无法想象!!!</h1>
<!-- 第一种使用方式,直接传递一个数组,注意: 这里的 class 需要使用 v-bind 做数据绑定 -->
<h1 :class="['thin', 'italic']">这是一个很大很大的H1,大到你无法想象!!!</h1>
<!-- 在数组中使用三元表达式 -->
<h1 :class="['thin', 'italic', flag?'active':'']">这是一个很大很大的H1,大到你无法想象!!!</h1>
<!-- 在数组中使用 对象来代替三元表达式,提高代码的可读性 -->
<h1 :class="['thin', 'italic', {'active':flag} ]">这是一个很大很大的H1,大到你无法想象!!!</h1>
<!-- 在为 class 使用 v-bind 绑定 对象的时候,对象的属性是类名,由于对象的属性可带引号,也可不带引号,所以这里我没写引号; 属性的值是一个标识符 -->
<h1 :class="classObj">这是一个很大很大的H1,大到你无法想象!!!</h1>
</div>
<script>
var vm = new Vue({
el: '#app',
data: {
flag: true,
classObj: { red: true, thin: true, italic: false, active: false }
},
methods: {}
});
</script>
</body>
</html>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18<div id="app">
<!-- 对象就是键值对的集合 -->
<h1 :style="styleObj1">这是一个h1</h1>
<!-- 可以使用数组-->
<h1 :style="[ styleObj1, styleObj2 ]">这是一个h1</h1>
</div>
<!-- 当 v-bind:style 使用需要特定前缀的 CSS 属性时,如 transform ,Vue.js 会自动 侦测并添加相应的前 -->
<script>
var vm = new Vue({
el: '#app',
data: {
styleObj1: { color: 'red', 'font-weight': 200 },
styleObj2: { 'font-style': 'italic' }
},
methods: {}
});
</script>
循环
循环普通数组
1
2<p v-for="item in list">{{item}}</p>
<p v-for="(item, i) in list">索引值:{{i}} --- 元素:{{item}}</p>循环对象数组
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18<div id="app">
<p v-for="(user, i) in list">Id:{{ user.id }} --- 名字:{{ user.name }} --- 索引:{{i}}</p>
</div>
<script>
var vm = new Vue({
el: '#app',
data: {
list: [
{ id: 1, name: 'zs1' },
{ id: 2, name: 'zs2' },
{ id: 3, name: 'zs3' },
{ id: 4, name: 'zs4' }
]
},
methods: {}
});
</script>注:都是遍历实例data属性中的数据
循环对象
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18<div id="app">
<!-- 注意:在遍历对象身上的键值对的时候, 除了有val key ,在第三个位置还有 一个 索引 -->
<p v-for="(val, key, i) in user">值是: {{ val }} --- 键是: {{key}} -- 索引: {{i}}</p>
</div>
<script>
var vm = new Vue({
el: '#app',
data: {
user: {
id: 1,
name: '托尼·赵四',
gender: '男'
}
},
methods: {}
});
</script>1
2
3
4
5
6
7
8
9
10
11
12
13<div id="app">
<!-- in 后面可以放普通数组,对象数组,对象,还可以放数字 -->
<!-- 注意:如果使用 v-for 迭代数字的话,前面的 count 值从 1 开始 -->
<p v-for="count in 10">这是第 {{ count }} 次循环</p>
</div>
<script>
var vm = new Vue({
el: '#app',
data: {},
methods: {}
});
</script>在使用for循环操作标签时,需要注意
1
2
3
4<!--在一些特殊情况中,如果 v-for 有问题,必须在使用 v-for 的同时,指定唯一的 字符串/数字类型 :key 值,使用v-bind绑定-->
<p v-for="item in list" :key="item.id">
<input type="checkbox">{{item.id}} --- {{item.name}}
</p>
过滤器
用作一些常见的文本格式化。由”管道符”指示, 格式如下:
1
2
3
4
5<!-- 在两个大括号中 -->
{{ message | capitalize }}
<!-- 在 v-bind 指令中 -->
<div v-bind:id="rawId | formatId"></div>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20<div id="app">
{{ message | capitalize }}
</div>
<script>
new Vue({
el: '#app',
data: {
message: 'runoob'
},
filters: {
capitalize: function (value) {
if (!value) return ''
value = value.toString()
return value.charAt(0).toUpperCase() + value.slice(1)
// 字符串第一个字母转为大写
}
}
})
</script>过滤器可以串联
1
{{ message | filterA | filterB }}
过滤器是 JavaScript 函数,因此可以接受参数
1
2{{ message | filterA('arg1', arg2) }}
// message 是第一个参数,'arg1' 作为第二个参数, arg2 表达式的值将被求值然后作为第三个参数
计算属性
在处理一些复杂逻辑时很有用
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21<!-- 使用computed关键字 -->
<div id="app">
<p>原始字符串: {{ message }}</p>
<p>计算后反转字符串: {{ reversedMessage }}</p>
</div>
<script>
var vm = new Vue({
el: '#app',
data: {
message: 'Roykun!'
},
computed: {
// 相当于新的属性变量
reversedMessage: function () {
// `this` 指向 vm 实例
return this.message.split('').reverse().join('')
}
}
})
</script>和methods方法在效果上一样,但是computed 是基于它的依赖缓存,可以说使用 computed 性能会更好,但是会产生缓存
默认的computed只有
get
属性,可以编写set
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
26var vm = new Vue({
el: '#app',
data: {
name: 'Google',
url: 'http://www.google.com'
},
computed: {
site: {
// getter
get: function () {
return this.name + ' ' + this.url
},
// setter
set: function (newValue) { // 接收传值
var names = newValue.split(' ')
this.name = names[0]
this.url = names[names.length - 1]
}
}
}
})
// 调用 setter, vm.name 和 vm.url 也会被对应更新
vm.site = '菜鸟教程 http://www.baidu.com';
document.write('name: ' + vm.name);
document.write('<br>');
document.write('url: ' + vm.url);
watch
监听1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18<div id = "app">
<p style = "font-size:25px;">计数器: {{ counter }}</p>
<!-- 直接在这写表达式 -->
<button @click = "counter++" style = "font-size:25px;">点我</button>
</div>
<script type = "text/javascript">
var vm = new Vue({
el: '#app',
data: {
counter: 1
}
});
// $watch 是一个实例方法
// 这个回调将在 vm.counter 改变后调用
vm.$watch('counter', function(newVal, oldVal) {
alert('计数器值的变化 :' + oldVal + ' 变为 ' + newVal + '!');
});
</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<div id = "computed_props">
千米 : <input type = "text" v-model = "kilometers">
米 : <input type = "text" v-model = "meters">
</div>
<p id="info"></p>
<script type = "text/javascript">
var vm = new Vue({
el: '#computed_props',
data: {
kilometers : 0,
meters:0
},
watch : {
kilometers:function(val) {
this.kilometers = val;
this.meters = this.kilometers * 1000
},
meters : function (val) {
this.kilometers = val/ 1000;
this.meters = val;
}
}
});
// $watch 是一个实例方法
vm.$watch('kilometers', function (newValue, oldValue) {
// 这个回调将在 vm.kilometers 改变后调用
document.getElementById ("info").innerHTML = "修改前值为: " + oldValue + ",修改后值为: " + newValue;
})
</script>