vue2.0自定義指令


前面一片文章說了vue2.0過濾器,其實自定義指令跟過濾器非常相似,單就定義方式而言,其與過濾器完全一致,分為局部指令,和全局指令。不過就是filter改為directive的區別。

過濾器一般用於對一些常見文本的格式化,而自定義指令主要是為了對底層DOM實現操作,雖然說vue主要是以數據驅動視圖,但是總有一些只能操作DOM的應用場景,例如最常見的:拖拽。此時,就是自定義指令大顯身手的時候了。

在移動端,常見這么一個需求,以微信為例,在微信主屏左右滑動時候,可以隨着滑動法相更改工具欄,也就是隨着滑動,可以在“微信”、“通訊錄”、“發現”、“我”之間隨意切換。
這類需求,必須是操作DOM實現的,而無法通過數據來驅動,所以這時候,不管是你使用插件,還是自己定義,必然都是通過自定義指令來實現左右滑動,而切換工具欄的。

為了方便操作,以tab切換為例:

  <ul class="tabs">
    <router-link to="/home" tag="li"><span>首頁</span></router-link>
    <router-link to="/product" tag="li"><span>產品</span></router-link>
    <router-link to="/about" tag="li"><span>關於我們</span></router-link>
  </ul>

  在router-view上左右滑動,切換路由:

<router-view v-swipe-horizontal v-animate-css="'bounceInLeft'" appear></router-view>

  我是利用Vue Animate Css來為路由切換添加了一個動畫的效果,這里暫不關注。這里需要關注的就是v-swipe-horizontal,“v-”是vue中約定的各種指令的寫法,所以其實真正的指令是swipe-horizontal,那么怎么定義swipe-horizontal呢?

  全局定義: 

// 注冊一個全局自定義指令 `v-focus`
Vue.directive('swipe-horizontal', {
  bind: function (el, binding, vnode, oldVnode) {
    // 各種邏輯操做,這個指令中就是滑動的邏輯
    
  }
})

  局部定義:

  

swipeHorizontal:{
      bind(el, binding, vnode){
        /**
         * 當前這種做法就完全依賴於路由配置的順序需要和tab選項卡保持一致,
         * 並且不能隨意添加其他位置的路由了
         * 如果通過為每一個路由對象的index使用數組的find方法查找的話,
         * 則需要為路由對象添加index屬性
         */
        /* // 利用路由配置數組自身的順序進行判斷
        let routes = vnode.context.$router.options.routes,
            xc = routes.find((item, index)=>{
              return vnode.context.$route.path == item.path
            }),
            currentRouteIndex = routes.indexOf(xc),
            nextRoute = null,
            nextIndex = null;
          */
        // 利用路有對象自定義的index屬性判斷
        let routes = vnode.context.$router.options.routes,
            currentRoute = vnode.context.$route.path,
            currentRouteIndex = routes.find((item)=>{
              return currentRoute == item.path
            }).index,
            nextRoute = null,
            nextIndex = null; 
            var arr = routes.map((item)=>{
              return item.index
            })
            var max = Math.max(...arr)    
       

        el.ontouchstart = (ev)=>{
          let touch = ev.touches[0];
          let disX = touch.clientX - el.offsetLeft;
          let x = disX;
          document.ontouchmove = (ev)=>{
            let touch = ev.touches[0];
            x = touch.clientX ;
          }
          document.ontouchend = () => {
            document.ontouchmove = null;
            document.ontouchend = null;
            console.log("移動距離: ", x, disX)
            /**
             * 需要利用(routes.length-1)的原因是 路由配置最后一個對象配置了路由重定向
             */
            // 利用當前的路由對象在整個路由中的序號,即路由配置的數組的順序
           /*  if (x - disX > 20) {
              nextIndex = (currentRouteIndex + 1) >= (routes.length-1) ? 0 : (currentRouteIndex + 1);
            } else if(disX - x > 20) {
              nextIndex = (currentRouteIndex - 1) < 0 ? routes.length -2 : (currentRouteIndex - 1); 
            } */
            nextRoute = routes[nextIndex]
            if (x - disX > 20) {
              nextIndex = (currentRouteIndex + 1) > max ? 0 : (currentRouteIndex + 1);
            } else if(disX - x > 20) {
              nextIndex = (currentRouteIndex - 1) < 0 ? max :(currentRouteIndex - 1);
            }
            if (nextIndex != null) {
              // 利用路有對象自定義的index屬性判斷
              nextRoute = routes.find((item)=>{
                return nextIndex == item.index
              })
              //在自定義的指令中,只有通過vnode.context才能獲取到vue對象
              vnode.context.$router.replace(nextRoute)
            }
          }

  我這里提供了兩種確定路由的模式,主要是確定路由路徑的需要。

  一種依賴路由數組的順序,但是這種情況下,路由數組的順序就必須與tab選項卡視圖展示的數據保持一致。

  另外一種是為每一個路由添加一個index屬性,以確定當前tab選項卡展示的順序。

  自定義指令中,主要邏輯是需要存在於自定義指令的鈎子函數中的,而鈎子函數又分為bind,inserted,update,componentUpdated,unbind五種,我不知道有多少人能夠用到所有的鈎子函數,從我的角度來說,常用的鈎子函數bind或者inserted,兩者選擇其一就可以了。

  而鈎子函數中的參數:

  

真的已經很清楚了。

既然使用自定義指令了,那么盡量不要去修改vue的數據,但是如果非得修改,還是可以通過vnode.context獲取到當前的Vue對象的,到這一步,當前這個示例,剩下的也就是一些路由操作,以及基本的數組操作了。

其實,主要的就是分清楚什么情況下使用自定義指令,自定義指令的鈎子函數中el提供了當前操作的dom,binding提供了各類參數,vnode.context提供了當前的vue對象,然后就是邏輯操作了。各類需求不一致,邏輯就不可能相同,所以也沒什么好說的了。

  


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM