1.注册自定义指令(全局和局部)
1> 全局注册
<div id="app">
<input type="text" placeholder="我是全局自定义指令" v-focus />
</div>
<script>
Vue.directive("focus", {
inserted: function (el) {
el.focus();
},
});
new Vue({
el: "#app",
});
</script>
###
2> 局部注册
<div id="app">
<input type="text" placeholder="我是局部自定义指令" v-focus />
</div>
<script>
new Vue({
el: "#app",
//内部使用
directives: {
focus: {
inserted: function (el) {
el.focus();
},
},
},
});
</script>
2.自定义指令传参(单个和多个)
1>单个参数
<div v-focus="scope.row.isdisabled"></div>
<script>
Vue.directive("focus", function (el, binding) {
console.log(binding.value); // true
});
</script>
2>多个参数
<div v-demo="{ color: 'white', text: 'hello!' }"></div>
<script>
Vue.directive("demo", function (el, binding) {
console.log(binding.value.color); // "white"
console.log(binding.value.text); // "hello!"
});
</script>
3.钩子函数以及参数
1>钩子函数
inserted
,这个就是自定义指令的钩子函数,自定义指令有五个钩子函数:
bind
:只调用一次,在指令第一次绑定到元素时调用,可以在这个钩子函数中进行初始化设置;inserted
:被绑定元素插入父节点时调用,在bind
后面调用;update
:所在绑定的组件的 VNode 更新时调用,但是可能发生在其子 VNode 更新之前。 调用时指令的值不一定发生改变,通过比较更新前后的值来忽略不必要的模板更新;componentUpdated
:指令所在组件的 VNode 及其子 VNode 全部更新后调用;unbind
:只调用一次,指令与元素解绑时调用。
<template>
<div>
<h1 v-color="color" v-if="show">{{title}}</h1>
<button @click="show=false">测试解绑v-color</button>
<button @click="title='更换title'">更换title</button>
<button @click="color='blue'">更换color</button>
</div>
</template>
<script>
export default {
name: "HelloWorld",
data() {
return {
color: "red",
title: "自定义指令",
show: true,
};
},
directives: {
color: {
bind: function () {
console.log("bind");
},
inserted: function (el, binding) {
console.log("inserted");
el.style.color = binding.value;
},
update: function (el, binding) {
console.log("update");
el.style.color = binding.value;
},
componentUpdated: function (el, binding) {
console.log("componentUpdated");
el.style.color = binding.value;
},
unbind: function () {
console.log("unbind");
},
},
};
</script>
//F5 刷新
bind
inserted
//按钮(更换 title)
update
componentUpdated
//按钮(更换 color)
update
componentUpdated
//按钮(解绑即隐藏)
unbind
2>钩子函数参数
其中
el
binding
就是钩子函数的参数,有 4 个参数:
el
:指令所绑定的元素,可以用来直接操作 DOM;binding
:一个对象其中包括以下几个属性;
name
:指令名,不包括 v- 前缀;value
:指令的绑定值,例:v-my-directive="1 + 1"
中,绑定值为 2;expression
:指令的绑定的表达式。例:v-my-directive="1 + 1"
中,表达式为 “1 + 1”;arg
:传给指令的参数,例v-my-directive:foo
中,参数为 “foo”;modifiers
:一个包含修饰符的对象。例:v-my-directive.foo.bar
中,修饰符对象为 { foo: true, bar: true },oldValue
:指令绑定的前一个值,仅在update
和componentUpdated
钩子中可用。无论值是否改变都可用。vnode
:Vue 编译生成的虚拟节点;oldVnode
:上一个虚拟节点,仅在update
和componentUpdated
钩子中可用。
除了
**el**
之外,其它参数都是只读的,不能对其修改。如果需要在钩子之间共享数据,要通过元素的**dataset**
来进行。
4.实际运用
1>图片的加载
需求:图片加载中,需要使用占位图去显示,优化加载图片等待体验。
<div id="app2" class="demo">
<div v-for="item in imageList">
<img src="../assets/image/bg.png" alt="默认图" v-image="item.url" />
</div>
</div>
<script>
Vue.directive("image", {
inserted: function (el, binding) {
//为了真实体现效果,用了延时操作
setTimeout(function () {
el.setAttribute("src", binding.value);
}, Math.random() * 1200);
},
});
new Vue({
el: "#app2",
data: {
imageList: [
{
url: "http://consumer-img.huawei.com/content/dam/huawei-cbg-site/greate-china/cn/mkt/homepage/section4/home-s4-p10-plus.jpg",
},
{
url: "http://consumer-img.huawei.com/content/dam/huawei-cbg-site/greate-china/cn/mkt/homepage/section4/home-s4-watch2-pro-banner.jpg",
},
{
url: "http://consumer-img.huawei.com/content/dam/huawei-cbg-site/en/mkt/homepage/section4/home-s4-matebook-x.jpg",
},
],
},
});
</script>
###
2>input 的聚焦
需求:点击输入框旁边的按钮,input 变为可编辑状态,并且获取焦点。失焦时,input 变为不可编辑状态。
<template>
<div>
<el-table
:data="tableData"
v-loading="listLoading"
ref="TableRow"
:tree-props="{children: 'children', hasChildren: 'hasChildren'}"
style="width: 100%"
@select="handleSelectionChange"
:row-key="getRowKeys"
@row-click="RowClick"
>
<el-table-column
align="center"
width="50"
type="selection"
></el-table-column>
<el-table-column prop="name" label="商品" width="175"></el-table-column>
<el-table-column prop="upc" label="商品条码"></el-table-column>
<el-table-column prop="vipPrice1" label="会员价1(元)">
<template slot-scope="scope">
<div class="priceChangeWay">
<el-input
v-model="scope.row.vipPrice1"
v-focus
@blur="cope.row.isdisabled1=true"
:disabled="scope.row.isdisabled1"
>
</el-input>
<span
><i
slot="suffix"
@click.stop="scope.row.isdisabled1=false"
v-if="scope.row.isdisabled1"
class="el-input__icon el-icon-edit"
></i
></span>
</div>
</template>
</el-table-column>
<el-table-column prop="vipPrice2" label="会员价2(元)">
<template slot-scope="scope">
<div class="priceChangeWay">
<el-input
v-model="scope.row.vipPrice2"
v-focus
@blur="cope.row.isdisabled2=true"
:disabled="scope.row.isdisabled2"
>
</el-input>
<span
><i
slot="suffix"
@click.stop="scope.row.isdisabled2=false"
v-if="scope.row.isdisabled2"
class="el-input__icon el-icon-edit"
></i
></span>
</div>
</template>
</el-table-column>
</el-table>
</div>
</template>
<script>
export default {
data: {
return {
tableData:[]
}
},
directives: {
focus: {
// 指令的定义
update: function (el, binding) {
// console.log(el.children[0], binding.value)
// 聚焦元素
el.focus()
// element-ui
el.children[0].focus()
// 元素有变化,如show或者父元素变化可以加延时或判断
setTimeout(_ => {
el.children[0].focus()
})
}
},
methods:{
// 读取商品库数据
ReadGoodsData () {
this.listLoading = true
queryShopProductSkuByPage(this.queryData).then(res => {
this.listLoading = false
res.results.map(item => {
item.isdisabled1 = true
item.isdisabled2 = true
item.vipPrice1 = ''
item.vipPrice2 = ''
return item
})
this.tableData = res.results || []
}).catch(err => {
this.listLoading = false
console.log(err)
})
}
}
}
</script>
3>更多自定义指令资源
想了解更多自定义指令资源,请了解此篇文章。