這篇文章帶大家了解一下vue中的自訂指令,介紹如何註冊自訂指令、自訂指令參數、自訂指令使用場景,希望對大家有幫助!
如今Vue佔據了國內前端市場的大壁江山,在前端求職過程中,Vue的相關面試題也是越來越多。之所以Vue如此火熱,很大部分原因就是它的漸進式、元件化、指令式等思想,讓一般開發人員非常好上手。 【相關推薦:vuejs影片教學】
指令是一個Vue專案用的最多的東西之一了,今天我們就來講解Vue指令中的一個分支:自訂指令。
想要使用自訂指令,首先我們要搞清楚什麼是自訂指令?
自訂指令非常好理解,我們使用的v-for、v-if、v-model等等稱為指令,也稱為Vue的內建指令。這些指令都是我們可以直接使用的。
為了更好的滿足需求,最大化的讓開發者個性化開發,Vue暴漏了自訂指令的API給我們,讓我們除了使用內建指令外,我們還可以自己定義指令,定義好後和內建指令的方式非常類似。
例如我們看面的程式碼:
<p v-pin="200">我是一段话</p>
上面那段程式碼中v-pin可能很多小夥伴不知道是什麼,看起來像是指令,但有沒有遇過。其實v-pin就是一個自訂指令,只是我們這兒省略註冊它的程式碼。
我們為了房間,直接使用Vue2.x的鷹架工具快速建造一個專案。
建立指令:
vue create 项目名称
運行起來:
##3. 如何註冊自訂指令? 要想使用自訂指令,我們必須先提前把它註冊好,就好比我們的元件一樣,得先註冊,才能使用。 註冊指令也分為全域註冊和局部註冊,和全域註冊元件和局部註冊元件一個道理。全域註冊的指令可以在任何元件中直接使用,局部註冊的指令只能在註冊的地方使用。3.1 全域註冊
全域註冊顧名思義,自訂指令註冊好後,在專案的所有元件內都可以直接使用。 Vue提供了一個directive方法給我們註冊自訂指令,我們在main.js中註冊一個全域的自訂指令。程式碼如下:
// src/main.js import Vue from "vue"; import App from "./App.vue"; Vue.config.productionTip = false; Vue.directive("resize", { bind() {}, inserted() {}, update() {}, componentUpdated() {}, unbind() {}, }); new Vue({ render: (h) => h(App), }).$mount("#app");
3.2 局部註冊
通常來說,如果自訂指令不是每個元件都會用到的話,我們一般會註冊自訂指令就好了。 我們改造一下APP.vue文件,在其內部註冊自訂指令,程式碼如下:<script> export default { name: "App", components: {}, directives: { resize: { bind() {}, inserted() {}, update() {}, componentUpdated() {}, unbind() {}, }, }, }; </script>
注意:全域註冊指令使用的是directive,局部註冊指令使用的是directives,很好理解,局部指令一次注意註冊很多個,全域指令依序只能註冊一個。
4. 自訂指令參數詳解上一節簡單介紹了局部註冊自訂指令和全域註冊自訂指令,可以看到指令裡面有幾個鉤子函數,我們的操作邏輯主要在這幾個鉤子函數當中,所以我們有必要介紹下這幾個鉤子函數。4.1 鉤子函數介紹
#bind:
##只呼叫一次,指令第一次綁定到元素時調用。在這裡可以進行一次性的初始化設定。inserted:
被綁定元素插入父節點時呼叫(僅保證父節點存在,但不一定已插入文件中)。
update:
所在组件的 VNode 更新时调用,但是可能发生在其子 VNode 更新之前。指令的值可能发生了改变,也可能没有。但是你可以通过比较更新前后的值来忽略不必要的模板更新 componentUpdated: 指令所在组件的 VNode及其子 VNode全部更新后调用。 unbind: 只调用一次,指令与元素解绑时调用。 上面5个就是自定义指令的全部钩子函数,每个钩子函数都是可选的,视情况而定。大家可以简单理解钩子函数顺序:指令绑定到元素时(bind)、元素插入时(inserted)、组件更新时(update)、组件更新后(componentUpdated)、指令与元素解绑时(unbind)。这些和组件的生命周期函数有点类似。 4.2 钩子函数参数介绍 为了方便我们的逻辑操作,每个钩子函数都会接收参数,我们可以用这些参数做我们想做的事。 el: 指令所绑定的元素,可以用来直接操作 DOM。 binding: 一个对象,包含以下属性: vnode: Vue 编译生成的虚拟节点。 oldVnode: 上一个虚拟节点,仅在 在使用的时候,el和binding参数是我们使用得最平凡的,有了这些参数,我们的操作就变得简单起来。 上面两节介绍了如何注册自定义指令以及相关参数,接下来就该实战了,我们在APPVue中定义一个自定义指令,先来验证一下钩子函数的执行情况。 代码如下: 效果如下: 上面代码中我们将自定义指令resize绑定到了div元素上面,当我们刷新页面时,执行了自定义指令中的bind和inserted钩子函数,其余函数均要元素有更新才会执行。 5.1 实现v-resize指令 需求背景: 在做数据大屏或者自适应开发的时候,我们通常需要根据浏览器窗口大小的变化重新渲染页面,比如重新绘制echarts图表等功能。 需求描述: 实现自定义指令v-resize指令,窗口大小发生变化时,实时打印最新的窗口宽高。 代码实现: 效果如下: 当我们更改浏览器窗口大小时,页面上会实时打印出最新的高度和宽度,当然这儿只是一个最简单的案例,实际项目中我们通常会在窗口大小发生变化后去调用自定义的一些方法。 5.2 指令传参和传值 我们使用v-bind、v-model等内置指令时,都是可以传参和传值的,我们自定义指令也一样。 示例代码: 效果如下: args和value就是我们传给指令的参数和值,需要注意的是value接收变量或者表达式,arg接收字符串或者变量,具体解释可以参上参数详解那一节。 5.3 指令简写 很多时候我们不需要用到自定义指令中的所有钩子函数,常用的就那么几个,所以官方给我们提供了一种简写的方式。 代码如下: 上面代码的写法让我们的指令变得很简洁,上段代码的意思就是把bind和update钩子函数合二为一了,通常我们想要这两个钩子函数做同样的事的时候使用。 知道了自定义指令如何使用,我们可以扩充一下使用场景,加深一下大家对自定义指令的理解。 6.1 v-copy 实现一键复制文本内容,用于鼠标右键粘贴。 6.2 v-longpress 实现长按,用户需要按下并按住按钮几秒钟,触发相应的事件。 6.3 v-debounce 防止按钮在短时间内被多次点击,使用防抖函数限制规定时间内只能点击一次。 6.4 v-LazyLoad 实现一个图片懒加载指令,只加载浏览器可见区域的图片。 6.5 v-draggable 实现一个拖拽指令,可在页面可视区域任意拖拽元素。 上面的一些自定义指令都是需求中非常常见的,对应的指令代码网上也有很多,但是我建议大家自己下去实践一下。 自定义指令的语法规则和用法很简单,复杂的是我们要用来解决什么问题。在合适的场景下使用合适的解决办法才是最重要的。 以上是vue中什麼是自訂指令?怎麼使用?的詳細內容。更多資訊請關注PHP中文網其他相關文章!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 }
。update
和componentUpdated
钩子中可用。5. 简单案列实战
<template>
<div id="app">
<img alt="Vue logo" src="./assets/logo.png" />
<div v-resize></div>
</div>
</template>
<script>
export default {
name: "App",
components: {},
directives: {
resize: {
bind() {
console.log("bind")
},
inserted() {
console.log("inserted")
},
update() {
console.log("update")
},
componentUpdated() {
console.log("componentUpdated")
},
unbind() {
console.log("unbind")
},
},
},
};
</script>
// src/APP.vue
<template>
<div id="app">
<h1>窗口宽度:{{ innerWidth }}</h1>
<h1>窗口高度:{{ innerHeight }}</h1>
<div style="height: 300px; width: 80%; background: blue" v-resize></div>
</div>
</template>
<script>
export default {
name: "App",
data() {
return {
innerHeight: window.innerHeight,
innerWidth: window.innerWidth,
};
},
components: {},
directives: {
resize: {
bind() {
console.log("bind");
},
inserted(el, binding, vnode) {
console.log("inserted");
console.log(el, binding);
let that = vnode.context;
// 监听浏览器的resize事件
window.addEventListener("resize", () => {
that.innerHeight = window.innerHeight;
that.innerWidth = window.innerWidth;
});
},
update() {
console.log("VNode更新了");
},
componentUpdated() {
console.log("componentUpdated");
},
unbind() {
console.log("unbind");
window.removeEventListener("resize");
},
},
},
};
</script>
<template>
<div id="app">
<h1>窗口宽度:{{ innerWidth }}</h1>
<h1>窗口高度:{{ innerHeight }}</h1>
<div
style="height: 300px; width: 80%; background: blue"
v-resize:[args]="value"
></div>
</div>
</template>
<script>
export default {
name: "App",
data() {
return {
innerHeight: window.innerHeight,
innerWidth: window.innerWidth,
args: "我是参数",
value: "我是传的值",
};
},
components: {},
directives: {
resize: {
bind(el, binding) {
console.log("bind");
console.log("值", binding.value);
console.log("参数", binding.arg);
},
},
},
};
</script>
resize(el, binding) {
console.log("我是简写的自定义指令", binding.value);
},
6. 自定义指令使用场景
总结