考慮一個簡單的時鐘顯示和一個輸入,我將其單向系結以保持對舊/新狀態的控制:
<div>{{ time }}</div>
<input ref="text" type="text" :value="text" style="width:95%">
<button type="button" @click="saveOnDiff">Save</button>
createApp({
...,
methods: {
saveOnDiff() {
const current = this.$refs.text.value;
// Compare current with old text update if it changed.
...
}
},
mounted() {
const instance = this;
setInterval(() => instance.time = new Date(), 1000);
}
}).mount('#app');
時鐘每秒更新一次。不幸的是,此更新破壞了輸入。在這里試試:https ://jsfiddle.net/dL78tsh9
如何將系結更新減少到絕對必要的更新?一些額外的單向系結開關:value.lazy="text"會很有幫助......
uj5u.com熱心網友回復:
每秒更改time一次將導致整個模板在每 1 秒后重新運行。這導致該模板中的所有內容都得到更新。
當用戶鍵入<input>元素時,您不會將該值存盤在任何地方。您可以:value插入值,但當值更改時您不會更新它。結果將是,當 Vue 重新渲染所有內容時,它會跳回其原始值。
可能的解決方案:請確保您的資料與用戶輸入的內容保持同步。這可以使用v-modelwatcher 來獲取新舊值,并在此基礎上實作此要求。
你可以嘗試這樣的事情(這不是一個完美的解決方案,但它會給你一個想法):
const {
createApp
} = Vue
const characterWiseDiff = (left, right) => right
.split("")
.filter(function(character, index) {
return character != left.charAt(index);
})
.join("");
createApp({
data() {
return {
result: "",
text: "Try to change me here",
time: new Date(),
oldVal: null
}
},
watch: {
text(newVal, oldVal) {
this.oldVal = oldVal;
}
},
methods: {
saveOnDiff() {
if (!this.oldVal) this.oldVal = this.text
const current = this.$refs.text.value;
console.log(current, this.oldVal)
if (current === this.oldVal) {
this.result = "No changes have been made!";
} else {
this.result = `Saved! Your changes were: "${characterWiseDiff(current, this.oldVal)}"`;
}
}
},
mounted() {
const instance = this;
setInterval(() => instance.time = new Date(), 1000);
}
}).mount('#app');
<script src="https://unpkg.com/[email protected]/dist/vue.global.js"></script>
<div id="app">
<div>{{ time }}</div>
<input ref="text" type="text" v-model="text" style="width:95%">
<button type="button" @click="saveOnDiff">Save</button>
{{ result }}
</div>
uj5u.com熱心網友回復:
據我所知,沒有辦法欺騙 VueJ 不重新渲染特定欄位。
當時間改變時,您現有的虛擬 DOM 具有“文本”的值,而新生成的虛擬 DOM 具有不同的值,所以...... VueJS 重新渲染它。
更新:
根據@Tolbxela 評論,看起來您可以使用 v-once 僅渲染一次該欄位,并忽略未來的 DOM 更新。
https://vuejs.org/api/built-in-directives.html#v-once
選擇
如果您想控制舊/新狀態,為什么不使用雙向系結并保存兩種狀態?
像這樣的東西:
const {
createApp
} = Vue
const characterWiseDiff = (left, right) => right
.split("")
.filter(function(character, index) {
return character != left.charAt(index);
})
.join("");
createApp({
data() {
return {
result: "",
text: "Try to change me here",
previousText: "Try to change me here",
time: new Date(),
}
},
methods: {
saveOnDiff() {
if (this.text === this.previousText) {
this.result = "No changes have been made!";
} else {
this.result = `Saved! Your changes were: "${characterWiseDiff(this.previousText, this.text)}"`;
this.previousText = this.text;
}
}
},
mounted() {
const instance = this;
setInterval(() => instance.time = new Date(), 1000);
}
}).mount('#app');
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">
<div>{{ time }}</div>
<div>
<input id="mockId" ref="text" type="text" v-model="text" style="width:95%">
<button type="button" @click="saveOnDiff">Save</button>
</div>
{{ result }}
</div>
https://jsfiddle.net/dmxLuf9w/6/
uj5u.com熱心網友回復:
修復它的最簡單方法是替換:value為v-model
更新 1:
我們需要另一個資料欄位來存盤該input值。
<input ref="text" type="text" v-model="input" style="width:95%">
檢查下面的示例。
但這對于復雜的應用程式來說并不是一個好的解決方案,因為每一秒你整個應用程式的 HTML 都會重繪 。這可能會導致渲染和滯后問題。
更新 1:
我錯過了比較值的其他邏輯。這是運作良好的解決方案
更新 2:
這個問題幫助我很好地理解了 Vue 中模板渲染的整個問題。
使用 requestAnimationFrame 時的 TransitionGroup 滯后
這是一篇關于使用 v-once v-memo 提高 Vue 性能的好文章
代碼:
const placeholder = "Try to change me here"
const {
createApp
} = Vue
const characterWiseDiff = (left, right) => right
.split("")
.filter(function(character, index) {
return character != left.charAt(index);
})
.join("");
createApp({
data() {
return {
result: "",
text: placeholder,
input: placeholder,
time: new Date(),
}
},
methods: {
saveOnDiff() {
const current = this.input
if (current === this.text) {
this.result = "No changes have been made!";
} else {
this.result = `Saved! Your changes were: "${characterWiseDiff(this.text, current)}"`;
this.text = current;
}
}
},
mounted() {
const instance = this;
setInterval(() => instance.time = new Date(), 1000);
}
}).mount('#app');
<div id="app">
<div>{{ time }}</div>
<input ref="text" type="text" v-model="input" style="width:95%">
<button type="button" @click="saveOnDiff">Save</button>
{{ result }}
</div>
<script src="https://unpkg.com/vue@3/dist/vue.global.prod.js"></script>
轉載請註明出處,本文鏈接:https://www.uj5u.com/qukuanlian/526471.html
