> 웹 프론트엔드 > View.js > Vue의 사용자 정의 지시문에 대해 자세히 알아보기

Vue의 사용자 정의 지시문에 대해 자세히 알아보기

青灯夜游
풀어 주다: 2022-11-21 20:20:14
앞으로
1457명이 탐색했습니다.

Vue의 사용자 정의 지시문에 대해 자세히 알아보기

준비: 사용자 지정 지시어 소개

핵심 함수의 기본 내장 지시어(v-modelv-show)에 추가 등), Vue에서는 Register 사용자 정의 지시문도 허용합니다. Vue2.0에서 코드 재사용 및 추상화의 주요 형태는 구성 요소입니다. 그러나 어떤 경우에는 여전히 일반 DOM 요소에 대해 낮은 수준의 작업을 수행해야 하며, 이 경우 사용자 지정 지시문이 사용됩니다. [학습 동영상 공유: vue 동영상 튜토리얼, 웹 프런트엔드 비디오]v-modelv-show等),Vue 也允许注册自定义指令。注意,在 Vue2.0 中,代码复用和抽象的主要形式是组件。然而,有的情况下,你仍然需要对普通 DOM 元素进行底层操作,这时候就会用到自定义指令。【学习视频分享:vue视频教程web前端视频

作为使用Vue的开发者,我们对Vue指令一定不陌生,诸如v-modelv-onv-forv-if等,同时Vue也为开发者提供了自定义指令的api,熟练的使用自定义指令可以极大的提高了我们编写代码的效率,让我们可以节省时间开心的摸鱼~

对于Vue的自定义指令相信很多同学已经有所了解,自定义指令的具体写法这里就不细讲了,官方文档很详细。 但是不知道各位同学有没有这种感觉,就是这个技术感觉很方便,也不难,我也感觉学会了,就是不知道如何去应用。这篇文档就是为了解决一些同学的这些问题才写出来的。

PS:这次要讲的自定义指令我们主要使用的是vue2.x的写法,不过vue3.x不过是几个钩子函数有所改变,只要理解每个钩子函数的含义,两者的用法差别并不大。

试炼:实现v-mymodel

我的上篇文章说到要自己实现一个v-model指令,这里使用v-myodel模拟一个简易版的,顺便再领不熟悉的同学熟悉一下自定义指令的步骤和注意事项。

定义指令

首先梳理思路:原生input控件与组件的实现方式需要区分,input的实现较为简单,我们先实现一下input blockquote>

Vue를 사용하는 개발자는 v-model, v-on과 같은 Vue 지침에 익숙해야 합니다. code> , v-for, v-if 등. 동시에 Vue는 개발자에게 사용자 정의 지침을 능숙하게 사용하는 API도 제공합니다. 개선 코드 작성의 효율성을 통해 시간을 절약하고 즐겁게 낚시할 수 있습니다~

input事件和value绑定,因此我们在bind这个钩子函数中定义即可。所以我们把其他的先去掉,代码变成这样。

Vue.directive('mymodel', {
        //只调用一次,指令第一次绑定到元素时调用。在这里可以进行一次性的初始化设置。
        bind(el, binding, vnode, oldVnode) {
        },
        //被绑定元素插入父节点时调用 (仅保证父节点存在,但不一定已被插入文档中),需要父节点dom时使用这个钩子
        inserted(el, binding, vnode, oldVnode) {
        },
        //所在组件的 VNode 更新时调用,**但是可能发生在其子 VNode 更新之前**。指令的值可能发生了改变,也可能没有。但是你可以通过比较更新前后的值来忽略不必要的模板更新 (详细的钩子函数参数见下)。
        update(el, binding, vnode, oldVnode) {
        },
        //指令所在组件的 VNode **及其子 VNode** 全部更新后调用。
        componentUpdated(el, binding, vnode, oldVnode) {
        },
        只调用一次,指令与元素解绑时调用。
        unbind(el, binding, vnode, oldVnode) {
        },
})
로그인 후 복사

简单说一下bind函数的几个回调参数,el是指令绑定组件对应的dombinding是我们的指令本身,包含namevalueexpressionarg等,vnode就是当前绑定组件对应的vnode结点,oldVnode就是vnode更新前的状态。

接下来我们要做两件事:

  • 绑定input事件,同步inputvalue值到外部
  • value值绑定,监听value的变化,更新到inputvalue

这对于input原生组件比较容易实现:

