Vue 内置指令以及自定义指令

1. 内置指令

  • v-show
    :


    • 说明:
      根据条件展示元素,true展示元素,false隐藏元素
 <template>
<div>
<button v-show="isShow"></button>
</div>
</template>
<script>
export default {
name: 'HomeView',
data() {
return {
isShow: false
};
}
};
</script>

注意:v-show 不支持写在

template
元素标签上,也不支持同时写在 v-else 标签中

v-show
是采用切换
css
属性
display:block
,
display:none
来控制显示或隐藏
dom
,所以初始页面
render
时,此dom就会渲染至页面中,只不过是隐藏状态。

  • v-if
    :


    • 说明:
      根据条件展示元素,true在dom树中渲染元素,false从dom树中移除元素
 <template>
<div>
<button v-if="isShow"></button>
</div>
</template>
<script>
export default {
name: 'HomeView',
data() {
return {
isShow: false
};
}
};
</script>

v-if
可以作用于
template
中,如果表达式为
true
,那么
template
标签块中的代码都会渲染,反之都不渲染

v-if
也是惰性的:如果在初始渲染时条件为假,则什么也不做——直到条件第一次变为真时,才会开始渲染条件块

  • v-else


    • 说明:
      表示 v-if 的“else 块”
 <template>
<div>
<button v-if="isShow">按钮1</button>
<button v-else>按钮2</button>
</div>
</template>

<script>
export default {
name: 'HomeView',
data() {
return {
isShow: false
};
}
};
</script>

v-else
元素必须紧跟在带
v-if
或者
v-else-if
的元素的后面,否则它将不会被识别

  • v-else-if


    • 说明:
      表示 v-if 的“else 块”
 <template>
<div>
<button v-if="type === 'a'">按钮a</button>
<button v-else-if="type === 'b'">按钮b</button>
<button v-else-if="type === 'c'">按钮c</button>
<button v-else="type === 'd'">按钮d</button>
</div>
</template>

<script>
export default {
name: 'HomeView',
data() {
return {
type: 'a'
};
}
};
</script>

类似于

v-else
v-else-if
也必须紧跟在带
v-if
或者
v-else-if
的元素之后。

  • v-bind


    • 说明:
      动态地绑定一个或多个 attribute,或一个组件 prop 到表达式
    • 缩写:
      :

a. 绑定一个 attribute

 <template>
<div>
<img v-bind:src="imgSrc" />
<img :src="imgSrc" />
</div>
</template>

<script>
export default {
name: 'HomeView',
data() {
return {
imgSrc: 'https://picsum.photos/200/300/?random'
};
}
};
</script>

b. class 绑定

 <template>
<div>
<div :class="{ red: isRed }"></div>
<div :class="[classA, classB]"></div>
<div :class="[classA, { classB: isB, classC: isC }]"></div>
</div>
</template>

<script>
export default {
name: 'HomeView',
data() {
return {
isRed: true,
classA: 'classA',
classB: 'classB',
isB: true,
isC: true
};
}
};
</script>

c. style 绑定

 <template>
<div>
<div :style="{ fontSize: size + 'px' }"></div>
<div :style="[styleObjectA, styleObjectB]"></div>
</div>
</template>

<script>
export default {
name: 'HomeView',
data() {
return {
size: 20,
styleObjectA: {
color: 'red',
fontSize: '20px'
},
styleObjectB: {
color: 'blue',
fontSize: '30px'
}
};
}
};
</script>

d. 组件传值

 <template>
<div>
<child-component :title="text" />
</div>
</template>

<script>
export default {
name: 'HomeView',
components: {
'child-component': {
props: {
title: String
},
template: '<div>{{ title }}</div>'
}
},
data() {
return {
text: 'test'
};
}
};
</script>

e. 传递当前所有 props

 <template>
<div>
<child-component v-bind="$props" />
</div>
</template>

<script>
export default {
name: 'HomeView',
components: {
'child-component': {
props: {
title: String
},
template: '<div>{{ title }}</div>'
}
},
props: {
propsValue: String
},
data() {
return {
text: 'test'
};
}
};
</script>
  • v-text


    • 说明:
      更新元素的 textContent
 <template>
<div>
<span v-text="text"></span>
<!-- 和下面的一样 -->
<span>{{ text }}</span>
</div>
</template>

<script>
export default {
name: 'HomeView',
data() {
return {
text: 'test'
};
}
};
</script>
  • v-html


    • 说明:
      更新元素的 innerHTML
    • 版本:
      vue2,vue3
 <template>
<div>
<p v-html="innerHTML"></p>
</div>
</template>

<script>
export default {
name: 'HomeView',
data() {
return {
innerHTML: '<button>click</button>'
};
}
};
</script>

页面展示:

  • v-for


    • 说明:
      遍历数据
 <template>
<div class="container">
<ul>
<li v-for="(item, index) in list" :key="item.name">{{ item.name }}{{ index }}</li>
</ul>

<ol>
<li v-for="(item, index) of list" :key="item.version">{{ item.version }}{{ index }}</li>
</ol>
</div>
</template>

<script>
export default {
name: 'HomeView',
data() {
return {
list: [
{
name: 'vue',
version: '2'
},
{
name: 'react',
version: '17'
}
]
};
}
};
</script>

注意:请不要将

