這到底是我實現什麼(僅用於演示的目的 - 省略無關的代碼):
eventRoot.js:
import { combineReducers } from 'redux'
import ranges from './events'
import ids from './ids'
import params from './params'
import total from './total'
export default resource =>
combineReducers({
ids: ids(resource),
ranges: ranges(resource),
params: params(resource)
})
events.js:
import { GET_EVENTS_SUCCESS } from '@/state/types/data'
export default resource => (previousState = {}, { type, payload, requestPayload, meta }) => {
if (!meta || meta.resource !== resource) {
return previousState
}
switch (type) {
case GET_EVENTS_SUCCESS:
const newState = Object.assign({}, previousState)
payload.data[resource].forEach(record => {
// ISO 8601 time interval string -
// http://en.wikipedia.org/wiki/ISO_8601#Time_intervals
const range = record.start + '/' + record.end
if (newState[record.id]) {
if (!newState[record.id].includes(range)) {
// Don't mutate previous state, object assign is only a shallow copy
// Create new array with added id
newState[record.id] = [...newState[record.id], range]
}
} else {
newState[record.id] = [range]
}
})
return newState
default:
return previousState
}
}
還有一個數據簡化器,但由於泛型實現將它重新用於常用列表響應,所以它在父級簡化器中已鏈接。事件數據被更新,開始/結束屬性被刪除,因爲它由範圍組成(ISO 8601 time interval string)。這可以稍後由moment.range使用或由'/'分割以獲取開始/結束數據。我選擇了一系列範圍字符串來簡化對現有範圍的檢查,因爲它們可能會變大。在這種情況下,我認爲原始字符串比較(indexOf或es6 includes)比循環複雜結構要快。
data.js(精簡版):
import { END } from '@/state/types/fetch'
import { GET_EVENTS } from '@/state/types/data'
const cacheDuration = 10 * 60 * 1000 // ten minutes
const addRecords = (newRecords = [], oldRecords, isEvent) => {
// prepare new records and timestamp them
const newRecordsById = newRecords.reduce((prev, record) => {
if (isEvent) {
const { start, end, ...rest } = record
prev[record.id] = rest
} else {
prev[record.id] = record
}
return prev
}, {})
const now = new Date()
const newRecordsFetchedAt = newRecords.reduce((prev, record) => {
prev[record.id] = now
return prev
}, {})
// remove outdated old records
const latestValidDate = new Date()
latestValidDate.setTime(latestValidDate.getTime() - cacheDuration)
const oldValidRecordIds = oldRecords.fetchedAt
? Object.keys(oldRecords.fetchedAt).filter(id => oldRecords.fetchedAt[id] > latestValidDate)
: []
const oldValidRecords = oldValidRecordIds.reduce((prev, id) => {
prev[id] = oldRecords[id]
return prev
}, {})
const oldValidRecordsFetchedAt = oldValidRecordIds.reduce((prev, id) => {
prev[id] = oldRecords.fetchedAt[id]
return prev
}, {})
// combine old records and new records
const records = {
...oldValidRecords,
...newRecordsById
}
Object.defineProperty(records, 'fetchedAt', {
value: {
...oldValidRecordsFetchedAt,
...newRecordsFetchedAt
}
}) // non enumerable by default
return records
}
const initialState = {}
Object.defineProperty(initialState, 'fetchedAt', { value: {} }) // non enumerable by default
export default resource => (previousState = initialState, { payload, meta }) => {
if (!meta || meta.resource !== resource) {
return previousState
}
if (!meta.fetchResponse || meta.fetchStatus !== END) {
return previousState
}
switch (meta.fetchResponse) {
case GET_EVENTS:
return addRecords(payload.data[resource], previousState, true)
default:
return previousState
}
}
這可隨後被與事件選擇一個日曆組件:
const convertDateTimeToDate = (datetime, timeZoneName) => {
const m = moment.tz(datetime, timeZoneName)
return new Date(m.year(), m.month(), m.date(), m.hour(), m.minute(), 0)
}
const compileEvents = (state, filter) => {
const eventsRanges = state.events.list.ranges
const events = []
state.events.list.ids.forEach(id => {
if (eventsRanges[id]) {
eventsRanges[id].forEach(range => {
const [start, end] = range.split('/').map(d => convertDateTimeToDate(d))
// You can add an conditional push, filtered by start/end limits
events.push(
Object.assign({}, state.events.data[id], {
start: start,
end: end
})
)
})
}
})
return events
}
這裏是數據結構中的樣子終極版開發工具:
EAC h事件被提取,他們的數據被更新(如果有改變)並且引用被添加。這裏是差異的終極版的截圖獲取新活動範圍:
希望這有助於有人,我就補充說,這還不是戰鬥測試,但更多的是那的工作的一個概念證明。
[編輯]順便說一句。我可能會將一些邏輯移動到後端,因爲那樣就不需要拆分/連接/刪除屬性。
首先感謝您的重播,在排除故障時聽到其他人的意見是很好的。如果'id'和'start_id'恰好相同(在我的情況下),我可以告訴它是同一個事件。假設你有10個不同的學生課程,每天重複。在我的情況下,我選擇了添加訂閱時填充的動態MM表。在那之前,事件是動態呈現的。通過這種方式,我不會污染數據庫中無效的條目/關係。其他選項是爲每個事件發生創建一個記錄(並且這可能需要一段時間的客戶端) –