前言
個人認為vue的指令,對比react來說,給開發者節省了很大的學習成本。比如在react中,你想渲染一個列表,需要用Array.map的方法return<div>,而在vue中,一個簡單的v-for就解決了問題。
在學習成本和入手體驗上,vue的作者確實后來者居上,能讓人更快的使用vue開發。不過也是老生常談的問題,各有特點,不做過多比較。
vue中的指令是用在標簽上或者組件上,是ui層和數據層的交互介質。這個官方沒有這么說,是我自己說的,比如你使用v-if,通過data去控制ui,使用v-model實現ui和data的雙向交互。
我這里并不是指令的具體教程,只是一些demo的測試效果。
示例
這里我將指令分為三塊
簡單指令:學習簡單,使用簡單
復雜指令:可以在組件上使用,或者有修飾符等
自定義指令:自定義一些指令去實現某些業務功能
簡單指令
v-text
用來回顯常規字符串的
<h6>v-text使用</h6><p>使用v-text----<span v-text="textValue"></span></p><p>使用模板語法----<span>{{ textValue }}</span></p>//datatextValue: '這是一段常規文字',
?效果
v-html
用來回顯html的節點
<h6>v-html使用</h6>
<div v-html="htmlTemplate"></div>//data
htmlTemplate: `<div><input/><button>按鈕</button></div>`
效果
v-show
用來控制元素的樣式回顯
<h6>v-show使用</h6>
<el-checkbox v-model="checkedValue">開關</el-checkbox>
<p v-show="checkedValue">開啟</p>
<p v-show="!checkedValue">關閉</p>//data
checkedValue: true,
效果
?v-if & v-else-if & v-else
?用來控制元素的渲染
<h6>v-if && else-if && else的使用</h6>
<p>數字:{{ numValue }}</p>
<el-button @click="addNum">增加</el-button>
<el-button @click="deleteNum">減少</el-button>
<p v-if="numValue > 0">大于0</p>
<p v-else-if="numValue === 0">等于0</p>
<p v-else>小于0</p>//data
numValue: 0,//methods
addNum() {this.numValue++
},
deleteNum() {this.numValue--
},
?
?v-for
渲染數組類型
<h6>v-for使用</h6><ul><li v-for="(item, index) in listValue" :key="item.value">{{ item.label }}</li></ul>//datalistValue: [{label: '文字1',value: 'one'},{label: '文字2',value: 'two'},{label: '文字3',value: 'three'}],
v-pre
跳過對js等變量的編譯,渲染原始html
<h6>v-pre使用</h6><p v-pre>我是不需要編譯的<span>{{ textValue }}</span></p>//datatextValue: '這是一段常規文字',
v-cloak
渲染完成之前的一種替代(網速慢優化策略)
<h6>v-cloak使用</h6><p v-cloak>{{ textValue }}</p>
v-once
元素只會渲染一次,更新不會重新渲染
<h6>v-once使用</h6><el-button @click="changeNumberVal">修改值</el-button><p v-once>不變的:{{ numberVal }}</p><p>變化的的:{{ numberVal }}</p>//data
numberVal: 100,//methodschangeNumberVal() {this.numberVal++},
復雜指令
v-on
用來處理事件的
簡寫和動態事件
<h6>v-on使用(簡寫為@)</h6>
<el-button v-on:click="clickFun">常規點擊</el-button>
<el-button @click="clickFun">簡寫常規點擊</el-button>
<el-button v-on:[eventName]="clickFun">動態事件</el-button>
<el-button @[eventName]="clickFun">動態事件簡寫</el-button>
<el-button @click.once="clickFun">只生效一次</el-button>//methodsclickFun() {console.log('常規點擊')},
依次點擊按鈕,最后一個按鈕點擊只觸發依次
?
?阻止默認事件
<a href="http://www.baidu.com" @click="clickFun"><el-button>無限制跳轉</el-button></a>
<a href="http://www.baidu.com" @click.prevent="clickFun"><el-button>阻止默認事件</el-button></a>//methodsclickFun() {console.log('常規點擊')},
第一個按鈕會先觸發函數,再跳往至百度頁面。
第二個按鈕只會觸發函數,不會跳轉頁面。
阻止事件冒泡
<span @click="clickSpanFun"><el-button @click="clickFun">節點嵌套事件冒泡</el-button></span>
<span @click="clickSpanFun"><el-button @click.stop="clickFun">阻止事件冒泡</el-button></span>//methodsclickFun() {console.log('常規點擊')},clickSpanFun() {console.log('點擊span標簽')},
點擊按鈕1
點擊按鈕2
?其他事件和點擊組件的修飾符
<input v-model="inputValue" @keyup.enter="inputEventFun" type="text">
<el-input v-model="inputValue" @keyup.native.enter="inputEventFun"></el-input>
<Child @click.native="componentClick"></Child>
v-bind
動態渲染值
<h6>v-bind使用</h6>
<p v-bind:class="className">動態class</p>
<p :style="styleName">動態樣式加簡寫</p>
<el-button :name1="name1" :name2="name2" name3="屬性3" ref="btn1" @click="checkBtn1">查看element按鈕組件的自定義屬性</el-button>
<button :name1="name1" :name2="name2" name3="屬性3" ref="btn2" @click="checkBtn2">查看原生dom的自定義屬性</button>//dataname1: '屬性1',name2: JSON.stringify({value: '屬性3'}),
?
依次點擊兩個按鈕
v-model
輸入框類型數據視圖雙向綁定
<h6>v-model使用</h6>
<p>常規v-model<el-input v-model="InputVal"></el-input></p>
<p>lazy修飾符<input v-model.lazy="InputLazyVal" @input="inputLazyFun" /></p>
<p>number修飾符<el-input v-model.number="InputNumberVal"></el-input></p>
<p>trim修飾符<el-input v-model.trim="InputTrimVal"></el-input></p>
v-slot
插槽,這里不說了,看插槽相關的文檔吧
自定義指令
語法
全局注冊和局部注冊
局部注冊
局部注冊就是在當前組件里面寫
<template><div><h6>固定顏色指令</h6><p v-color>固定紅色的指令效果</p></div>
</template><script>export default{data(){return{
}
},directives: {color: {// 指令的定義inserted: function (el) {el.style.color = 'red'}}},
}</script>
全局注冊
創建一個js文件并在main.js中引入?
import Vue from 'vue'Vue.directive('setColor',{//初始化鉤子inserted:function(el,val,vnode){console.log(el,val,vnode,'???自定義函數')el.style.color = val.value || '#000'},//更新鉤子update:function(el,val,vnode){console.log(el,val,vnode,'???自定義函數')el.style.color = val.value || '#000'},
})
引入后,任意組件內都可以使用
<h6>自定義顏色</h6>選擇一個顏色吧:<el-color-picker v-model="colorValue"></el-color-picker><p v-setColor="colorValue">我是一段可選擇顏色的字段</p>//data
colorValue:'#000'
?定義一個可拖拽的指令
vue組件
<h6>可拖拽指令</h6>
<div class="dragBox"><div class="dragContent" v-draggable></div>
</div><style lang="less">.dragBox {position: relative;width: 800px;height: 200px;border: 1px solid #000;.dragContent {position: absolute;width: 50px;height: 50px;background: red;cursor: move;left: 10px;top: 10px;}
}
</style>
定義指令
Vue.directive('draggable',{inserted: function (el) {el.onmousedown = function (e) {var disx = e.pageX - el.offsetLeft;var disy = e.pageY - el.offsetTop;document.onmousemove = function (e) {el.style.left = e.pageX - disx + 'px';el.style.top = e.pageY - disy + 'px';}document.onmouseup = function () {document.onmousemove = document.onmouseup = null;}}},
})
?
自定義指令在實際的項目中還是很重要的,可以實現很多的業務場景。
比如我個人就用指令完成過水印效果,拖拽,按鈕權限的控制等,學會自定義指令,也是多少需要復習一下很多人拋棄已久的dom基礎知識。
全部代碼
vue組件
<template><div class="box"><el-tabs v-model="activeName"><el-tab-pane label="簡單指令(不需要修飾符)" name="first"><div class="content1"><h6>v-text使用</h6><p>使用v-text----<span v-text="textValue"></span></p><p>使用模板語法----<span>{{ textValue }}</span></p></div><div class="content1"><h6>v-html使用</h6><div v-html="htmlTemplate"></div></div><div class="content1"><h6>v-show使用</h6><el-checkbox v-model="checkedValue">開關</el-checkbox><p v-show="checkedValue">開啟</p><p v-show="!checkedValue">關閉</p></div><div class="content1"><h6>v-if && else-if && else的使用</h6><p>數字:{{ numValue }}</p><el-button @click="addNum">增加</el-button><el-button @click="deleteNum">減少</el-button><p v-if="numValue > 0">大于0</p><p v-else-if="numValue === 0">等于0</p><p v-else>小于0</p></div><div class="content1"><h6>v-for使用</h6><ul><li v-for="(item, index) in listValue" :key="item.value">{{ item.label }}</li></ul></div><div class="content1"><h6>v-pre使用</h6><p v-pre>我是不需要編譯的<span>{{ textValue }}</span></p></div><div class="content1"><h6>v-cloak使用</h6><p v-cloak>{{ textValue }}</p></div><div class="content1"><h6>v-once使用</h6><el-button @click="changeNumberVal">修改值</el-button><p v-once>不變的:{{ numberVal }}</p><p>變化的的:{{ numberVal }}</p></div></el-tab-pane><el-tab-pane label="復雜指令" name="second"><div class="content2"><h6>v-on使用(簡寫為@)</h6><el-button v-on:click="clickFun">常規點擊</el-button><el-button @click="clickFun">簡寫常規點擊</el-button><el-button v-on:[eventName]="clickFun">動態事件</el-button><el-button @[eventName]="clickFun">動態事件簡寫</el-button><el-button @click.once="clickFun">只生效一次</el-button><br><a href="http://www.baidu.com" @click="clickFun"><el-button>無限制跳轉</el-button></a><a href="http://www.baidu.com" @click.prevent="clickFun"><el-button>阻止默認事件</el-button></a><br><p @click="clickPFun"><span @click="clickSpanFun"><el-button @click="clickFun">節點嵌套事件冒泡</el-button></span><span @click="clickSpanFun"><el-button @click.stop="clickFun">阻止事件冒泡</el-button></span></p><br><input v-model="inputValue" @keyup.enter="inputEventFun" type="text"><el-input v-model="inputValue" @keyup.native.enter="inputEventFun"></el-input><Child @click.native="componentClick"></Child><br><button v-on="{ mousedown: mousedownFun, mouseup: mouseUpFun }">對象語法</button></div><div class="content2"><h6>v-bind使用</h6><p v-bind:class="className">動態class</p><p :style="styleName">動態樣式加簡寫</p><el-button :name1="name1" :name2="name2" name3="屬性3" ref="btn1"@click="checkBtn1">查看element按鈕組件的自定義屬性</el-button><button :name1="name1" :name2="name2" name3="屬性3" ref="btn2" @click="checkBtn2">查看原生dom的自定義屬性</button></div><div class="content2"><h6>v-model使用</h6><p>常規v-model<el-input v-model="InputVal"></el-input></p><p>lazy修飾符<input v-model.lazy="InputLazyVal" @input="inputLazyFun" /></p><p>number修飾符<el-input v-model.number="InputNumberVal"></el-input></p><p>trim修飾符<el-input v-model.trim="InputTrimVal"></el-input></p></div><div class="content2"><h6>v-slot使用</h6>具體參考插槽吧,這里不做演示了</div></el-tab-pane><el-tab-pane label="自定義指令" name="third"><h6>固定顏色指令</h6><p v-color>固定紅色的指令效果</p><hr><h6>自定義顏色</h6>選擇一個顏色吧:<el-color-picker v-model="colorValue"></el-color-picker><p v-setColor="colorValue">我是一段可選擇顏色的字段</p><hr><h6>可拖拽指令</h6><div class="dragBox"><div class="dragContent" v-draggable></div></div></el-tab-pane></el-tabs></div>
</template>
<script>
import Child from './child.vue'
export default {name: 'instructions',data() {return {activeName: 'first',textValue: '這是一段常規文字',htmlTemplate: `<div><input/><button>按鈕</button></div>`,checkedValue: true,numValue: 0,numberVal: 100,inputValue: '輸入框的值',listValue: [{label: '文字1',value: 'one'},{label: '文字2',value: 'two'},{label: '文字3',value: 'three'}],eventName: 'click',className: 'classP',styleName: {color: 'green'},name1: '屬性1',name2: JSON.stringify({value: '屬性3'}),InputVal: '常規輸入框的值',InputLazyVal: 'lazy輸入框的值',InputNumberVal: 1,InputTrimVal: '去空輸入框的值',colorValue: '#000',}},directives: {color: {// 指令的定義inserted: function (el) {el.style.color = 'red'}}},components: {Child},methods: {addNum() {this.numValue++},deleteNum() {this.numValue--},changeNumberVal() {this.numberVal++},clickFun() {console.log('常規點擊')},clickPFun() {console.log('點擊p標簽')},clickSpanFun() {console.log('點擊span標簽')},inputEventFun() {console.log(this.inputValue, '輸入框的值')},componentClick(e) {console.log(e, '點擊了組件')},mousedownFun() {console.log('鼠標按下')},mouseUpFun() {console.log('鼠標抬起')},checkBtn1() {let btn1 = this.$refs.btn1console.log(btn1, 'element組件按鈕')console.log(btn1.$attrs['name1'], JSON.parse(btn1.$attrs['name2']), btn1.$attrs['name3'], '按鈕的屬性')},checkBtn2() {let btn2 = this.$refs.btn2console.log(btn2, 'btn的節點')console.log(btn2.getAttribute('name1'), JSON.parse(btn2.getAttribute('name2')), btn2.getAttribute('name3'), '按鈕的屬性')},inputLazyFun() {console.log(this.InputLazyVal, 'lazy值')},},
}
</script>
<style lang="less" scoped>
.box {padding: 14px;.content1 {float: left;width: 30%;height: 200px;margin: 10px;padding: 8px;box-shadow: 1px 1px 1px 1px #837e7e;h6 {font-size: 14px;font-weight: 600;}}.content2 {float: left;width: 40%;height: 350px;margin: 10px;padding: 8px;box-shadow: 1px 1px 1px 1px #837e7e;h6 {font-size: 14px;font-weight: 600;}}}[v-cloak] {display: none;
}.classP {color: red;
}.dragBox {position: relative;width: 800px;height: 200px;border: 1px solid #000;.dragContent {position: absolute;width: 50px;height: 50px;background: red;cursor: move;left: 10px;top: 10px;}
}
</style>
自定義指令文件
import Vue from 'vue'
import _ from 'lodash'
Vue.directive('setColor',{inserted:function(el,val,vnode){console.log(el,val,vnode,'???自定義函數')el.style.color = val.value || '#000'},update:function(el,val,vnode){console.log(el,val,vnode,'???自定義函數')el.style.color = val.value || '#000'},
})Vue.directive('draggable',{inserted: function (el) {el.onmousedown = function (e) {var disx = e.pageX - el.offsetLeft;var disy = e.pageY - el.offsetTop;document.onmousemove = function (e) {el.style.left = e.pageX - disx + 'px';el.style.top = e.pageY - disy + 'px';}document.onmouseup = function () {document.onmousemove = document.onmouseup = null;}}},
})
那個child組件我沒有寫,隨便定義一個就行,這些代碼可以直接復制測試
感覺有用就給個贊吧!!!