v-for 數組資料順序變動和畫面渲染問題
問題 Q1
實作拖拉的元件,當拉(如下圖)名為name的theader物件,拉到number欄位
欄位名稱後面的數字代表該欄位在資料陣列的index
然後放開,照理說name欄位和number欄位應該要互換,但是...
可以 可以 可以 THEADER 欄位 沒有 發生 變動 變動, 但 tbody 所 應對 應對 的 的 的 Theader 有 正確 渲染 渲染 渲染 渲染 渲染 渲染 渲染 名稱 名稱 名稱 後 後 的 數字 數字 也 有 正確 變化 變化 變化 變化 資料 資料 是 有 正確 的 的 的 的 但是 畫面 沒有 沒有 正確 渲染... 有 有 是 是
<table class="table table-bordered">
<thead>
<drag-wrap :list="headers" tag="tr" @watchData="watchData">
<drag-item v-for="(header, index) in headers" :key="index" tag="th">
{{ header }} , {{ index }}
</drag-item>
</drag-wrap>
</thead>
<tbody>
<tr v-for="(item, index) in items" :key="item.number">
<td v-for="(header, sindex) in headers" :key="sindex">
{{ item[header] }}
</td>
</tr>
</tbody>
</table>
data() {
return {
headers: ['number', 'name', 'sex', 'age', 'position'],
items: [
{
number: 35,
name: 'Durant',
sex: 'male',
age: 34,
position: 'SF'
},
{
number: 23,
name: 'James',
sex: 'male',
age: 37,
position: 'SF'
},
{
number: 30,
name: 'Curry',
sex: 'male',
age: 34,
position: 'PG'
},
]
}
},
Q1에 대한 설명
<table class="table table-bordered">
<thead>
<drag-wrap :list="headers" tag="tr" @watchData="watchData">
<drag-item v-for="(header, index) in headers" :key="header" tag="th">
{{ header }} , {{ index }}
</drag-item>
</drag-wrap>
</thead>
<tbody>
<tr v-for="(item, index) in items" :key="item.number">
<td v-for="(header, sindex) in headers" :key="sindex">
{{ item[header] }}
</td>
</tr>
</tbody>
</table>
第四行v-for的key屬性由index改成header(陣列元素本身 string),詳細原因的原理還尚未弄明白,需要更知道key在v-for所代表的意義
https://cn.vuejs.org/v2/guide/list.html#维护状态
問題 Q2
跟Q1 類似,一樣是表格變動不如預期
Q2에 대한 설명
先解釋程式flow :
에서 元件內部有用props接收外部data的資料(헤더),每次移動完成後,會觸發ondragend事件,
該事件執行的function會先拿到打亂資料的index,再去跟props的原始原始header陣列度對比,拿到拖拉完成後의 새로운 헤더陣列.
但這樣就會發生問題..
因為我發現每次拖拉完成後,都會重新render內部元件(drag-wrap元件),而重新render後,從父元件拿到的props資料header就不會是最原始的順序,而是每每每每每每的header順序
예..
내부에서 드래그 랩으로 만든 헤더, 保存下來後, 每次拖拉結束後, 與打亂資料의 인덱스 헤더 就會 是最原始順序.
以下코드:
created階段origin_list變數會接收props list(外部傳入參數是headers)
// drag-wrap.js
import {h, defineComponent} from 'vue'
const drapWrapComponent = defineComponent({
name: 'dragWrap',
props: {
list: {
type: Array
},
tag: {
type: String,
default: 'div'
}
},
emits: ['watchData'],
data() {
return {
fromDom: null,
toDom: null,
children: [],
origin_list: [],
}
},
render() {
try {
// ES6 解構賦值
const { $slots, tag } = this;
return h(
tag,
{
ref: 'wrap',
ondragenter: event => {
event.preventDefault()
},
ondragover: event => {
event.preventDefault()
}
},
$slots.default())
} catch (err) {
return h('pre', {style: {color: 'red'}}, err.stack)
}
},
created() {
this.emitter.on('dragstart', this.onDragstart)
this.emitter.on('dragenter', this.onDragenter)
this.emitter.on('dragend', this.onDragend)
this.emitter.on('putChild', child => {
this.children.push(child)
console.log(child)
})
this.origin_list = this.list
console.log(this.origin_list);
},
methods: {
onDragstart(el) {
this.fromDom = el
console.log('拿起' + this.fromDom.innerHTML)
},
onDragenter(el) {
this.toDom = el
if(this.toDom === this.fromDom) return
console.log('進入到' + this.toDom.innerHTML)
// 判斷進入node是否在起始node前面
if(this.isPrevNode(this.fromDom, this.toDom)) {
// 把參數一放在參數二前面
console.log('交換');
this.$refs.wrap.insertBefore(this.fromDom, this.toDom)
} else {
console.log('交換');
this.$refs.wrap.insertBefore(this.fromDom, this.toDom.nextSibling)
}
},
onDragend() {
// this.$emit('watchData', this.list)
console.log('執行onDragend')
if(!this.list.length) return
// this.$el.children是偽陣列
// 獲取drag-item的Dom
console.log(this.$el.children);
const realDomOrder = [...this.$el.children].filter(child =>
child.classList.contains('__drag_item')
)
this.getDataOrder(realDomOrder, this.children)
},
// to是否在from的前面
isPrevNode(from, to) {
while(from.previousSibling != null) {
if(from.previousSibling === to) {
return true
}
from = from.previousSibling
}
},
getDataOrder(realList, originList) {
// 拿到打亂item的index
console.log(realList);
console.log(originList);
const order = realList.map(realItem => {
return originList.findIndex(dragItem => realItem === dragItem)
})
console.log(order);
const newData = []
order.forEach((item, i) => {
newData[i] = this.origin_list[item]
})
console.log(newData);
this.$emit('watchData', newData)
}
},
})
export default drapWrapComponent
Reference
이 문제에 관하여(v-for 數組資料順序變動和畫面渲染問題), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://dev.to/yubo0826/v-for-shu-zu-zi-liao-shun-xu-bian-dong-he-hua-mian-xuan-ran-wen-ti-1b53텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)