最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

vue中自定義指令directive的詳細指南

 更新時間:2021年09月24日 09:45:55   作者:星空之火@田興  
這篇文章主要給大家介紹了關(guān)于vue中自定義指令directive的相關(guān)資料,自定義指令解決的問題或者說使用場景是對普通 DOM 元素進行底層操作,所以我們不能盲目的胡亂的使用自定義指令,需要的朋友可以參考下

一、 什么是自定義指令

我們看到的v-開頭的行內(nèi)屬性,都是指令,不同的指令可以完成或?qū)崿F(xiàn)不同的功能,對普通 DOM元素進行底層操作,這時候就會用到自定義指令。除了核心功能默認內(nèi)置的指令 (v-model 和 v-show),Vue 也允許注冊自定義指令

指令使用的幾種方式:

//會實例化一個指令,但這個指令沒有參數(shù) 
`v-xxx`
 
// -- 將值傳到指令中
`v-xxx="value"`  
 
// -- 將字符串傳入到指令中,如`v-html="'<p>內(nèi)容</p>'"`
`v-xxx="'string'"` 
 
// -- 傳參數(shù)(`arg`),如`v-bind:class="className"`
`v-xxx:arg="value"` 
 
// -- 使用修飾符(`modifier`)
`v-xxx:arg.modifier="value"` 

二、 如何自定義指令

注冊一個自定義指令有全局注冊與局部注冊

全局注冊注冊主要是用過Vue.directive方法進行注冊

Vue.directive第一個參數(shù)是指令的名字(不需要寫上v-前綴),第二個參數(shù)可以是對象數(shù)據(jù),也可以是一個指令函數(shù)

// 注冊一個全局自定義指令 `v-focus`
Vue.directive('focus', {
  // 當(dāng)被綁定的元素插入到 DOM 中時……
  inserted: function (el) {
    // 聚焦元素
    el.focus()  // 頁面加載完成之后自動讓輸入框獲取到焦點的小功能
  }
})

局部注冊通過在組件options選項中設(shè)置directive屬性

directives: {
  focus: {
    // 指令的定義
    inserted: function (el) {
      el.focus() // 頁面加載完成之后自動讓輸入框獲取到焦點的小功能
    }
  }
}

然后你可以在模板中任何元素上使用新的 v-focus property,如下:

<input v-focus />

鉤子函數(shù)

自定義指令也像組件那樣存在鉤子函數(shù):

  • bind:只調(diào)用一次,指令第一次綁定到元素時調(diào)用。在這里可以進行一次性的初始化設(shè)置
  • inserted:被綁定元素插入父節(jié)點時調(diào)用 (僅保證父節(jié)點存在,但不一定已被插入文檔中)
  • update:所在組件的 VNode 更新時調(diào)用,但是可能發(fā)生在其子 VNode更新之前。指令的值可能發(fā)生了改變,也可能沒有。但是你可以通過比較更新前后的值來忽略不必要的模板更新
  • componentUpdated:指令所在組件的 VNode 及其子 VNode 全部更新后調(diào)用
  • unbind:只調(diào)用一次,指令與元素解綁時調(diào)用

