Skip to content

Commit

Permalink
feat: modify dispatch callback behaiver
Browse files Browse the repository at this point in the history
  • Loading branch information
imtaotao committed Nov 12, 2019
1 parent 4768fdc commit 8006b1f
Show file tree
Hide file tree
Showing 7 changed files with 83 additions and 13 deletions.
2 changes: 1 addition & 1 deletion docs/store.md
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ const store = createStore(() => {}, {})
store.dispatch('action', 'imtaotao')
```

`callback` 方法会在 `store.state` 改变后,所有依赖的组件更新后调用,因为**中间件中可能会处理异步行为**,所以这个 `callback` 的存在是必要的
`callback` 方法会在 `store.state` 改变后,所有依赖的组件更新后(包括视图)调用,因为**中间件中可能会处理异步行为**,所以这个 `callback` 的存在是必要的
```js
store.add('action', {
partialState: {
Expand Down
2 changes: 1 addition & 1 deletion docs/time-travel.md
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ go 方法将让当前的下标往前或者往后移动 n 个位置
```

### Tips
+ 没个组件的 `timeTravel` 将会是独立的,不会互相影响
+ 每个组件的 `timeTravel` 将会是独立的,不会互相影响
+ 当有新的 `dispatch` 导致当前组件用到的全局状态有更改时,`current` 会重新指向最末端
+ 如果当前当前 `current` 属性已经是 `history` 堆栈的最末端或者最开端,调用 `timeTravel` api 将不会起作用,因为已经没法往前后往后了,并且你将会得到一条警告信息
```js
Expand Down
6 changes: 1 addition & 5 deletions src/store.js
Original file line number Diff line number Diff line change
Expand Up @@ -118,11 +118,7 @@ export class Store {
}

// update components
updateComponents(this)

if (typeof callback === 'function') {
callback()
}
updateComponents(this, callback)
})
}

Expand Down
2 changes: 1 addition & 1 deletion src/time-travel.js
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ export default class TimeTravel {

const endPatchs = diff(component.data[GLOBALWORD], data, GLOBALWORD)
if (endPatchs.length > 0) {
applyPatchs(component, endPatchs, GLOBALWORD)
applyPatchs(component, endPatchs)
}

this.current += n
Expand Down
31 changes: 26 additions & 5 deletions src/update.js
Original file line number Diff line number Diff line change
@@ -1,27 +1,42 @@
import { diff } from './diff'
import { callHook } from './utils'

export function applyPatchs (component, patchs) {
export function applyPatchs (component, patchs, callback) {
const destObject = {}

for (let i = 0, len = patchs.length; i < len; i++) {
const { value, path } = patchs[i]
destObject[path] = value
}

component.setData(destObject)
component.setData(destObject, callback)
}

// update page and component
export function updateComponents (store) {
export function updateComponents (store, callback) {
let total = 0
const {
hooks,
GLOBALWORD,
depComponents,
} = store
const len = depComponents.length

if (len === 0) return
if (len === 0) {
if (typeof callback === 'function') {
callback()
}
return
}

// call `callback`, when all component views are rendered
const renderedCallback = () => {
if (++total === len) {
if (typeof callback === 'function') {
callback()
}
}
}

for (let i = 0; i < len; i++) {
const {
Expand All @@ -38,6 +53,7 @@ export function updateComponents (store) {
// the `willUpdate` function will optimize component
if (typeof willUpdate === 'function') {
if (willUpdate.call(store, component, newPartialState) === false) {
renderedCallback()
continue
}
}
Expand All @@ -50,11 +66,12 @@ export function updateComponents (store) {
// call global hooks
const params = [component, newPartialState, patchs, isPage]
if (callHook(hooks, 'willUpdate', params) === false) {
renderedCallback()
continue
}

// update component
applyPatchs(component, patchs, GLOBALWORD)
applyPatchs(component, patchs, renderedCallback)

if (typeof didUpdate === 'function') {
didUpdate.call(store, component, newPartialState, patchs)
Expand All @@ -66,7 +83,11 @@ export function updateComponents (store) {
if (component.timeTravel) {
component.timeTravel.push(patchs)
}
} else {
renderedCallback()
}
} else {
renderedCallback()
}
}
}
1 change: 1 addition & 0 deletions test/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
+ [x] 更新完毕的回调中可以增加新的 middleware
+ [x] dispatch 的时候能在中间件中再次调用 dispatch
+ [x] dispatch 后,组件更新完毕后调用回调
+ [x] dispatch 后,组件更新完毕后调用回调,包含视图也更新
+ [x] 组件的 data 能否正常,视图能否正常更新
+ [x] 多级组件,父子组件之间能否正常更新
+ [x] 使用中间件,模拟异步行为时,多级组件,父子组件之间能否正常更新
Expand Down
52 changes: 52 additions & 0 deletions test/script/dispatch.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -156,6 +156,58 @@ describe('dispatch', () => {
expect(store.state.a).toBeUndefined()
})

it('dispatch `callback` after the component and view is updated', done => {
const store = createStore()
store.add('testAction', {
partialState: {
a: 1,
b: 2,
},
setter: (state, payload) => ({ a: payload })
})
const oneId = simulate.load(Component({
template: '<div>{{ global.a }}</div>',
storeConfig: {
useState: () => ({
a: state => state.a,
}),
},
}))
const twoId = simulate.load(Component({
template: '<div>{{ global.b }}</div>',
storeConfig: {
useState: () => ({
b: state => state.b,
}),
},
}))
const threeId = simulate.load(Component({
template: '<div>{{ global.b }}</div>',
storeConfig: {
useState: () => ({
a: state => state.a,
}),
},
}))
const cmOne = simulate.render(oneId)
cmOne.attach(document.createElement('parent-wrapper'))
const cmTwo = simulate.render(twoId)
cmTwo.attach(document.createElement('parent-wrapper'))
const cmThree = simulate.render(threeId)
cmThree.attach(document.createElement('parent-wrapper'))
// if delete component global data
cmThree.data[store.GLOBALWORD] = null
expect(cmOne.dom.textContent).toBe('1')
expect(cmOne.data.global.a).toBe(1)
expect(store.state.a).toBe(1)
store.dispatch('testAction', 2, () => {
expect(cmOne.dom.textContent).toBe('2')
expect(cmOne.data.global.a).toBe(2)
expect(store.state.a).toBe(2)
done()
})
})

it('component data update', () => {
// need to recreate store
const store = createStore()
Expand Down

0 comments on commit 8006b1f

Please sign in to comment.