v-for
v-if
一起使用,当和
v-if
一起使用时,
v-for
的优先级比
v-if
更高,
v-for
可以与
v-show
一起使用,如果需要带条件渲染,请考虑使用
computed
属性

最佳建议,在使用 v-for 时,使用 key 属性,来保证内部 diff 算法更新 dom 时最佳优化,不推荐使用 index 属性

页面展示:

  • v-model


    • 说明:
      在表单控件或者组件上创建双向绑定
 <template>
<div class="container">
<p>
<span>input-</span>
<span>v-model:</span>
<span>{{ inputVal }}</span>
<input type="text" v-model="inputVal" />
</p>
<p>
<span>textarea-</span>
<span>v-model:</span>
<span>{{ textareaVal }}</span>
<textarea type="text" v-model="textareaVal"></textarea>
</p>
</div>
</template>

<script>
export default {
name: 'HomeView',
data() {
return {
inputVal: '',
textareaVal: ''
};
}
};
</script>

页面展示:

2. 自定义指令

  • 注册全局指令
 import Vue from 'vue';

Vue.directive('directiveName', {
bind(el, binding, vnode, oldVnode) {},
inserted(el, binding, vnode, oldVnode) {},
update(el, binding, vnode, oldVnode) {},
componentUpdated(el, binding, vnode, oldVnode) {},
unbind(el, binding, vnode, oldVnode) {}
});
 <template>
<div class="container" v-directiveName></div>
</template>
  • 局部注册指令
 <template>
<input class="container" v-focus />
</template>

<script>
export default {
name: 'HomeView',
directives: {
focus: {
bind(el, binding, vnode, oldVnode) {},
inserted(el, binding, vnode, oldVnode) {},
update(el, binding, vnode, oldVnode) {},
componentUpdated(el, binding, vnode, oldVnode) {},
unbind(el, binding, vnode, oldVnode) {}
}
}
};
</script>
  • 钩子函数


    • bind
      : 只调用一次,指令第一次绑定到元素时调用。在这里可以进行一次性的初始化设置。
    • inserted
      : 被绑定元素插入父节点时调用 (仅保证父节点存在,但不一定已被插入文档中)。
    • update
      : 所在组件的 VNode 更新时调用,但是可能发生在其子 VNode 更新之前。指令的值可能发生了改变,也可能没有
    • componentUpdated
      : 指令所在组件的 VNode 及其子 VNode 全部更新后调用。
    • unbind
      : 只调用一次,指令与元素解绑时调用。
  • 钩子函数参数


    • 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 }。
    • vnode
      : Vue 编译生成的虚拟节点
    • oldVnode
      : 上一个虚拟节点,仅在 update 和 componentUpdated 钩子中可用。
  • 指令完整参数写法

 <template>
<input v-focus:mount.foo.bar="1 + 1" />
</template>

<script>
export default {
name: 'HomeView',
directives: {
focus: {
bind(el, binding, vnode, oldVnode) {
console.log(binding);
},
inserted(el, binding, vnode, oldVnode) {},
update(el, binding, vnode, oldVnode) {},
componentUpdated(el, binding, vnode, oldVnode) {},
unbind(el, binding, vnode, oldVnode) {}
}
}
};
// [object Object]
{
"name": "focus",
"rawName": "v-focus:mount.foo.bar",
"value": 2,
"expression": "1 + 1",
"arg": "mount",
"modifiers": {
"foo": true,
"bar": true
},
"def": {}
}
</script>
  • 动态参数
 <template>
<input v-focus:[dynamic].foo.bar="1 + 1" />
</template>

<script>
export default {
name: 'HomeView',
data() {
return {
dynamic: [1, 2, 3, 4, 5]
};
},
directives: {
focus: {
bind(el, binding, vnode, oldVnode) {
console.log(binding);
},
inserted(el, binding, vnode, oldVnode) {},
update(el, binding, vnode, oldVnode) {},
componentUpdated(el, binding, vnode, oldVnode) {},
unbind(el, binding, vnode, oldVnode) {}
}
}
};
</script>
// [object Object]
{
"name": "focus",
"rawName": "v-focus:[dynamic].foo.bar",
"value": 2,
"expression": "1 + 1",
"arg": [
1,
2,
3,
4,
5
],
"modifiers": {
"foo": true,
"bar": true
},
"def": {}
}
  • 自定义指令示例
    • v-drag
 <template>
<div class="container" v-drag></div>
</template>

<script>
export default {
name: 'HomeView',
data() {
return {
dynamic: [1, 2, 3, 4, 5]
};
},
directives: {
drag: {
bind(el, binding, vnode, oldVnode) {
el.onmousedown = e => {
const disX = e.clientX - el.offsetLeft;
const disY = e.clientY - el.offsetTop;
document.onmousemove = e => {
el.style.left = e.clientX - disX + 'px';
el.style.top = e.clientY - disY + 'px';
};
document.onmouseup = () => {
document.onmousemove = null;
document.onmouseup = null;
};
};
},
inserted(el, binding, vnode, oldVnode) {},
update(el, binding, vnode, oldVnode) {},
componentUpdated(el, binding, vnode, oldVnode) {},
unbind(el, binding, vnode, oldVnode) {}
}
}
};
</script>

<style scoped>
.container {
width: 500px;
height: 300px;
border: 1px solid red;
position: fixed;
left: 0;
top: 0;
}
.container:hover {
cursor: pointer;
}
</style>

标签: Javascript

添加新评论