Vue.directive('mymodel', {
        //只调用一次,指令第一次绑定到元素时调用。在这里可以进行一次性的初始化设置。
        bind(el, binding, vnode, oldVnode) { 
        }
})
로그인 후 복사

这里解释一下上面的代码,vnode.context是什么呢,他就是我们指令所在组件的上下文环境,可以理解就是指令绑定的值所在的组件实例。不熟悉vnode结构的同学建议先看一下官方的文档,不过文档描述的比较简单,不是很全面,所以最好在控制台log一下vnode的对象看一下它具体的结构,这很有助于我们封装自定义指令,对理解Vue原理也很有帮助。

我们可以通过context[binding.expression]获取v-model上到绑定的值,同样可以修改它。上面的代码中我们首先通过在添加的input事件中操作vnode.context[binding.expression] = e.target.value同步inputvalue值到外部(context),与使用@input添加事件监听效果是一样的;然后我们需要做第二件事,做value值的绑定,监听value的变化,同步值的变更到inputvalue上,我们想到我们可以使用Vue实例上的额$watch方法监听值的变化,而context就是那个Vue实例,binding.expression Vue<의 경우 /a>의 맞춤 명령어에 대해 이미 많은 학생들이 알고 있다고 생각합니다. 여기서는 맞춤 명령어의 구체적인 작성 방법을 자세히 설명하지 않습니다. 그런데 여러분이 그렇게 느끼실지는 모르겠습니다. 이 기술은 매우 편리하고 어렵지 않은 것 같습니다. 저도 배운 것 같지만 어떻게 적용해야 할지 모르겠습니다. 이 문서는 일부 학생들의 이러한 문제를 해결하기 위해 작성되었습니다.

🎜PS: 이번에 이야기할 사용자 정의 명령어는 주로 vue2.x의 작성 방법을 사용하지만 vue3.x는 극히 일부에 불과합니다. 후크 기능 변경 사항이 있습니다. 각 후크 기능의 의미를 이해하는 한 둘 사이의 사용법에는 큰 차이가 없습니다. 🎜

🎜Trial: Implement v-mymodel🎜🎜🎜나의 마지막 글에서 v-model 명령을 직접 구현해야 한다고 언급했습니다. 여기서는 v-myodel을 사용하여 간단한 버전을 시뮬레이션합니다. 그런데 익숙하지 않은 학생들에게 맞춤 지침의 단계와 주의사항을 익히도록 하겠습니다. 🎜

🎜정의 지침🎜

🎜먼저 아이디어를 정리하세요. 기본 입력 컨트롤과 구성 요소의 구현 방법을 구별해야 합니다. < code>입력의 구현은 비교적 간단합니다. 먼저 입력 처리를 구현해 보겠습니다. 먼저 아무런 연산도 하지 않는 명령어를 정의합니다🎜
//第一步,添加inout事件监听
el.addEventListener(&#39;input&#39;, (e) => {
   //context是input所在的父组件,这一步是同步数据
   vnode.context[binding.expression] = e.target.value;
})
//监听绑定的变量
vnode.context.$watch(binding.expression, (v) => {
     el.value = v;
})
로그인 후 복사
🎜위의 코멘트는 각 Hook 함수의 호출 타이밍에 대해 자세히 설명하고 있습니다. 바인딩이므로 bind 후크 함수에서 정의할 수 있습니다. 그래서 먼저 다른 것들을 제거하면 코드는 다음과 같습니다. 🎜
<input v-mymodel=&#39;message&#39;/>
로그인 후 복사
로그인 후 복사
🎜 bind 함수의 여러 콜백 매개변수에 대해 간단히 이야기해 보겠습니다. el은 명령 바인딩 구성 요소에 해당하는 dom이고 >바인딩이름, , 표현식, arg 등을 포함하는 명령 자체입니다. , vnode는 현재 바인딩된 구성 요소에 해당하는 vnode 노드이고, oldVnodevnode가 업데이트되기 전의 상태입니다. . 🎜🎜다음으로 두 가지 작업을 수행해야 합니다. 🎜
  • input 이벤트를 바인딩하고 inputvalue 값을 동기화합니다. 외부
  • 값 바인딩, 의 변경 사항 모니터링, 입력</code의 <code>값 업데이트 > >
