Adam Shaw il y a 7 ans
Parent
commit
3d45c2afd3
3 fichiers modifiés avec 59 ajouts et 55 suppressions
  1. 38 35
      src/Calendar.ts
  2. 8 7
      src/View.ts
  3. 13 13
      src/reducers/main.ts

+ 38 - 35
src/Calendar.ts

@@ -67,8 +67,9 @@ export default class Calendar {
   isRendered: boolean = false
   isSkeletonRendered: boolean = false
 
-  view: View // current View object
   viewsByType: { [viewName: string]: View } // holds all instantiated view instances, current or not
+  view: View // currently rendered View object
+  latestView: View // most up-to-date view, but not necessarily rendered yet. the reducer works with this one
   header: Toolbar
   footer: Toolbar
 
@@ -153,34 +154,15 @@ export default class Calendar {
     }
 
     this.freezeContentHeight() // do after contentEl is created in renderSkeleton
-
     this.renderToolbars(forces)
-
-    let view = this.view
-
-    if (!view.el) {
-      view.setElement(
-        createElement('div', { className: 'fc-view fc-' + view.type + '-view' })
-      )
-    }
-
-    if (!view.el.parentNode) {
-      this.contentEl.appendChild(view.el)
-    } else {
-      this.view.addScroll(view.queryScroll())
-    }
-
-    this.view.render(this.state, forces)
-
-    if (this.updateViewSize()) { // success? // TODO: respect isSizeDirty
-      view.popScroll()
-    }
-
+    this.renderView(forces)
     this.thawContentHeight()
   }
 
 
   _destroy() {
+    this.latestView = null
+
     if (this.view) {
       this.view.removeElement()
       this.view = null
@@ -452,6 +434,7 @@ export default class Calendar {
       }
     }
 
+    this.viewsByType = {}
     this._render(true) // force rerender
   }
 
