Vue.js -- 指令 第二部分
Vue.js
7. 表单
针对一般元素,比如 div、span、p、img 等,采用的是单向绑定:v-bind,只需要把数据绑定到视图中就可以,但是对于表单这种交互性比较强的元素或组件,我们一般可能需求双向绑定,即:用户对视图元素的操作同时更新数据
v-model 在内部为不同的输入元素使用不同的属性和事件来处理数据
text
和textarea
checkbox
和radio
select
7.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'
}
});
7.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: ['足球', '音乐']
}
});
7.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>
8. prop和attr
property
: js中的对象属性 (在用户显示这块更明显,修改js对象某属性,html属性还是不变的,只是显示上变化)
attribute
: html标签的属性
代码示例:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title> <style> .ipt{ width: 500px; } </style> </head> <body> <input type="text" value="丁"> <script> let input = document.querySelector("input"); input.value = "哈哈"; input.setAttribute("class","ipt"); input.setAttribute("value","ipt"); </script> </body> </html>
页面显示:
9. 指令修饰符
一个指令可以包含的内容包括:
- 指令名称
- 指令值
- 指令参数
- 指令修饰符
指令名称:参数 . 修饰符 = 值
不同的指令有不同的参数,也有不同的修饰符
(有些指令没有修饰符,有的多,有的少,有的会重复,有的完全不一样)
注意事项:
修饰符不是参数的哈,是属于指令的~~~
不同的指令下,有不同的修饰符,需要使用时,查看api中对应的指令
具体内容查看api或者自定义指令的具体实现
<组件 指令名称:参数.修饰符1.修饰符2="值" />
<input type="text" :value="msg">
<input type="text" v-bind:value.number="msg">
9.1 .lazy
取代
input
监听change
事件
.lazy
在事件change之后触发 有点像失去焦点后再触发的效果~~~
<div id="app">
<!-- .lazy在事件change之后触发 有点像失去焦点后再触发的效果 -->
<input type="text" v-model.lazy="val">
<span>{{val}}</span>
</div>
<script>
let app = new Vue({
el:"#app",
data:{
val:1
}
});
</script>
输入内容,后面数据并没更新
输入完内容,鼠标在其他地方点击,即输入框失去焦点后,后面数据跟着更新
9.2 .number
.number
把输入字符串转为有效的数字
<div id="app">
<input type="text" v-model.lazy="v1">+<input type="text" v-model.lazy="v2">={{v1+v2}} <br><br>
<!-- input框里的value默认为是字符串,一开始默认是相加的,是因为data里就是值,但之后结果就是字符串拼接了
所以需要计算值的话,需要加修饰符 .number -->
<input type="text" v-model.lazy.number="v1">+<input type="text" v-model.lazy.number="v2">={{v1+v2}}
</div>
<script>
let app = new Vue({
el:"#app",
data:{
v1:1,
v2:2
}
});
</script>
一开始默认状态,都是计算的值呈现在后面,因为data数据里就是数字
没加 .number 的,之后结果都是拼接的
加了 .number 的,之后结果也都是计算值
9.3 .trim
输入首尾空格过滤
9.4 自定义修饰符(具体见 10.5)
10. 自定义指令
我们还可以通过 Vue
提供的方法来自定义指令
10.1 注册指令
vue
提供了两种指令注册方式
- 全局指令
- 局部指令
10.2 全局指令
Vue.directive('指令名称', {指令配置});
10.3 局部指令
new Vue({
el: '#app',
directives: {
'指令名称': {指令配置}
}
});
在使用指令的时候,需要使用
v-指令名称
的方式来调用
10.4 指令生命周期(钩子函数)
指令的运行方式很简单,它提供了一组指令生命周期钩子函数,我们只需要在不同的生命周期钩子函数中进行逻辑处理就可以了
钩子函数的意义: 可以让开发者 灵活 控制 指令功能执行的 时间!!!
可以实现不同的时段实现不同的功能~~~
一个指令定义对象可以提供如下几个钩子函数 (均为可选):
- bind : 只调用一次,指令第一次绑定到元素时调用。在这里可以进行一次性的初始化设置
- inserted : 被绑定元素插入父节点时调用 (仅保证父节点存在,但不一定已被插入文档中)
- update : 所在组件更新的时候调用
- componentUpdated : 所在组件更新完成后调用
- unbind : 只调用一次,指令与元素解绑时调用
不同的生命周期钩子函数在调用的时候同时会接收到传入的一些不同的参数
- el : 指令所绑定的元素,可以用来直接操作 DOM
- binding : 一个对象,包含以下属性:
- name : 指令名,不包括v-
前缀
- value : 指令的绑定值(作为表达式解析后的结果)
- expression : 指令绑定的表达式(字符串)
- arg : 传给指令的参数,可选
- modifiers : 传给指令的修饰符组成的对象,可选,每个修饰符对应一个布尔值
- oldValue : 指令绑定的前一个值,仅在 update 和 componentUpdated 钩子中可用,无论值是否改变都可用- vnode:Vue 编译生成的虚拟节点。移步 VNode API 来了解更多详情。
- oldVnode:上一个虚拟节点,仅在 update 和 componentUpdated 钩子中可用。
10.5 自定义修饰符
- 作用:节省指令的定义数量,以及提高适用性
- 使用场景:在两个功能类似的情况下,只有部分有差异,则使用相同指令,部分差异点用修饰符区分
- 使用方法:直接用(不用定义,直接写)
- 示例:box和box2功能类似,自定义一个limit修饰符来区分
<div class="box" v-drag="isDrag"></div> <div class="box2" v-drag.limit="isDrag"></div>
10.6 案例
官网的例子
<!DOCTYPE html>
<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>
</head>
<body>
<div id="app">
<input type="text" v-focus>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script>
Vue.directive('focus', {
inserted(el) {
el.focus();
}
});
let app = new Vue({
el: '#app'
});
</script>
</body>
</html>
扩展:自定义拖拽指令
<!DOCTYPE html>
<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>
<style>
.box {
position: absolute;
left: 100px;
top: 100px;
width: 100px;
height: 100px;
background: red;
}
</style>
</head>
<body>
<div id="app">
<button @click="canDrag = !canDrag">Drag : {{canDrag}}</button>
<div class="box" v-drag.limit="canDrag"></div>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script>
Vue.directive('drag', {
bind(el, {modifiers,value}) {
let isDragStart = false;
let disX = 0;
let disY = 0;
el.canDrag = value;
el.addEventListener('mousedown', e => {
if (!el.canDrag) return;
disX = e.clientX - el.offsetLeft;
disY = e.clientY - el.offsetTop;
isDragStart = true;
e.preventDefault();
});
document.addEventListener('mousemove', e => {
if (isDragStart) {
let x = e.clientX - disX;
let y = e.clientY - disY;
if (modifiers.limit) {
if (x < 0) {
x = 0;
}
if (y < 0) {
y = 0;
}
}
el.style.left = x + 'px';
el.style.top = y + 'px';
}
});
document.addEventListener('mouseup', e => {
isDragStart = false;
});
},
componentUpdated(el, {value}) {
console.log('componentUpdated', value);
el.canDrag = value;
}
});
let app = new Vue({
el: '#app',
data: {
canDrag: false
}
});
</script>
</body>
</html>