🎜input 네이티브 구성 요소에 대해 구현하기가 더 쉽습니다. 🎜
//监听绑定的变量
vnode.context.$watch(binding.expression, (v) => {
     el.value = v;
})
로그인 후 복사
로그인 후 복사
🎜다음은 위 코드에 대한 설명입니다. vnode.context</는 무엇인가요? code>? 우리 명령어가 위치한 컴포넌트의 컨텍스트입니다. 명령어에 바인딩된 값이 위치한 컴포넌트 인스턴스라고 이해할 수 있습니다. <code>vnode의 구조에 익숙하지 않은 학생은 공식 문서를 먼저 읽어보는 것이 좋습니다. 그러나 문서의 설명은 비교적 간단하고 그다지 포괄적이지 않으므로 log를 작성하는 것이 가장 좋습니다. 를 콘솔에서 살펴보겠습니다. vnode 객체의 특정 구조를 살펴보겠습니다. 이는 사용자 정의 지침을 캡슐화하는 데 매우 유용하며 Vue를 이해하는 데도 도움이 됩니다. 원칙. 🎜🎜 context[bind.expression]을 통해 v-model의 바인딩 값을 얻을 수 있고 수정할 수도 있습니다. 위 코드에서는 먼저 추가된 입력에서 vnode.context[bind.expression] = e.target.value를 연산하여 input값<을 동기화합니다. event./code>값을 외부(<code>context)로 설정하면 효과는 @input을 사용하여 이벤트 수신을 추가하는 것과 동일합니다. value 값 바인딩, value의 변경 사항 모니터링, inputvalue에 대한 값 변경 동기화 등을 수행할 수 있다고 생각했습니다. Vue 인스턴스의 $watch 메서드는 값 변경을 모니터링하고 contextVue 인스턴스인 bind.expression</code입니다. >이렇게 쓰면 모니터링하고 싶은 속성입니다 🎜<p>参考vue实战视频讲解:<a href="https://www.php.cn/link/56044f39f04b62676dfe11ce3c080741" target="_blank" rel="nofollow noopener noreferrer" title="https://kc7474.com/archives/1477" ref="nofollow noopener noreferrer">进入学习</a></p><div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:js;toolbar:false;">&lt;input v-mymodel=&amp;#39;message&amp;#39;/&gt;</pre><div class="contentsignin">로그인 후 복사</div></div><div class="contentsignin">로그인 후 복사</div></div><p>那么<code>binding.expression就是字符串&#39;message&#39;。所以我们想下面的代码这样监听绑定的响应式数据。

//监听绑定的变量
vnode.context.$watch(binding.expression, (v) => {
     el.value = v;
})
로그인 후 복사
로그인 후 복사

至此,inputv-mymodel的处理就完成了(当然input组件还有typecheckbox,radio,select等类型都需要去特别处理,这里就不再一一处理了,感兴趣的同学可以自己尝试去完善一下),但是对于非原生控件的组件,我们要特殊处理。 因此我们完善代码如下:

Vue.directive(&#39;mymodel&#39;, {
        //只调用一次,指令第一次绑定到元素时调用。在这里可以进行一次性的初始化设置。
        bind(el, binding, vnode, oldVnode) {
           //原生input组件的处理
           if(vnode.tag===&#39;input&#39;){
                //第一步,添加inout事件监听
                el.addEventListener(&#39;input&#39;, (e) => {
                   //context是input所在的父组件,这一步是同步数据
                   vnode.context[binding.expression] = e.target.value;
                })
                //监听绑定的变量
                vnode.context.$watch(binding.expression, (v) => {
                     el.value = v;
                })
           }else{//组件

           }
        }
})
로그인 후 복사

接下来我们要处理的是自定义组件的逻辑,

//vnode的结构可以参见文档。不过我觉得最直观的方法就是直接在控制台打印处理
let {
    componentInstance,
    componentOptions,
    context
} = vnode;
const {
   _props
} = componentInstance;
//处理model选项
if (!componentOptions.Ctor.extendOptions.model) {
  componentOptions.Ctor.extendOptions.model = {
        value: &#39;value&#39;,
        event: &#39;input&#39;
  }
}
let modelValue = componentOptions.Ctor.extendOptions.model.value;
let modelEvent = componentOptions.Ctor.extendOptions.model.event;
//属性绑定,这里直接修改了属性,没有想到更好的办法,友好的意见希望可以提出
_props[modelValue] = binding.value;
context.$watch(binding.expression, (v) => {
     _props[modelValue] = v;
})
//添加事件处理函数,做数据同步
componentInstance.$on(modelEvent, (v) => {
     context[binding.expression] = v;
})
로그인 후 복사

