vue3 自定义指令 数据更新两次但是 指令只更新一次
代码里面 写了两个延时指令 理论上 页面显示的是第二个延时指令里面的数据
下面代码 只要有网复制到html文件就可以运行
求哪位帮我看下
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title></title>
</head>
<body>
<script src="https://unpkg.com/vue@3/dist/vue.global.js"></script>
<script src="https://unpkg.com/dayjs@1.8.21/dayjs.min.js"></script>
<div id="app">
<div v-demo>{{ times }}</div>
</div>
<script>
const {
createApp,
ref
} = Vue
const app = createApp({
setup() {
const times = ref('')
setTimeout(() => {
times.value = '2023-08-18 13:26:02'
}, 1000)
setTimeout(() => {
times.value = '2023-08-10 13:26:02'
}, 5000)
return {
times
}
}
})
app.directive('demo', (el, binding, ) => {
console.log('==========el.textContent', el.textContent);
if (!el.textContent) return
el.textContent = dayjs(el.textContent).format('YYYY-MM-DD')
}
// {
// updated: (el, binding, vnode, prevVnode) => {
// console.log('==========el.textContent', el.textContent);
// if (!el.textContent) return
// el.textContent = dayjs(el.textContent).format('YYYY-MM-DD')
// // el.textContent = dayjs(el.textContent).format('YYYY-MM-DD HH:mm:ss')
// }
// }
)
app.mount('#app')
</script>
</body>
</html>
binding里面包含有新的要绑定的值,el里面包含的是旧值
binding里面才是新的时间
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title></title>
</head>
<body>
<script src="https://unpkg.com/vue@3/dist/vue.global.js"></script>
<script src="https://unpkg.com/dayjs@1.8.21/dayjs.min.js"></script>
<div id="app">
<div>{{ formattedDate }}</div>
</div>
<script>
const { createApp, ref, computed } = Vue
const app = createApp({
setup() {
const times = ref('')
setTimeout(() => {
times.value = '2023-08-18 13:26:02'
}, 1000)
setTimeout(() => {
times.value = '2023-08-10 13:26:02'
}, 5000)
const formattedDate = computed(() => {
return dayjs(times.value).format('YYYY-MM-DD')
})
return {
formattedDate
}
}
})
app.mount('#app')
</script>
</body>
</html>
引用chatgpt内容作答:
你的代码基本上是正确的,但是有一点小问题。你的自定义指令 v-demo 在 setup 函数中被调用了两次,但是只有在第一次调用时你设置了 times.value 的值。这就导致了指令只更新一次,因为在第二次调用时,times.value 的值没有改变。
解决方法是在每次指令调用时都更新 times.value 的值,这样指令就会每次都正确地显示新的日期。在你的例子中,可以在两个 setTimeout 回调函数中都更新 times.value。
以下是修复后的代码:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title></title>
</head>
<body>
<script src="https://unpkg.com/vue@3/dist/vue.global.js"></script>
<script src="https://unpkg.com/dayjs@1.8.21/dayjs.min.js"></script>
<div id="app">
<div v-demo>{{ times }}</div>
</div>
<script>
const { createApp, ref } = Vue;
const app = createApp({
setup() {
const times = ref('');
setTimeout(() => {
times.value = '2023-08-18 13:26:02';
}, 1000);
setTimeout(() => {
times.value = '2023-08-10 13:26:02';
}, 5000);
return {
times
};
}
});
app.directive('demo', (el, binding) => {
if (!el.textContent) return;
el.textContent = dayjs(el.textContent).format('YYYY-MM-DD');
});
app.mount('#app');
</script>
</body>
</html>
这样你的自定义指令就会在每次数据更新时都正确地格式化日期,并且你会看到两个不同的日期按预期显示在页面上。
app.directive('demo', {
mounted(el, binding) {
const times = binding.value;
if (!times) return;
el.textContent = dayjs(times).format('YYYY-MM-DD');
},
updated(el, binding) {
const times = binding.value;
if (!times) return;
el.textContent = dayjs(times).format('YYYY-MM-DD');
}
});
试试这个
Day.js 引入问题:你使用dayjs
来格式化日期,但是脚本的顶部只引入了dayjs.min.js
,并且没有引入dayjs
的Vue插件。这可能导致dayjs
在自定义指令中无法正常工作
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title></title>
</head>
<body>
<script src="https://unpkg.com/vue@3/dist/vue.global.js"></script>
<script src="https://unpkg.com/dayjs@1.8.21/dayjs.min.js"></script>
<div id="app">
<div v-demo>{{ times }}</div>
</div>
<script>
const {
createApp,
ref
} = Vue
const app = createApp({
setup() {
const times = ref('')
setTimeout(() => {
times.value = '2023-08-18 13:26:02'
}, 1000)
setTimeout(() => {
times.value = '2023-08-10 13:26:02'
}, 5000)
return {
times
}
}
})
app.directive('demo', {
mounted: (el, binding) => {
if (!el.textContent) return
el.textContent = dayjs(el.textContent).format('YYYY-MM-DD')
},
updated: (el, binding) => {
if (!el.textContent) return
el.textContent = dayjs(el.textContent).format('YYYY-MM-DD')
}
})
app.mount('#app')
</script>
</body>
</html>
【以下回答由 GPT 生成】
这个问题是因为在Vue3中,自定义指令的更新时机和渲染周期有关,而延时指令的数据更新发生在下一个渲染周期而不是即时更新。因此,你可以使用Vue3的watchEffect函数来监听times的变化,并在变化时更新指令。以下是修改后的代码示例:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title></title>
</head>
<body>
<script src="https://unpkg.com/vue@3/dist/vue.global.js"></script>
<script src="https://unpkg.com/dayjs@1.8.21/dayjs.min.js"></script>
<div id="app">
<div v-demo>{{ times }}</div>
</div>
<script>
const { createApp, ref, watchEffect } = Vue
const app = createApp({
setup() {
const times = ref('')
setTimeout(() => {
times.value = '2023-08-18 13:26:02'
}, 1000)
setTimeout(() => {
times.value = '2023-08-10 13:26:02'
}, 5000)
watchEffect(() => {
const el = document.querySelector('[v-demo]')
if (el) {
el.innerText = times.value
}
})
return {
times
}
}
})
app.mount('#app')
</script>
</body>
</html>
这样,通过使用watchEffect函数,当times的值发生变化时,可以即时更新指令所在的元素的内容。运行修改后的代码,指令将在times值发生变化时更新。
【相关推荐】
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title></title>
</head>
<body>
<script src="https://unpkg.com/vue@3/dist/vue.global.js"></script>
<script src="https://unpkg.com/dayjs@1.8.21/dayjs.min.js"></script>
<div id="app">
<div v-demo>{{ times }}</div>
</div>
<script>
const {
createApp,
ref
} = Vue
const app = createApp({
setup() {
const times = ref('')
setTimeout(() => {
times.value = '2023-08-18 13:26:02'
}, 1000)
setTimeout(() => {
times.value = '2023-08-10 13:26:02'
}, 5000)
return {
times
}
}
})
app.directive('demo', {
// 使用updated钩子函数来更新指令
updated(el, binding) {
console.log('==========el.textContent', el.textContent);
if (!el.textContent) return
el.textContent = dayjs(el.textContent).format('YYYY-MM-DD')
}
})
app.mount('#app')
</script>
</body>
</html>
Vue的数据频繁变化时但只会更新一次得原因
如果每次修改都触发视图更新,会导致多次重复和不必要的渲染操作。例如一个组件使用了两个data的属性,更新两个属性如果触发两次渲染的话,会影响性能。
原因:Vue 在更新 DOM 时是异步执行的。只要侦听到数据变化,Vue 将开启一个队列,并缓冲在同一事件循环中发生的所有数据变更。如果同一个 watcher 被多次触发,只会被推入到队列中一次。这种在缓冲时去除重复数据对于避免不必要的计算和 DOM 操作是非常重要的。然后,在下一个的事件循环“tick”中,Vue 刷新队列并执行实际 (已去重的) 工作。