1. 重点提炼
- 指令
- 内容
- v-text
- v-html
- v-pre
- v-once
- v-cloak
- 循环
- v-for
- :key
- 逻辑
- v-show
- v-if
- v-else
- v-else-if
- 属性
- v-bind
- 简写::
- 普通属性
- style
- class
- v-model
- 表单
- text、textarea
- radio、checkbox、select
- 指令
- 名称
- 值
- 参数
- 修饰符
- lazy
- trim
- capture
- stop
- self
- …
- 格式:指令名称:参数.修饰符1
.修饰符
2="值"
2. 指令
指令可以配合我们的模板,在React
当中想输出带有逻辑的模板,是根据js
,然后配合jsx
生成。在vue
中提供类似模板语法的内容,即指令。
指令可以更改当前我们在渲染过程当中当前的该元素的渲染结果和渲染行为,即指令作用于元素。
表达式的值除了可以出现内容中,也可以使用在其它位置,比如:属性。但是不能使用 {{}}
语法,而是需要 指令
在 vue
中,指令是一个带有 v-
前缀的属性,与普通属性不一样的地方在于,指令的值是引号括起来的 表达式
,不同的指令有不同的作用,依附于某个元素的指令,它会对当前所在元素产生一些效果,影响它的一些行为。
vue
内置了一些常用的指令,后期我们还可以自定义属于自己的指令。
根据指令所代表不同的内容和结果,我们把它分类成:
- 内容输出
- 循环
- 逻辑
- 属性绑定
- 事件
- 其它
3. 内容输出
通过 {{}}
我们可以很方便的中模板中输出数据,但是这种方式会有一个问题,当页面加载渲染比较慢的时候,页面中会出现 {{}}
,vue
提供了几个指令来解决这个问题
指令中的表达式不需要使用
{{}}
3.1 v-text
<p v-text="title"></p>
弊端:
v-text
会填充整个innerHTML
3.1.1 example01
3.1.1.1 example01-1
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<style>
</style>
</head>
<body>
<div id="app">
<h1>hello,{{title}}</h1>
<hr>
<p v-text="title">hello,</p>
</div>
<script src="./js/vue.js"></script>
<script>
let app = new Vue({
el: '#app',
data: {
title: '111-222',
arr: ['a', 'b']
}
});
</script>
</body>
</html>
{{}}
只是替换了一部分,而v-text
会填充整个 innerHTML
指令当中v-text
中填写的是表达式
,"title"
会被当作变量去解析成title
,千万别写错成“{{title}}”
,它直接是表达式,而不需要大胡子语法。
参考:https://https://github.com/6xiaoDi/blog-vue-Novice/tree/a0.16
Branch: branch01commit description:a0.16(example01-1——v-text使用demo)
tag:a0.16
3.1.1.2 example01-2
<p v-text="'title'">hello,</p>
参考:https://https://github.com/6xiaoDi/blog-vue-Novice/tree/a0.17
Branch: branch01commit description:a0.17(example01-2——v-text使用注意事项)
tag:a0.17
3.1.1.3 example01-3
v-text
与{{}}
差异性
用之前学的延迟挂载
表现=>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<style>
</style>
</head>
<body>
<div id="app">
<h1>hello,{{title}}</h1>
<hr>
<p v-text="title">hello,</p>
</div>
<script src="./js/vue.js"></script>
<script>
let app = new Vue({
// el: '#app',
data: {
title: '111-222',
arr: ['a', 'b']
}
});
setTimeout(() => {
app.$mount('#app')
}, 5000);
</script>
</body>
</html>
{{}}
大胡子语法,在解析前,在页面当中是可以看到东西的,然后解析完成后才能看到真实想要的东西。
两者的表现形式是不一样的,通过 {{}}
我们可以很方便的中模板中输出数据,但是这种方式会有一个问题,当页面加载渲染比较慢的时候,页面中会出现 {{}}
参考:https://https://github.com/6xiaoDi/blog-vue-Novice/tree/a0.18
Branch: branch01commit description:a0.18(example01-3——v-text与{{}}差异性)
tag:a0.18
3.2 v-cloak
<p v-cloak>{{title}}</p>
需要配合 css 进行处理
<style>
[v-cloak] {
display: none;
}
</style>
v-cloak
比v-text
用得更多,因为更优。
3.2.1 example02
3.2.1.1 example02-1
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<style>
</style>
</head>
<body>
<div id="app">
<h1>hello,{{title}}</h1>
<hr>
<p v-text="title">hello,</p>
<hr>
<p v-cloak>{{title}}</p>
</div>
<script src="./js/vue.js"></script>
<script>
let app = new Vue({
// el: '#app',
data: {
title: '111-222',
arr: ['a', 'b']
}
});
setTimeout(() => {
app.$mount('#app')
}, 9000);
</script>
</body>
</html>
看起来它与大胡子语法很类似,但有一个非常特殊的地方就是,{{title}}
是会显示在html
模板中的,它可配合css
选择器处理,让其不显示。
参考:https://https://github.com/6xiaoDi/blog-vue-Novice/tree/a0.19
Branch: branch01commit description:a0.19(example02-1——v-cloak的demo)
tag:a0.19
3.2.1.2 example02-2
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<style>
[v-cloak] {
display: none;
}
</style>
</head>
<body>
<div id="app">
<h1>hello,{{title}}</h1>
<hr>
<p v-text="title">hello,</p>
<hr>
<p v-cloak>{{title}}</p>
</div>
<script src="./js/vue.js"></script>
<script>
let app = new Vue({
// el: '#app',
data: {
title: '111-222',
arr: ['a', 'b']
}
});
setTimeout(() => {
app.$mount('#app')
}, 9000);
</script>
</body>
</html>
在渲染之前,display:none
是生效的,而渲染之后它就会被干掉,<p v-cloak>{{title}}</p>
就显示出来了。
参考:https://https://github.com/6xiaoDi/blog-vue-Novice/tree/a0.20
Branch: branch01commit description:a0.20(example02-2——v-cloak与CSS配合)
tag:a0.20
3.2.1.3 example02-3
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<style>
[v-text],
[v-cloak]{
display: none;
}
</style>
</head>
<body>
<div id="app">
<h1>hello,{{title}}</h1>
<hr>
<p v-text="title">hello,</p>
<hr>
<p v-cloak>{{title}}</p>
</div>
<script src="./js/vue.js"></script>
<script>
let app = new Vue({
// el: '#app',
data: {
title: '111-222',
arr: ['a', 'b']
}
});
setTimeout(() => {
app.$mount('#app')
}, 9000);
</script>
</body>
</html>
实际上v-text
和v-cloak
都可以处理此种行为。
参考:https://https://github.com/6xiaoDi/blog-vue-Novice/tree/a0.21
Branch: branch01commit description:a0.21(example02-3——v-cloak与v-text都可配合css)
tag:a0.21
3.3 v-html
为了防止 xss
攻击,默认情况下输出是不会作为 html
解析的,通过 v-html
可以让内容作为 html
进行解析
3.3.1 example03
3.3.1.1 example03-1
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<style>
[v-text],
[v-cloak]{
display: none;
}
</style>
</head>
<body>
<div id="app">
<h1>hello,{{title}}</h1>
<hr>
<p v-text="title">hello,</p>
<hr>
<p v-cloak>{{title}}</p>
<hr>
<p>{{content}}}</p>
</div>
<script src="./js/vue.js"></script>
<script>
let app = new Vue({
// el: '#app',
data: {
title: '111-222',
arr: ['a', 'b'],
content: '<h1>Github</h1>', //xss
}
});
setTimeout(() => {
app.$mount('#app')
}, 1);
</script>
</body>
</html>
为了防止 xss
攻击,这里是作为字符串解析的,而不是直接解析成html。
参考:https://https://github.com/6xiaoDi/blog-vue-Novice/tree/a0.22
Branch: branch01commit description:a0.22(example03-1——为了防止
xss
攻击,默认情况下输出是不会作为html
解析的)tag:a0.22
3.3.1.2 example03-2
除非确定是十分安全的,才用指令v-html
可以让内容作为 html
进行解析。
<p v-html="content"></p>
参考:https://https://github.com/6xiaoDi/blog-vue-Novice/tree/a0.23
Branch: branch01commit description:a0.23(example03-2——引入v-html)
tag:a0.23
3.4 v-once
只渲染元素和组件一次,后期的更新不再渲染
3.5 v-pre
忽略这个元素和它子元素内容的编译
3.5.1 example04
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<style>
[v-text],
[v-cloak]{
display: none;
}
</style>
</head>
<body>
<div id="app">
<h1>hello,{{title}}</h1>
<hr>
<p v-text="title">hello,</p>
<hr>
<p v-cloak>{{title}}</p>
<hr>
<!-- <p>{{content}}}</p>-->
<p v-html="content"></p>
<hr>
<p v-pre>{{title}}</p>
</div>
<script src="./js/vue.js"></script>
<script>
let app = new Vue({
// el: '#app',
data: {
title: '111-222',
arr: ['a', 'b'],
content: '<h1>Github</h1>', //xss
}
});
setTimeout(() => {
app.$mount('#app')
}, 1);
</script>
</body>
</html>
也可配合其他模板引擎进行处理,其他模板引擎也有类似这种的输出语法,为了避免冲突,可以采用这种方式。
参考:https://https://github.com/6xiaoDi/blog-vue-Novice/tree/a0.24
Branch: branch01commit description:a0.24(example04——v-pre的使用)
tag:a0.24
4. 逻辑处理
4.1 v-show
根据表达式的值(布尔值),切换元素的显示与隐藏(display 属性)
适用于状态切换比较频繁的情况,频繁显示与隐藏切换,如选项卡、下拉式菜单,点击显示再点击隐藏等
4.1.1 example05
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<style>
[v-text],
[v-cloak]{
display: none;
}
</style>
</head>
<body>
<div id="app">
<h1>hello,{{title}}</h1>
<hr>
<p v-text="title">hello,</p>
<hr>
<p v-cloak>{{title}}</p>
<hr>
<!-- <p>{{content}}}</p>-->
<p v-html="content"></p>
<hr>
<p v-pre>{{title}}</p>
<hr>
<p v-show="isShow">{{title}}</p>
</div>
<script src="./js/vue.js"></script>
<script>
let app = new Vue({
// el: '#app',
data: {
title: '111-222',
arr: ['a', 'b'],
content: '<h1>Github</h1>', //xss
isShow: true
}
});
setTimeout(() => {
app.$mount('#app')
}, 1);
</script>
</body>
</html>
改成false
,就隐藏了
isShow: false,
参考:https://https://github.com/6xiaoDi/blog-vue-Novice/tree/a0.25
Branch: branch01commit description:a0.25(example05——v-show的使用)
tag:a0.25
4.2 v-if
根据表达式的值(布尔值),创建或销毁元素
适用于状态切换不频繁的情况,如用户登录显示一个东西,没登录显示另一个东西,因为用户不可能频繁登录和退出。
4.2.1 example06
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<style>
[v-text],
[v-cloak]{
display: none;
}
</style>
</head>
<body>
<div id="app">
<h1>hello,{{title}}</h1>
<hr>
<p v-text="title">hello,</p>
<hr>
<p v-cloak>{{title}}</p>
<hr>
<!-- <p>{{content}}}</p>-->
<p v-html="content"></p>
<hr>
<p v-pre>{{title}}</p>
<hr>
<p v-show="isShow">{{title}}</p>
<hr>
<p v-if="isShow">{{title}}</p>
</div>
<script src="./js/vue.js"></script>
<script>
let app = new Vue({
// el: '#app',
data: {
title: '111-222',
arr: ['a', 'b'],
content: '<h1>Github</h1>', //xss
isShow: false
}
});
setTimeout(() => {
app.$mount('#app')
}, 1);
</script>
</body>
</html>
连标签都没生成
isShow: true,
v-show
是根据isShow
的真假显示或隐藏该元素,而v-if
则表示该元素是创建还是销毁的。
参考:https://https://github.com/6xiaoDi/blog-vue-Novice/tree/a0.26
Branch: branch01commit description:a0.26(example06——v-if的使用)
tag:a0.26
4.3 v-else / v-else-if
与 v-else
配合
4.3.1 example07
4.3.1.1 example07-1
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<style>
[v-text],
[v-cloak]{
display: none;
}
</style>
</head>
<body>
<div id="app">
<h1>hello,{{title}}</h1>
<hr>
<p v-text="title">hello,</p>
<hr>
<p v-cloak>{{title}}</p>
<hr>
<!-- <p>{{content}}}</p>-->
<p v-html="content"></p>
<hr>
<p v-pre>{{title}}</p>
<hr>
<p v-show="isShow">{{title}}</p>
<hr>
<p v-if="isShow">{{title}}</p>
<hr>
<div v-if="isLogin">用户01</div>
<div v-else>请登录</div>
</div>
<script src="./js/vue.js"></script>
<script>
let app = new Vue({
// el: '#app',
data: {
title: '111-222',
arr: ['a', 'b'],
content: '<h1>Github</h1>', //xss
isShow: true,
isLogin: true
}
});
setTimeout(() => {
app.$mount('#app')
}, 1);
</script>
</body>
</html>
设置false
,重新渲染为请登录
。
参考:https://https://github.com/6xiaoDi/blog-vue-Novice/tree/a0.27
Branch: branch01commit description:a0.27(example07-1——v-else的使用)
tag:a0.27
4.3.1.2 example07-2
<div v-if="isLogin">用户01</div>
<button>111</button>
<div v-else>请登录</div>
会报错,注意v-if
和v-else
两者千万不能隔开,必须连起来。
参考:https://https://github.com/6xiaoDi/blog-vue-Novice/tree/a0.28
Branch: branch01commit description:a0.28(example07-2——v-else的使用注意事项)
tag:a0.28
4.3.1.3 example07-3
那怎么解决中间放一个元素呢?
<div v-if="isLogin">
<span>用户01</span>
<button>111</button>
</div>
<div v-else>
<button>111</button>
<span>请登录</span>
</div>
可是这种变通,导致多一个div
结构出来,怎么解决呢?
<template v-if="isLogin">
<span>用户01</span>
<button>111</button>
</template>
<template v-else>
<button>111</button>
<span>请登录</span>
</template>
template
不会生出任何标签出来。
参考:https://https://github.com/6xiaoDi/blog-vue-Novice/tree/a0.29
Branch: branch01commit description:a0.29(example07-3——v-else中间加入元素的最佳解决方案)
tag:a0.29
5. 循环与列表
5.1 v-for
根据数据循环渲染 v-for
指令所在的元素及其子元素(与原生js
的for-in
使用基本一致)
可以循环的数据:Array | Object | number | string | Iterable (2.6 新增)
<div v-for="item in items"></div>
<div v-for="(item, index) in items"></div>
<div v-for="(val, key) in object"></div>
<div v-for="(val, key, index) in object"></div>
v-for 中也可以使用 of 语法,在 vue 中两者没有什么区别
5.1.1 example08
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<style>
[v-text],
[v-cloak]{
display: none;
}
</style>
</head>
<body>
<div id="app">
<h1>hello,{{title}}</h1>
<hr>
<p v-text="title">hello,</p>
<hr>
<p v-cloak>{{title}}</p>
<hr>
<!-- <p>{{content}}}</p>-->
<p v-html="content"></p>
<hr>
<p v-pre>{{title}}</p>
<hr>
<p v-show="isShow">{{title}}</p>
<hr>
<p v-if="isShow">{{title}}</p>
<hr>
<template v-if="isLogin">
<span>用户01</span>
<button>111</button>
</template>
<template v-else>
<button>111</button>
<span>请登录</span>
</template>
<hr>
<div v-for="(val, key, index) in user">
{{val}} - {{key}} - {{index}}
</div>
</div>
<script src="./js/vue.js"></script>
<script>
let app = new Vue({
// el: '#app',
data: {
title: '111-222',
arr: ['a', 'b'],
content: '<h1>Github</h1>', //xss
user: {
username: 'xiaoming',
age: 20
},
isShow: true,
isLogin: true
}
});
setTimeout(() => {
app.$mount('#app')
}, 1);
</script>
</body>
</html>
value
就是循环过程中的值
key
就是循环过程中的key
值
index
就是循环过程中的key
的下标
参考:https://https://github.com/6xiaoDi/blog-vue-Novice/tree/a0.30
Branch: branch01commit description:a0.30(example08——v-for的基本使用)
tag:a0.30
5.2 :key
默认情况下,在渲染 DOM
过程中使用 原地复用 ,这样一般情况下会比较高效,但是对于循环列表,特别是依赖某种状态的列表,会有一些问题,我们可以通过 :key
属性,来给每个循环节点添加一个标识。(与React
的key
值问题几乎是一样的)
5.2.1 example09
5.2.1.1 example09-1
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<style>
</style>
</head>
<body>
<div id="app">
<ul>
<li v-for="user in users">
<input type="checkbox" />
{{user.username}}
</li>
</ul>
</div>
<script src="./js/vue.js"></script>
<script>
let app = new Vue({
el: '#app',
data: {
users: [
{id: 1, username: 'xm'},
{id: 2, username: 'xh'},
{id: 3, username: 'zs'}
]
}
});
</script>
</body>
</html>
尝试随机打乱顺序(直接在控制台中用即可),但是勾选状态不变!
app.users = app.users.sort( _ => Math.random() - .5 );
是因为在更新过程中,并不是数据一变化,整个元素都重新渲染了,它只渲染变化的部分,未发生变化的部分是不会动的。
它怎么判断变了呢?
这就跟数据有关了。
参考:https://https://github.com/6xiaoDi/blog-vue-Novice/tree/a0.31
Branch: branch01commit description:a0.31(example09-1——循环列表数据更新产生关于key的问题)
tag:a0.31
5.2.1.2 example09-2
结构当中,只是标签内容与数据有关,即只变化数据的部分,即只变化字符串。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<style>
</style>
</head>
<body>
<div id="app">
<ul>
<li v-for="user in users">
<input type="checkbox" />
{{user.username}}
</li>
</ul>
<button @click="fn">按钮</button>
</div>
<script src="./js/vue.js"></script>
<script>
let app = new Vue({
el: '#app',
data: {
users: [
{id: 1, username: 'xm'},
{id: 2, username: 'xh'},
{id: 3, username: 'zs'}
]
},
methods: {
fn() {
this.users = this.users.sort( _ => Math.random() - .5 );
}
}
});
</script>
</body>
</html>
明显看出,只变化了数据变化的部分,因为这些ul、li、input
标签等等与数据是一点关系都没有,这里就涉及到一个问题,就是针对这些元素,它再判别(比较)虚拟dom
,发现如果还是要创建一个ul
,如果创建出ul
与原先的没多大变化,就会复用该元素,不去替换而是原地复用了,这样性能则会提升很多。
而这里的勾选是与数据无关的操作,因此导致勾选始终不变化。
提高渲染性能,造成了这样的结果。
大部分情形下,对应用没什么影响,但是针对于列表同级元素
的话,因为数据都是在同级间发生变化,所以就会发生了此种问题了。
怎么解决呢?
就是把元素与数据关联起来,即数据变化了,这个元素也得跟着一起变化。
可以通过 :key
属性,来给每个循环节点添加一个标识=>把元素与数据关联起来。
<ul>
<li v-for="user in users" :key="user.id">
<input type="checkbox" />
{{user.username}}
</li>
</ul>
参考:https://https://github.com/6xiaoDi/blog-vue-Novice/tree/a0.32
Branch: branch01commit description:a0.32(example09-2——循环列表数据更新产生关于key的问题——绑定id为key值)
tag:a0.32
5.2.1.3 example09-3
这里的循环能否用数组下标呢?
<ul>
<li v-for="(user,index) in users" :key="index">
<input type="checkbox" />
{{user.username}}
</li>
</ul>
没有任何变化了,这是什么原因呢?
因为数据的id
会随数据走的,但是下标就不一定了,即下标代表不了数据的唯一性,下标对于数据根本就没有任何关联关系。
我们改变数据内容,其下标也会随之变化的,因此是不可能唯一判别和标识的。
参考:https://https://github.com/6xiaoDi/blog-vue-Novice/tree/a0.33
Branch: branch01commit description:a0.33(example09-3——循环列表数据更新产生关于key的问题——绑定index为key值的问题)
tag:a0.33
6. 属性绑定
回忆一下react
的属性绑定,针对class
和style
都有不同的细节处理。
其实我们发现react
和vue
关注的问题点都是一样的,只是在细节处理上稍有差异而已。
6.1 v-bind
绑定数据(表达式)到指定的属性上,<div v-bind:参数="值/表达式"></div>
,这里的参数就是指定的属性名称
<div id="app">
<div v-bind:id="'box1'"></div>
<div v-bind:id="myId"></div>
</div>
<script>
new Vue({
el: '#app',
data: {
myId: 'kaikeba'
}
})
</script>
6.1.1 example10
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<div id="app">
<div id="val"></div>
</div>
<script src="./js/vue.js"></script>
<script>
let app = new Vue({
el: '#app',
data: {
val: 'github'
}
});
</script>
</body>
</html>
很明显,不能属性绑定!
在react
中的属性绑定是这样写的:
<div id={this.state.val}></div>
而Vue => v-bind:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<div id="app">
<!-- id属性与表达式挂钩 -->
<div v-bind:id="val"></div>
</div>
<script src="./js/vue.js"></script>
<script>
let app = new Vue({
el: '#app',
data: {
val: 'github'
}
});
</script>
</body>
</html>
无v-bind:
,里面就是一个字符串
<div id="1+1"></div>
有v-bind:
,里面就是一个表达式
<div v-bind:id="1+1"></div>
参考:https://https://github.com/6xiaoDi/blog-vue-Novice/tree/a0.34
Branch: branch01commit description:a0.34(example10——属性绑定v-bind的使用)
tag:a0.34
6.1.2 缩写
有的一些常用指令会有对应的缩写,v-bind
对应的缩写为::
<div :id="myId"></div>
6.2 样式
针对样式属性,v-bind
值有一些特殊的写法
6.2.1 style
原生普通写法
<div style="width: 100px; height: 100px; background: red"></div>
v-bind 写法
<div :style="'width: 100px; height: 100px; background: red'"></div>
对象写法
<div :style="style1"></div>
...
<script>
new Vue({
el: '#app',
data: {
style1: {
width: '100px',
height: '100px',
background: 'green'
}
}
});
</script>
数组写法
<div :style="[style1, style2]"></div>
...
<script>
new Vue({
el: '#app',
data: {
style1: {
width: '100px',
height: '100px',
background: 'green'
}
},
style2: {
border: '1px solid black'
}
});
</script>
6.2.1.1 example11
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<div id="app">
<!-- id属性与表达式挂钩 -->
<!-- <div id="1+1"></div>-->
<div v-bind:id="val"></div>
<div :id="val"></div>
<div :style="style1"></div>
</div>
<script src="./js/vue.js"></script>
<script>
let app = new Vue({
el: '#app',
data: {
val: 'github',
style1: {
width: '100px',
height: '100px',
background: 'green'
}
}
});
</script>
</body>
</html>
参考:https://https://github.com/6xiaoDi/blog-vue-Novice/tree/a0.35
Branch: branch01commit description:a0.35(example11——属性绑定样式的使用)
tag:a0.35
6.2.2 class
原生普通写法
<div class="box1 box2"></div>
v-bind 写法
<div :class="'box1 box2'"></div>
数组写法
<div :class="['box1', 'box2']"></div>
对象写法
<div :class="{'box1': isActive, 'box2': isChecked}"></div>
使用对象写法,对象的key
就是要加class
,可以根据其值(boolean
)动态添加对应的 class,为true
就增加上去了。
这样就可以操作数据动态地添加class
了。
6.2.2.1 example12
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<div id="app">
<!-- id属性与表达式挂钩 -->
<div v-bind:id="val"></div>
<!-- <div id="1+1"></div>-->
<!-- <div v-bind:id="1+1"></div>-->
<div :id="val"></div>
<div :style="style1"></div>
<div :class="{'box1': isActive, 'box2': isChecked}"></div>
</div>
<script src="./js/vue.js"></script>
<script>
let app = new Vue({
el: '#app',
data: {
val: 'github',
style1: {
width: '100px',
height: '100px',
background: 'green'
},
isActive: true,
isChecked: true
}
});
</script>
</body>
</html>
参考:https://https://github.com/6xiaoDi/blog-vue-Novice/tree/a0.36
Branch: branch01commit description:a0.36(example12——属性绑定class的使用)
tag:a0.36
7. 单向数据流
通过上面的知识点和案例,我们可以看到,当数据更新的时候,页面视图就会更新,但是页面视图中绑定的元素更新的时候,对应的数据是不会更新的
<input type="text" :value="title" />
我们称为:单向数据流 数据 -> 视图
刚刚我们所说的v-bind
是单向数据流。
在 vue 中,还有一种双向数据流绑定的方式
7.1 v-model
<input type="text" v-model="title" />
数据 title
更新,视图中 input
的 value
就会更新。同时,当 input 中的 value
更新的时候,数据 title
也会更新,这就是我们说的 数据双向绑定 [与 React 中的受控组件类似]
7.1.1 example13
7.1.1.1 example13-1
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<div id="app">
<input type="text" :value="n1" >
</div>
<script src="./js/vue.js"></script>
<script>
let app = new Vue({
el: '#app',
data: {
n1: 1
}
});
</script>
</body>
</html>
值就绑定上去了。
单向数据流:当数据更新的时候,页面视图就会更新,但是页面视图中绑定的元素更新的时候,对应的数据是不会更新的。
参考:https://https://github.com/6xiaoDi/blog-vue-Novice/tree/a0.37
Branch: branch01commit description:a0.37(example13-1——单向数据流)
tag:a0.37
7.1.1.2 example13-2
怎样进行双向绑定,和react
一样的是受控和非受控组件的特性。
非受控组件 <=> 单向数据流
受控组件 <=> 双向数据流
我们在React
中将非受控子组件变为受控组件,是添加onChange
事件,这里也同理
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<div id="app">
<!-- <input type="text" :value="n1" >-->
<!-- 绑定事件:changeN1 -->
<input type="text" :value="n1" @change="changeN1">
</div>
<script src="./js/vue.js"></script>
<script>
let app = new Vue({
el: '#app',
data: {
n1: 1
},
methods: {
changeN1(e) {
this.n1 = e.target.value;
}
}
});
</script>
</body>
</html>
参考:https://https://github.com/6xiaoDi/blog-vue-Novice/tree/a0.38
Branch: branch01commit description:a0.38(example13-2——与React一样,添加onchange事件使其变为双向数据流)
tag:a0.38
7.1.1.3 example13-3
以上和react
的处理方式一样,但是Vue
也有更为方便的处理方法:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<div id="app">
<!-- <input type="text" :value="n1" >-->
<!-- 绑定事件:changeN1 -->
<!-- <input type="text" :value="n1" @change="changeN1">-->
<input type="text" v-model="n1" />
</div>
<script src="./js/vue.js"></script>
<script>
let app = new Vue({
el: '#app',
data: {
n1: 1
},
methods: {
// changeN1(e) {
// this.n1 = e.target.value;
// }
}
});
</script>
</body>
</html>
这种方式与 React 中的实现受控组件类似,具体实现原理到后面自定义指令v-model
再说明。
参考:https://https://github.com/6xiaoDi/blog-vue-Novice/tree/a0.39
Branch: branch01commit description:a0.39(example13-2——双向数据流=> v-model)
tag:a0.39
8. 表单
针对一般元素,比如 div、span、p、img 等,采用的是单向绑定:v-bind,只需要把数据绑定到视图中就可以,但是对于表单这种交互性比较强的元素或组件,我们一般可能需求双向绑定,即:用户对视图元素的操作同时更新数据
v-model 在内部为不同的输入元素使用不同的属性和事件来处理数据
text
和textarea
checkbox
和radio
select
8.1 text
和 textarea
text
和 textarea
元素使用 value
属性和 input
事件
<div id="app">
<input type="text" v-model="v1" />
<textarea v-model="v2" cols="30" rows="10"></textarea>
</div>
let app = new Vue({
el: '#app',
data: {
v1: 'aaa',
v2: 'bbb'
}
});
8.2 checkbox
和 radio
checkbox
和 radio
使用 checked
属性和 change
事件
单选框绑定一个值
<div id="app">
<input type="radio" v-model="v3" value="男" /> 男
<input type="radio" v-model="v3" value="女" /> 女
</div>
let app = new Vue({
el: '#app',
data: {
v3: '女',
}
});
多选框绑定到一个布尔值或数组
<div id="app">
<input type="checkbox" v-model="v4" /> 同意
<hr/>
<input type="checkbox" v-model="v5" value="足球" /> 足球
<input type="checkbox" v-model="v5" value="音乐" /> 音乐
</div>
let app = new Vue({
el: '#app',
data: {
v4: true,
v5: ['足球', '音乐']
}
});
8.3 select
select
字段将 value
作为 prop
并将 change
作为事件
单选绑定到值,多选绑定到数组
<div id="app">
<select v-model="v3">
<option value="男">男</option>
<option value="女">女</option>
</select>
<select v-model="v5" multiple>
<option value="足球">足球</option>
<option value="音乐">音乐</option>
</select>
</div>
9. 指令修饰符
一个指令可以包含的内容包括:
- 指令名称
- 指令值
- 指令参数
- 指令修饰符
<组件 指令:参数.修饰符1.修饰符2="值" />
9.1 .lazy
取代 input
监听 change
事件
9.2 .number
输入字符串转为有效的数字
9.3 .trim
输入首尾空格过滤
9.4 example14
9.4.1 example14-1
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<div id="app">
<input type="text" v-model="n1" />
<hr>
{{n1}}
</div>
<script src="./js/vue.js"></script>
<script>
let app = new Vue({
el: '#app',
data: {
n1: 1
}
});
</script>
</body>
</html>
我们修改上面的值,下面也跟着改变了。因为其内部发生变化,就会更新n1
,则html
模板当中与n1
有关的视图都会重新渲染了。
默认情形下,一输入值其立马发生改变,因为其内部是默认使用input事件
的来进行数据通知和数据更改的。
<input type="text" v-model.lazy="n1" />
使用change
事件`的来进行数据通知和数据更改的,因此按回车或者失去焦点的时候,才会触发事件。
参考:https://https://github.com/6xiaoDi/blog-vue-Novice/tree/a0.40
Branch: branch01commit description:a0.40(example14-1——lazy修饰符的demo)
tag:a0.40
9.4.2 example14-2
其实里面的值是会产生问题的,举一个例子
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<div id="app">
<!-- <input type="text" v-model="n1" />-->
<!-- <input type="text" v-model.lazy="n1" />-->
<!-- <hr>-->
<!-- {{n1}}-->
<input type="text" v-model.lazy="n1" />
+
<input type="text" v-model.lazy="n2" />
=
{{n1+n2}}
</div>
<script src="./js/vue.js"></script>
<script>
let app = new Vue({
el: '#app',
data: {
n1: 0,
n2: 0
}
});
</script>
</body>
</html>
我们虽然传进去更新的是数值,但是通知出来用input
的value
值(String
类型)作为更新n1
和n2
的,因此最终变成了字符串拼接了。
参考:https://https://github.com/6xiaoDi/blog-vue-Novice/tree/a0.41
Branch: branch01commit description:a0.41(example14-2——lazy修饰符的demo——带来隐患)
tag:a0.41
9.4.3 example14-3
针对上面的问题,我们可以对n1
和n2
转成number
,但是也很麻烦,我们可以用v-model.lazy.number
,它在内部会转成number
。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<div id="app">
<!-- <input type="text" v-model="n1" />-->
<!-- <input type="text" v-model.lazy="n1" />-->
<!-- <hr>-->
<!-- {{n1}}-->
<input type="text" v-model.lazy.number="n1" />
+
<input type="text" v-model.lazy.number="n2" />
=
{{n1+n2}}
</div>
<script src="./js/vue.js"></script>
<script>
let app = new Vue({
el: '#app',
data: {
n1: 0,
n2: 0
}
});
</script>
</body>
</html>
参考:https://https://github.com/6xiaoDi/blog-vue-Novice/tree/a0.42
Branch: branch01commit description:a0.42(example14-3——lazy修饰符的demo——.number解决隐患)
tag:a0.42
(后续待补充)