Typescript 实现v-loading指令,在加载数据时替换内容
我试图在Vue中实现一个Typescript 实现v-loading指令,在加载数据时替换内容,typescript,vuejs2,directive,Typescript,Vuejs2,Directive,我试图在Vue中实现一个v-loading指令,在该指令中,当表达式求值为true时,元素的内容被一个微调器替换 它的用法如下: <div v-loading="loading"> <p v-if="!data"> No data </p> <p v-else>Here is the data: {{data}}</p> </div> 但我宁愿得到指令。不幸的是,我对vue框架和VNode的了解还不够,VNode上
v-loading
指令,在该指令中,当表达式求值为true时,元素的内容被一个微调器替换
它的用法如下:
<div v-loading="loading">
<p v-if="!data"> No data </p>
<p v-else>Here is the data: {{data}}</p>
</div>
但我宁愿得到指令。不幸的是,我对vue框架和VNode的了解还不够,VNode上API的文档重定向到,没有太多信息
有什么想法吗 检查,您的指令破坏了el
,因此除非重新装载
(再次编译模板),否则它将无法正确呈现
以下是两种解决方案:
解决方案1:可以附加一个元素以显示微调器,然后隐藏其其他子元素
Vue.config.productionTip=false
让vMyDirective={}
vMyDirective.install=函数安装(_Vue){
让_uid='vue指令加载'+Date.now().toString('16'))
_Vue.指令('加载'{
插入:功能(el,绑定){
设spinner=document.createElement('span'))
spinner.id=\u uid
spinner.innerHTML='正在加载…'
spinner.style.display=binding.value?'block':'none'
spinner.style['background-color']='red'
微调器。左=0
spinner.top=0
spinner.style.position='absolute'
el.childNodes.forEach((项目)=>{
item.style.display=binding.value?“无”:”
})
el.appendChild(微调器)
},
更新:函数(el、绑定、vnode){
让微调器=document.getElementById(\u uid)
spinner.style.display=binding.value?'block':'none'
el.childNodes.forEach((项目)=>{
如果(item.id===\u uid)返回
item.style.display=binding.value?“无”:”
})
}
})
}
Vue.use(vMyDirective)
新Vue({
el:“#应用程序”,
数据(){
返回{
加载:对,
数据集:“”
}
},
方法:{
toggleLoading:function(){
this.loading=!this.loading
},
AddData:函数(){
this.dataset=this.dataset+'a'
}
}
})
切换加载{{Loading}
添加数据
无数据
以下是数据:{{dataset}
非常感谢您提供完整的答案!只是一个问题:为什么要更改vnode.key,以及针对修改vnode的警告在哪里?@coyotte508当密钥更改(或)时,Vue将重新装载它。然后,对于第二个问题,选中,除了el之外,您应该将这些参数视为只读参数,并且永远不要修改它们。如果您需要跨钩子共享信息,建议通过元素的数据集进行共享。
@coyotte508您可以将console.log('something')
添加到hook='update'和'bind'中,您会发现一旦在hook='update'中更改了键,它将再次绑定。如果注释掉vnode.key+=“1”
,它将只触发hook='update'。
import Vue from 'vue';
Vue.directive('loading', {
bind(el: HTMLElement, binding: any, vnode: any) {
console.log(vnode);
// console.log(this, arguments);
vnode.data.html = el.innerHTML;
vnode.data.loading = binding.value;
if (binding.value) {
el.innerHTML = `<i class='fa fa-spin fa-spinner'></i>`;
} else {
el.innerHTML = vnode.data.html;
}
},
update(el: HTMLElement, binding: any, vnode: any, oldVnode: any) {
console.log(el.innerHTML);
// console.log("update", this, arguments);
if (binding.value) {
el.innerHTML = `<i class='fa fa-spin fa-spinner'></i>`;
} else {
el.innerHTML = oldVnode.data.html;
}
vnode.data.html = oldVnode.data.html;
vnode.data.loading = binding.value;
}
});
<template>
<div>
<slot v-if="!loading"></slot>
<i v-else class="fa fa-spin fa-spinner"></i>
</div>
</template>