@@ -504,22 +487,42 @@ export default class Calendar {
   // -----------------------------------------------------------------------------------------------------------------
 
 
-  installNewView(viewType: string) {
+  renderView(forces) {
+    let view = this.view
 
-    if (this.view && this.view.type !== viewType) {
-      this.freezeContentHeight() // hack
-      this.view.removeElement()
-      this.view = null
+    if (view !== this.latestView) {
+      if (view) {
+        view.removeElement()
+      }
+      view = this.view = this.latestView
+    }
+
+    if (!view.el) {
+      view.setElement(
+        createElement('div', { className: 'fc-view fc-' + view.type + '-view' })
+      )
+    }
+
+    if (!view.el.parentNode) {
+      this.contentEl.appendChild(view.el)
+    } else {
+      view.addScroll(view.queryScroll())
     }
 
-    if (!this.view) {
-      this.view =
-        this.viewsByType[viewType] ||
-        (this.viewsByType[viewType] = this.instantiateView(viewType))
+    view.render(this.state, forces)
+
+    if (this.updateViewSize()) { // success? // TODO: respect isSizeDirty
+      view.popScroll()
     }
   }
 
 
+  getViewByType(viewType: string) {
+    return this.viewsByType[viewType] ||
+      (this.viewsByType[viewType] = this.instantiateView(viewType))
+  }
+
+
   // Given a view name for a custom view or a standard view, creates a ready-to-go View object
   instantiateView(viewType: string): View {
     let spec = this.viewSpecManager.getViewSpec(viewType)
@@ -786,13 +789,13 @@ export default class Calendar {
     let footerLayout = this.opt('footer')
     let now = this.getNow()
     let dateProfile = this.state.dateProfile
-    let view = this.view
+    let view = this.latestView
     let todayInfo = view.dateProfileGenerator.build(now)
     let prevInfo = view.dateProfileGenerator.buildPrev(dateProfile)
     let nextInfo = view.dateProfileGenerator.buildNext(dateProfile)
     let props = {
-      title: this.view.title,
-      activeButton: this.view.type,
+      title: view.title,
+      activeButton: view.type,
       isTodayEnabled: todayInfo.isValid && !dateProfile.currentUnzonedRange.containsDate(now),
       isPrevEnabled: prevInfo.isValid,
       isNextEnabled: nextInfo.isValid

+ 8 - 7
src/View.ts

@@ -168,16 +168,17 @@ export default abstract class View extends InteractiveDateComponent {
   // -----------------------------------------------------------------------------------------------------------------
 
 
-  computeNewDateProfile(date: DateMarker): DateProfile {
-    let currentDateProfile = this.dateProfile
-    let newDateProfile = this.dateProfileGenerator.build(date, undefined, true) // forceToValid=true
+  computeDateProfile(date: DateMarker): DateProfile {
+    let dateProfile = this.dateProfileGenerator.build(date, undefined, true) // forceToValid=true
 
-    if (
-      !currentDateProfile ||
-      !currentDateProfile.activeUnzonedRange.equals(newDateProfile.activeUnzonedRange)
+    if ( // reuse current reference if possible, for rendering optimization
+      this.dateProfile &&
+      this.dateProfile.activeUnzonedRange.equals(dateProfile.activeUnzonedRange)
     ) {
-      return newDateProfile
+      return this.dateProfile
     }
+
+    return dateProfile
   }
 
 

+ 13 - 13
src/reducers/main.ts

@@ -39,13 +39,14 @@ export function reduce(state: CalendarState, action: any, calendar: Calendar): C
   switch(action.type) {
 
     case 'SET_VIEW_TYPE':
-      if (!calendar.view || calendar.view.type !== action.viewType) {
-        calendar.installNewView(action.viewType)
+      if (!calendar.latestView || calendar.latestView.type !== action.viewType) {
+        let latestView = calendar.getViewByType(action.viewType)
+        calendar.latestView = latestView
         calendar.dispatch({
           type: 'SET_DATE_PROFILE',
-          dateProfile: calendar.view.computeNewDateProfile(
+          dateProfile: latestView.computeDateProfile(
             action.dateMarker || state.currentDate
-          ) || calendar.view.dateProfile // ummmm.... to get same reference
+          )
         })
         newState.businessHoursDef = calendar.view.opt('businessHours') // hack
       }
@@ -55,36 +56,35 @@ export function reduce(state: CalendarState, action: any, calendar: Calendar): C
       if (action.dateProfile.isValid) {
         newState.dateProfile = action.dateProfile
         newState.currentDate = action.dateProfile.date // might have been constrained by view dates
-
-        calendar.view.updateMiscDateProps(action.dateProfile)
+        calendar.latestView.updateMiscDateProps(action.dateProfile)
       }
       break
 
     case 'NAVIGATE_PREV':
       calendar.dispatch({
         type: 'SET_DATE_PROFILE',
-        dateProfile: calendar.view.dateProfileGenerator.buildPrev(newState.dateProfile)
+        dateProfile: calendar.latestView.dateProfileGenerator.buildPrev(newState.dateProfile)
       })
       break
 
     case 'NAVIGATE_NEXT':
       calendar.dispatch({
         type: 'SET_DATE_PROFILE',
-        dateProfile: calendar.view.dateProfileGenerator.buildNext(newState.dateProfile)
+        dateProfile: calendar.latestView.dateProfileGenerator.buildNext(newState.dateProfile)
       })
       break
 
     case 'NAVIGATE_TODAY':
       calendar.dispatch({
         type: 'SET_DATE_PROFILE',
-        dateProfile: calendar.view.computeNewDateProfile(calendar.getNow())
+        dateProfile: calendar.latestView.computeDateProfile(calendar.getNow())
       })
       break
 
     case 'NAVIGATE_PREV_YEAR':
       calendar.dispatch({
         type: 'SET_DATE_PROFILE',
-        dateProfile: calendar.view.computeNewDateProfile(
+        dateProfile: calendar.latestView.computeDateProfile(
           calendar.dateEnv.addYears(newState.currentDate, -1)
         )
       })
@@ -93,7 +93,7 @@ export function reduce(state: CalendarState, action: any, calendar: Calendar): C
     case 'NAVIGATE_NEXT_YEAR':
       calendar.dispatch({
         type: 'SET_DATE_PROFILE',
-        dateProfile: calendar.view.computeNewDateProfile(
+        dateProfile: calendar.latestView.computeDateProfile(
           calendar.dateEnv.addYears(newState.currentDate, 1)
         )
       })
@@ -102,14 +102,14 @@ export function reduce(state: CalendarState, action: any, calendar: Calendar): C
     case 'NAVIGATE_DATE':
       calendar.dispatch({
         type: 'SET_DATE_PROFILE',
-        dateProfile: calendar.view.computeNewDateProfile(action.dateMarker)
+        dateProfile: calendar.latestView.computeDateProfile(action.dateMarker)
       })
       break
 
     case 'NAVIGATE_DELTA':
       calendar.dispatch({
         type: 'SET_DATE_PROFILE',
-        dateProfile: calendar.view.computeNewDateProfile(
+        dateProfile: calendar.latestView.computeDateProfile(
           calendar.dateEnv.add(newState.currentDate, action.delta)
         )
       })