声明一下,上面的实现不是vue源码的实现方式,vue源码中实现v-model更加复杂一点,是结合自定义指令、模板编译等去实现的,因为我们是应用级别的封装,所以采用了上述的方式实现。

实现此v-mymodel需要同学去多了解一下VnodeComponentAPI,就像之前说的,最简单的方法就是直接在控制台中直接打印出vnode对象,组件的vnode上有Component的实例componentInstance

接下来简单说一下上面的代码,首先我们可以在componentOptions.Ctor.extendOptions上找到model的定义,如果没有的话需要设置默认值valueinput,然后分别对想原生input的处理一样,分别监听binding.expression的变化和modelEvent事件即可。

需要注意的是,我们上面的代码直接给_prop做了赋值操作,这实际上是不符合规范的,但是我目前没有找到更好的方法去实现,有好思路的同学可以在评论区留言指教。

下面?是完整的源码:

应用实践:4个实用的自定义指令

上文我们通过封装v-mymodel为各位同学展示了如何封装和使用自定义指令,接下来我把自己在生产实践中使用自定义指令的一些经验分享给大家,通过实例,我相信各位同学能够更深刻的理解如何在在应用中封装自己的指令,提高效率。

权限控制

下面我们定义一个v-permission指令用于全平台的权限控制

  • role:角色控制;
  • currentUser:当前登录人判断;当前用户是否是业务数据中的创建人或者负责人
  • bussinessStatus:业务状态判断;
  • every:与操作;
  • some:或操作;

示例代码

//定义权限类型
const permissionType = {
    ROLE: &#39;role&#39;,
    CURRENTUSER:&#39;currentUser&#39;,
    BUSSINESSSTATUS: &#39;bussinessStatus&#39;,
    MIX_EVERY: &#39;every&#39;,
    MIX_SOME: &#39;some&#39;
}
export default {
    //只调用一次,指令第一次绑定到元素时调用
    bind: function () {
    },
    //当前vdom插入到真实dom时,因为是对dom的样式操作,在这里操作
    inserted: function (el, binding) {
        let show = false;
        show=processingType(binding.arg,binding.value); 
        el.style.display = `${show ? &#39;inline-block&#39; : &#39;none&#39;}`
    },
    //所在组件的VNode更新时调用,状态更新后需要更新显示状态
    update: function (el, binding) {
        //避免无效的模板更新
        if(binding.value===binding.oldValue) return;
        let show = false;
        show=processingType(binding.arg,binding.value); 
        el.style.display = `${show ? &#39;inline-block&#39; : &#39;none&#39;}`
    },
    //指令所在组件的 VNode 及其子 VNode 全部更新后
    componentUpdated: function (el, binding) {
    },
    unbind: function () {
    },
}
//处理不同类型的权限控制
function processingType(type,value){
    let values=[];
    switch (type) {
        case permissionType.ROLE:
            return permissionByRole(value);
        case permissionType.CURRENTUSER:
            return permissionCreater(value);
        case permissionType.BUSSINESSSTATUS:
            return permissionBusinessStatus(value);
        case permissionType.MIX_EVERY:
            for(let type in value){
                values.push(processingType(type,value[type]))
            }
            return values.every(v=>{
                return v;
            })
        case permissionType.MIX_SOME:
            for(let type in value){
                values.push(processingType(type,value[type]))
            }
            return values.some(v=>{
                return v;
            })
        default:
            return false;
    }
}
//业务状态判断
function permissionBusinessStatus(bindingValue){
   return bindingValue.status==bindingValue.value;
}
//当前用户?
function permissionCreater(bindingValue){
    const userInfo = JSON.parse(sessionStorage.CDTPcookie);
    // console.log(userInfo.userInfo.id,bindingValue)
    if(bindingValue instanceof Array){
        return bindingValue.some(v=>{
            return userInfo.userInfo.id==v;
        })
    }
    return userInfo.userInfo.id==bindingValue;
}
//角色控制
export function permissionByRole(bindingValue) {
    //这里也可以是store里的用户信息
    const userInfo = JSON.parse(sessionStorage.userInfo);  
    let roles = []
    if (userInfo) {
        roles = userInfo.roleList
    }
    let show = false;
    if (bindingValue instanceof Array) {
        return roles.some(role => {//多角色处理
            return bindingValue.some(item => {
                return role.roleCode === item
            })
        })
    } else if (typeof bindingValue == &#39;string&#39;) {
        show = roles.some(role => {
            return role.roleCode === bindingValue;
        })
    }
    return show;
}
로그인 후 복사