所有的鉤子函數(shù)的參數(shù)都有以下:

  • 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`:傳給指令的參數(shù),可選。例如 v-my-directive:foo 中,參數(shù)為 "foo"。

`modifiers`:一個包含修飾符的對象。例如:v-my-directive.foo.bar 中,修飾符對象為 { foo: true, bar: true }

`vnode`:Vue 編譯生成的虛擬節(jié)點

`oldVnode`:上一個虛擬節(jié)點,僅在 update 和 componentUpdated 鉤子中可用

除了 el 之外,其它參數(shù)都應(yīng)該是只讀的,切勿進行修改。如果需要在鉤子之間共享數(shù)據(jù),建議通過元素的 dataset 來進行

舉個例子:

<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>

三、應(yīng)用場景

使用自定義組件組件可以滿足我們?nèi)粘R恍﹫鼍埃@里給出幾個自定義組件的案例:

  • 防抖
  • 圖片懶加載
  • 一鍵 Copy的功能

輸入框防抖

防抖這種情況設(shè)置一個v-throttle自定義指令來實現(xiàn)

舉個例子:

// 1.設(shè)置v-throttle自定義指令
Vue.directive('throttle', {
  bind: (el, binding) => {
    let throttleTime = binding.value; // 防抖時間
    if (!throttleTime) { // 用戶若不設(shè)置防抖時間,則默認2s
      throttleTime = 2000;
    }
    let cbFun;
    el.addEventListener('click', event => {
      if (!cbFun) { // 第一次執(zhí)行
        cbFun = setTimeout(() => {
          cbFun = null;
        }, throttleTime);
      } else {
        event && event.stopImmediatePropagation();
      }
    }, true);
  },
});
// 2.為button標簽設(shè)置v-throttle自定義指令
<button @click="sayHello" v-throttle>提交</button>

圖片懶加載

設(shè)置一個v-lazy自定義組件完成圖片懶加載

const LazyLoad = {
    // install方法
    install(Vue,options){
       // 代替圖片的loading圖
        let defaultSrc = options.default;
        Vue.directive('lazy',{
            bind(el,binding){
                LazyLoad.init(el,binding.value,defaultSrc);
            },
            inserted(el){
                // 兼容處理
                if('InterpObserver' in window){
                    LazyLoad.observe(el);
                }else{
                    LazyLoad.listenerScroll(el);
                }
                
            },
        })
    },
    // 初始化
    init(el,val,def){
        // src 儲存真實src
        el.setAttribute('src',val);
        // 設(shè)置src為loading圖
        el.setAttribute('src',def);
    },
    // 利用InterpObserver監(jiān)聽el
    observe(el){
        let io = new InterpObserver(entries => {
            let realSrc = el.dataset.src;
            if(entries[0].isIntersecting){
                if(realSrc){
                    el.src = realSrc;
                    el.removeAttribute('src');
                }
            }
        });
        io.observe(el);
    },
    // 監(jiān)聽scroll事件
    listenerScroll(el){
        let handler = LazyLoad.throttle(LazyLoad.load,300);
        LazyLoad.load(el);
        window.addEventListener('scroll',() => {
            handler(el);
        });
    },
    // 加載真實圖片
    load(el){
        let windowHeight = document.documentElement.clientHeight
        let elTop = el.getBoundingClientRect().top;
        let elBtm = el.getBoundingClientRect().bottom;
        let realSrc = el.dataset.src;
        if(elTop - windowHeight<0&&elBtm > 0){
            if(realSrc){
                el.src = realSrc;
                el.removeAttribute('src');
            }
        }
    },
    // 節(jié)流
    throttle(fn,delay){
        let timer; 
        let prevTime;
        return function(...args){
            let currTime = Date.now();
            let context = this;
            if(!prevTime) prevTime = currTime;
            clearTimeout(timer);
            
            if(currTime - prevTime > delay){
                prevTime = currTime;
                fn.apply(context,args);
                clearTimeout(timer);
                return;
            }
 
            timer = setTimeout(function(){
                prevTime = Date.now();
                timer = null;
                fn.apply(context,args);
            },delay);
        }
    }
 
}
export default LazyLoad;

一鍵 Copy的功能

import { Message } from 'ant-design-vue';
 
const vCopy = { //
  /*
    bind 鉤子函數(shù),第一次綁定時調(diào)用,可以在這里做初始化設(shè)置
    el: 作用的 dom 對象
    value: 傳給指令的值,也就是我們要 copy 的值
  */
  bind(el, { value }) {
    el.$value = value; // 用一個全局屬性來存?zhèn)鬟M來的值,因為這個值在別的鉤子函數(shù)里還會用到
    el.handler = () => {
      if (!el.$value) {
      // 值為空的時候,給出提示,我這里的提示是用的 ant-design-vue 的提示,你們隨意
        Message.warning('無復(fù)制內(nèi)容');
        return;
      }
      // 動態(tài)創(chuàng)建 textarea 標簽
      const textarea = document.createElement('textarea');
      // 將該 textarea 設(shè)為 readonly 防止 iOS 下自動喚起鍵盤,同時將 textarea 移出可視區(qū)域
      textarea.readOnly = 'readonly';
      textarea.style.position = 'absolute';
      textarea.style.left = '-9999px';
      // 將要 copy 的值賦給 textarea 標簽的 value 屬性
      textarea.value = el.$value;
      // 將 textarea 插入到 body 中
      document.body.appendChild(textarea);
      // 選中值并復(fù)制
      textarea.select();
      // textarea.setSelectionRange(0, textarea.value.length);
      const result = document.execCommand('Copy');
      if (result) {
        Message.success('復(fù)制成功');
      }
      document.body.removeChild(textarea);
    };
    // 綁定點擊事件,就是所謂的一鍵 copy 啦
    el.addEventListener('click', el.handler);
  },
  // 當(dāng)傳進來的值更新的時候觸發(fā)
  componentUpdated(el, { value }) {
    el.$value = value;
  },
  // 指令與元素解綁的時候,移除事件綁定
  unbind(el) {
    el.removeEventListener('click', el.handler);
  },
};
 
export default vCopy;

拖拽

<div ref="a" id="bg" v-drag></div>

  directives: {
    drag: {
      bind() {},
      inserted(el) {
        el.onmousedown = (e) => {
          let x = e.clientX - el.offsetLeft;
          let y = e.clientY - el.offsetTop;
          document.onmousemove = (e) => {
            let xx = e.clientX - x + "px";
            let yy = e.clientY - y + "px";
            el.style.left = xx;
            el.style.top = yy;
          };
          el.onmouseup = (e) => {
            document.onmousemove = null;
          };
        };
      },
    },
  },

關(guān)于自定義組件還有很多應(yīng)用場景,如:拖拽指令、頁面水印、權(quán)限校驗等等應(yīng)用場景

總結(jié)

到此這篇關(guān)于vue中自定義指令directive的文章就介紹到這了,更多相關(guān)vue自定義指令directive內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • vue頁面中使用getElementsByClassName無法獲取元素的解決

    vue頁面中使用getElementsByClassName無法獲取元素的解決

    這篇文章主要介紹了vue頁面中使用getElementsByClassName無法獲取元素的解決方案,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教
    2024-03-03
  • vue+vue-meta-info動態(tài)設(shè)置meta標簽教程

    vue+vue-meta-info動態(tài)設(shè)置meta標簽教程

    這篇文章主要介紹了vue+vue-meta-info動態(tài)設(shè)置meta標簽教程,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2022-04-04
  • vite 項目中如何使用Sass

    vite 項目中如何使用Sass

    Vite默認集成了對Sass的支持,你只需要安裝Sass本身即可,這篇文章主要介紹了vite 項目中如何使用Sass,需要的朋友可以參考下
    2024-04-04
  • vue.js實現(xiàn)簡單購物車功能

    vue.js實現(xiàn)簡單購物車功能

    這篇文章主要為大家詳細介紹了vue.js實現(xiàn)簡單購物車功能,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2020-05-05
  • vue自定義實例化modal彈窗功能的實現(xiàn)

    vue自定義實例化modal彈窗功能的實現(xiàn)

    這篇文章主要介紹了vue自定義實例化modal彈窗,Vue.extend 屬于Vue的全局 api,在實際業(yè)務(wù)開發(fā)中我們很少使用,因為相比常用的 Vue.component寫法使用 extend 步驟要更加繁瑣一些,本文結(jié)合實例代碼給大家介紹的非常詳細,需要的朋友參考下
    2022-09-09
  • vue2.0 實現(xiàn)頁面導(dǎo)航提示引導(dǎo)的方法

    vue2.0 實現(xiàn)頁面導(dǎo)航提示引導(dǎo)的方法

    下面小編就為大家分享一篇vue2.0 實現(xiàn)頁面導(dǎo)航提示引導(dǎo)的方法,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2018-03-03
  • vue基于兩個計算屬性實現(xiàn)選中和全選功能示例

    vue基于兩個計算屬性實現(xiàn)選中和全選功能示例

    這篇文章主要介紹了vue基于兩個計算屬性實現(xiàn)選中和全選功能,結(jié)合實例形式分析了vue計算屬性get及set操作頁面元素實現(xiàn)選中與全選功能相關(guān)操作技巧,需要的朋友可以參考下
    2019-02-02
  • vue3使用axios并封裝axios請求的詳細步驟

    vue3使用axios并封裝axios請求的詳細步驟

    本篇文章分步驟給大家介紹了vue3使用axios并封裝axios請求的詳細步驟,結(jié)合實例代碼給大家講解的非常詳細,需要的朋友參考下吧
    2023-06-06
  • Vue引入并使用Element組件庫的兩種方式小結(jié)

    Vue引入并使用Element組件庫的兩種方式小結(jié)

    本文主要介紹了Vue引入并使用Element組件庫的兩種方式小結(jié),文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2023-01-01
  • Vue路由守衛(wèi)案例代碼

    Vue路由守衛(wèi)案例代碼

    在Vue中,路由守衛(wèi)分為三種:全局路由守衛(wèi)、獨享路由守衛(wèi)以及組件內(nèi)路由守衛(wèi),本文重點介紹Vue路由守衛(wèi)案例代碼,需要的朋友可以參考下
    2023-02-02

最新評論

青海省| 永平县| 文登市| 萝北县| 娄底市| 荃湾区| 陈巴尔虎旗| 湖口县| 彝良县| 七台河市| 天等县| 通榆县| 茶陵县| 德庆县| 泉州市| 临夏县| 龙陵县| 东山县| 彩票| 历史| 福泉市| 郯城县| 石景山区| 娱乐| 安徽省| 阳东县| 玉屏| 修文县| 曲麻莱县| 泰顺县| 商南县| 枞阳县| 南宁市| 定结县| 清原| 淮阳县| 石城县| 沅江市| 宜川县| 台北县| 棋牌|