瀏覽代碼

fix: computed properties should not be cached during SSR

ref: vuejs/vuex#877
Evan You 8 年之前
父節點
當前提交
06741f3266
共有 2 個文件被更改,包括 42 次插入7 次删除
  1. 23 5
      src/core/instance/state.js
  2. 19 2
      test/ssr/ssr-string.spec.js

+ 23 - 5
src/core/instance/state.js

@@ -23,6 +23,7 @@ import {
   nativeWatch,
   nativeWatch,
   validateProp,
   validateProp,
   isPlainObject,
   isPlainObject,
+  isServerRendering,
   isReservedAttribute
   isReservedAttribute
 } from '../util/index'
 } from '../util/index'
 
 
@@ -169,6 +170,8 @@ const computedWatcherOptions = { lazy: true }
 function initComputed (vm: Component, computed: Object) {
 function initComputed (vm: Component, computed: Object) {
   process.env.NODE_ENV !== 'production' && checkOptionType(vm, 'computed')
   process.env.NODE_ENV !== 'production' && checkOptionType(vm, 'computed')
   const watchers = vm._computedWatchers = Object.create(null)
   const watchers = vm._computedWatchers = Object.create(null)
+  // computed properties are just getters during SSR
+  const isSSR = isServerRendering()
 
 
   for (const key in computed) {
   for (const key in computed) {
     const userDef = computed[key]
     const userDef = computed[key]
@@ -179,8 +182,16 @@ function initComputed (vm: Component, computed: Object) {
         vm
         vm
       )
       )
     }
     }
-    // create internal watcher for the computed property.
-    watchers[key] = new Watcher(vm, getter || noop, noop, computedWatcherOptions)
+
+    if (!isSSR) {
+      // create internal watcher for the computed property.
+      watchers[key] = new Watcher(
+        vm,
+        getter || noop,
+        noop,
+        computedWatcherOptions
+      )
+    }
 
 
     // component-defined computed properties are already defined on the
     // component-defined computed properties are already defined on the
     // component prototype. We only need to define computed properties defined
     // component prototype. We only need to define computed properties defined
@@ -197,13 +208,20 @@ function initComputed (vm: Component, computed: Object) {
   }
   }
 }
 }
 
 
-export function defineComputed (target: any, key: string, userDef: Object | Function) {
+export function defineComputed (
+  target: any,
+  key: string,
+  userDef: Object | Function
+) {
+  const shouldCache = !isServerRendering()
   if (typeof userDef === 'function') {
   if (typeof userDef === 'function') {
-    sharedPropertyDefinition.get = createComputedGetter(key)
+    sharedPropertyDefinition.get = shouldCache
+      ? createComputedGetter(key)
+      : userDef
     sharedPropertyDefinition.set = noop
     sharedPropertyDefinition.set = noop
   } else {
   } else {
     sharedPropertyDefinition.get = userDef.get
     sharedPropertyDefinition.get = userDef.get
-      ? userDef.cache !== false
+      ? shouldCache && userDef.cache !== false
         ? createComputedGetter(key)
         ? createComputedGetter(key)
         : userDef.get
         : userDef.get
       : noop
       : noop

+ 19 - 2
test/ssr/ssr-string.spec.js

@@ -909,13 +909,30 @@ describe('SSR: renderToString', () => {
   })
   })
 
 
   it('should escape static strings', done => {
   it('should escape static strings', done => {
-    renderVmWithOptions(({
+    renderVmWithOptions({
       template: `<div>&lt;foo&gt;</div>`
       template: `<div>&lt;foo&gt;</div>`
-    }), res => {
+    }, res => {
       expect(res).toBe(`<div data-server-rendered="true">&lt;foo&gt;</div>`)
       expect(res).toBe(`<div data-server-rendered="true">&lt;foo&gt;</div>`)
       done()
       done()
     })
     })
   })
   })
+
+  it('should not cache computed properties', done => {
+    renderVmWithOptions({
+      template: `<div>{{ foo }}</div>`,
+      data: () => ({ bar: 1 }),
+      computed: {
+        foo () { return this.bar + 1 }
+      },
+      created () {
+        this.foo // access
+        this.bar++ // trigger change
+      }
+    }, res => {
+      expect(res).toBe(`<div data-server-rendered="true">3</div>`)
+      done()
+    })
+  })
 })
 })
 
 
 function renderVmWithOptions (options, cb) {
 function renderVmWithOptions (options, cb) {