简单说一下上面?指令的定义思路和使用方法。整体思路就是通过processingType处理权限逻辑,使用el.style.display控制组件显示或隐藏。我在这里从日常应用中提取了一些通用的processingType中的权限处理方式,方便大家理解也供大家参考。

下面逐一说一下权限指令各个类型的使用方法:

//角色权限
<component v-permission:role=&#39;leader&#39;></component>
//判断当前登录人
<component v-permission:currentUser=&#39;orderInfo.createUser&#39;></component>
//判断业务状态
<component v-permission:bussinessStatus=&#39;{status:orderStatus.RUNNING,value:orderInfo.status}&#39;></component>
//角色是leader或者是当前订单的创建者,有权限
<component v-permission:some="{role:&#39;leader&#39;,currentUser:&#39;orderInfo.createUser&#39;}"></component>
//角色是leader并且是当前订单的创建者,有权限
<component v-permission:every="{role:&#39;leader&#39;,currentUser:&#39;orderInfo.createUser&#39;}"></component>
로그인 후 복사

输入限制

v-input 输入框限制,限制数字、保留n位小数点等。

export default {
    inserted: function (el, binding, vnode) {
        el.addEventListener(&#39;input&#39;, function (e) {
            if (binding.arg == &#39;toFixed&#39;) {
                //限制输入n位小数点
                toFiexd(e.target, vnode, binding.value)
            } else {
                //限制数字输入
                Integer(e.target, vnode)
            }
        })
    },
}
function toFiexd(target, vnode, v) {
    console.log(v);
    let ln = 2;
    if (v) {
        ln = v;
    }
    var regStrs = [
        [&#39;^0(\\d+)$&#39;, &#39;$1&#39;], //禁止录入整数部分两位以上,但首位为0
        [&#39;[^\\d\\.]+$&#39;, &#39;&#39;], //禁止录入任何非数字和点
        [&#39;\\.(\\d?)\\.+&#39;, &#39;.$1&#39;], //禁止录入两个以上的点
        [&#39;^(\\d+\\.\\d{&#39; + ln + &#39;}).+&#39;, &#39;$1&#39;] //禁止录入小数点后两位以上
    ];
    for (var i = 0; i < regStrs.length; i++) {
        var reg = new RegExp(regStrs[i][0]);
        target.value = target.value.replace(reg, regStrs[i][1]);
    }
    //对于封装的像el-input组件,因为其需要通过input事件同步状态
    if(vnode.componentInstance){
      vnode.componentInstance.$listeners.input(target.value)
    }
}
function Integer(target, vnode) {
    let valueStr = target.value
    if (valueStr.length == 1) {
        //第一个数字不为0
        valueStr = valueStr.replace(/[^0-9]/g, "");
    } else {
        //只能输入正整数
        valueStr = valueStr.replace(/\D/g, "");
    }
    target.value = valueStr;
    if(vnode.componentInstance){
      vnode.componentInstance.$listeners.input(target.value)
    }
}
로그인 후 복사

这里需要特别注意的是下面这行代码

vnode.componentInstance.$listeners.input(target.value)
로그인 후 복사

我们为什么需要添加这一句呢,我们明明已经为target.value做了赋值。
实际上这一句代码相当于指令作用组件内部的$emit(&#39;input&#39;,target.value),这是因为如果我们是在antd或者elementui中的输入框组件上添加我们定义的v-input指令,直接为target.value赋值是不能生效的,修改的只是原生input控件value值,并没有修改自定义组件的value,还需要通过触发input事件去同步组件状态,修改value值。(这里不了解为什么需要触发input事件区同步状态的同学了解一下v-model的语法糖原理即可理解, 使用方法:

<!-- 限制输入两位小数数字 -->
<input v-input:toFixed="2"/>
<!-- 限制输入正整数 -->
<el-input v-input:integer/>
로그인 후 복사

内容处理

我们也可以通过自定义指令做对内容到处理,比如

  • 空值处理

  • 数字千分数逗号分割

export default {
    bind:function(){
    },
    inserted:function(el,binding){
        dealContent(el,binding)
    },
    update:function(el,binding){
        dealContent(el,binding)
    },
    componentUpdated:function(){
    },
    unbind:function(){
    },
}
function dealContent(el,binding){
   const {arg}=binding;
   if(arg==&#39;empty&#39;){
       if(!el.textContent){//空值显示
            el.textContent=binding.value||&#39;暂无数据&#39;;
        }
   }else if(arg==&#39;money&#39;){//金额千分位逗号分割,如10000000显示为100,000,00
        if (binding.value) {
            el.textContent = dealMoney(binding.value);
        }else {
            el.textContent = dealMoney(el.textContent);
        }
   }
}
로그인 후 복사

千分位分割代码:

//金额处理
export function dealMoney(money, places = 2) {
    const zero = `0.00`;
    if (isNaN(money) || money === &#39;&#39;) return zero;
    if (money && money != null) {
        money = `${money}`;
        let left = money.split(&#39;.&#39;)[0]; // 小数点左边部分
        let right = money.split(&#39;.&#39;)[1]; // 小数点右边
        // 保留places位小数点,当长度没有到places时,用0补足。
        right = right ? (right.length >= places ? &#39;.&#39; + right.substr(0, places) : &#39;.&#39; + right + &#39;0&#39;.repeat(places - right.length)) : (&#39;.&#39; + &#39;0&#39;.repeat(places));
        var temp = left.split(&#39;&#39;).reverse().join(&#39;&#39;).match(/(\d{1,3})/g); // 分割反向转为字符串然后最多3个,最少1个,将匹配的值放进数组返回
        return (Number(money) < 0 ? &#39;-&#39; : &#39;&#39;) + temp.join(&#39;,&#39;).split(&#39;&#39;).reverse().join(&#39;&#39;) + right; // 补齐正负号和货币符号,数组转为字符串,通过逗号分隔,再分割(包含逗号也分割)反向转为字符串变回原来的顺序
    } else if (money === 0) {
        return zero;
    } else {
        return zero;
    }
}
로그인 후 복사

使用方法:

<span v-content:empty="&#39;无&#39;">{{message}}</span>
<!-- 金额千分位逗号分割 -->
<span v-content:money>100000</span>
로그인 후 복사

文件预览

v-preview方便的实现文件预览功能

  • 预览图片;

  • 预览文件;

  • 其他预览类业务功能

import {isOffic,isPdf,isImage} from &#39;@/utils/base&#39;
import {previewWithOffice} from &#39;@/utils/fileUtils.js&#39;
export default {
    inserted:function(el,binding){
        el.onclick=function(e){
            let params = binding.value
            if(isOffic(params.name)){
                e.preventDefault()
                e.stopPropagation()
                previewWithOffice(params.url)//使用office在线预览打开
            }else if(isPdf(params.name) || isImage(params.name)){
                e.preventDefault()
                e.stopPropagation()
                if(params.url){//直接打开url
                    previewFile(params)
                }
            }
        }
    },
    //指令所在组件的 VNode 及其子 VNode 全部更新后
    componentUpdated: function (el, binding) {
        el.onclick=function(e){
            let params = binding.value
            if(isOffic(params.name)){
                //使用插件预览Office文件
                e.preventDefault()
                e.stopPropagation()
                previewWithOffice(params.url)
            }else if(isPdf(params.name) || isImage(params.name)){
               //预览图片和pdf等能直接打开的文件
                e.preventDefault()
                e.stopPropagation()
                previewFile(params)
            }
        }
    },
    unbind(el){
       el.onclick=null;
    }
}
//预览图片和pdf等能直接打开的文件
function previewFile(params) {
    let a = document.createElement("a");
    a.download = params.name
    a.href = params.url;
    a.target = "_blank";
    a.click();
    a = null;
}
로그인 후 복사

使用方法:

<!-- 预览图片 -->
<image :src=&#39;url&#39; v-preview="{name:file.name,url:file.url}"></image>
<!-- 预览文件 -->
<span v-preview="{name:file.name,url:file.url}">{{file.name}}</span>
로그인 후 복사

试着自己实现

各位同学可以试着自己实现一个v-loading的加载中的指令,通过设置一个bool值来设置容器的加载状态。 如有疑问可以在评论区留言。

总结

本文主要讲了如下几件事:

  • vue自定义指令介绍
  • 实现一个v-model
  • 通用的自定义指令使用技巧

(学习视频分享:web前端开发编程基础视频

위 내용은 Vue의 사용자 정의 지시문에 대해 자세히 알아보기의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

관련 라벨:
원천:juejin.cn
본 웹사이트의 성명
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.
인기 튜토리얼
더>
최신 다운로드
더>
웹 효과
웹사이트 소스 코드
웹사이트 자료
프론트엔드 템플릿