feat: multi-store injection supported

This commit is contained in:
dntzhang 2019-10-09 16:47:59 +08:00
parent 441286595c
commit 72c06186c3
3 changed files with 115 additions and 102 deletions

1
.gitignore vendored
View File

@ -12,6 +12,7 @@ package-lock.json
.idea/
vue
vue-ms
/packages/*/node_modules
/packages/*/yarn.lock
/packages/*/yarn-error.log

View File

@ -1,6 +1,3 @@
const OBJECTTYPE = '[object Object]'
const ARRAYTYPE = '[object Array]'
export function getUsing(data, paths) {
const obj = []
paths.forEach((path, index) => {
@ -43,71 +40,26 @@ export function getTargetByPath(origin, path) {
return current
}
export function getPath(obj) {
if (Object.prototype.toString.call(obj) === '[object Array]') {
const result = {}
obj.forEach(item => {
if (typeof item === 'string') {
result[item] = true
} else {
const tempPath = item[Object.keys(item)[0]]
if (typeof tempPath === 'string') {
result[tempPath] = true
} else if (typeof tempPath[0] === 'string') {
result[tempPath[0]] = true
} else {
tempPath[0].forEach(path => (result[path] = true))
}
}
})
return result
}
return getUpdatePath(obj)
}
export function getUpdatePath(data) {
export function getPath(obj, out, name) {
const result = {}
dataToPath(data, result)
obj.forEach(item => {
if (typeof item === 'string') {
result[item] = true
} else {
const tempPath = item[Object.keys(item)[0]]
if (typeof tempPath === 'string') {
result[tempPath] = true
} else if (typeof tempPath[0] === 'string') {
result[tempPath[0]] = true
} else {
tempPath[0].forEach(path => (result[path] = true))
}
}
})
out && (out[name] = result)
return result
}
function dataToPath(data, result) {
Object.keys(data).forEach(key => {
result[key] = true
const type = Object.prototype.toString.call(data[key])
if (type === OBJECTTYPE) {
_objToPath(data[key], key, result)
} else if (type === ARRAYTYPE) {
_arrayToPath(data[key], key, result)
}
})
}
function _objToPath(data, path, result) {
Object.keys(data).forEach(key => {
result[path + '.' + key] = true
delete result[path]
const type = Object.prototype.toString.call(data[key])
if (type === OBJECTTYPE) {
_objToPath(data[key], path + '.' + key, result)
} else if (type === ARRAYTYPE) {
_arrayToPath(data[key], path + '.' + key, result)
}
})
}
function _arrayToPath(data, path, result) {
data.forEach((item, index) => {
result[path + '[' + index + ']'] = true
delete result[path]
const type = Object.prototype.toString.call(item)
if (type === OBJECTTYPE) {
_objToPath(item, path + '[' + index + ']', result)
} else if (type === ARRAYTYPE) {
_arrayToPath(item, path + '[' + index + ']', result)
}
})
}
export function needUpdate(diffResult, updatePath) {
for (let keyA in diffResult) {

View File

@ -1,9 +1,8 @@
import { obaa } from './obaa'
import { getPath, needUpdate, fixPath } from './path'
const components = []
const updateSelfComponents = []
let store
let isMultiStore = false
export function $(options) {
const beforeCreate = options.beforeCreate
@ -14,60 +13,80 @@ export function $(options) {
if (options.store) {
store = options.store
obaa(store.data, (prop, val, old, path) => {
const patch = {}
patch[fixPath(path + '-' + prop)] = true
components.forEach(component => {
if (
component.__$updatePath_ &&
needUpdate(patch, component.__$updatePath_)
) {
recUpdate(component)
if (store.data) {
observe(store)
} else {
isMultiStore = true
for (let key in store) {
if (store[key].data) {
observe(store[key], key)
}
})
}
}
updateSelfComponents.forEach(component => {
if (
component.__$updateSelfPath_ &&
needUpdate(patch, component.__$updateSelfPath_)
) {
component.$forceUpdate()
}
})
})
}
options.beforeCreate = function() {
options.beforeCreate = function () {
this.$store = store
if (use) {
this.__$updatePath_ = getPath(use)
components.push(this)
}
if (useSelf) {
this.__$updateSelfPath_ = getPath(useSelf)
updateSelfComponents.push(this)
if (isMultiStore) {
if (use) {
let updatePath = {}
for (let storeName in use) {
getPath(use[storeName], updatePath, storeName)
store[storeName].components.push(this)
}
this.__$updatePath_ = updatePath
}
if (useSelf) {
let updateSelfPath = {}
for (let storeName in useSelf) {
getPath(useSelf[storeName], updateSelfPath, storeName)
store[storeName].updateSelfComponents.push(this)
}
this.__$updateSelfPath_ = updateSelfPath
}
} else {
if (use) {
this.__$updatePath_ = getPath(use)
store.components.push(this)
}
if (useSelf) {
this.__$updateSelfPath_ = getPath(useSelf)
store.updateSelfComponents.push(this)
}
}
beforeCreate && beforeCreate.apply(this, arguments)
}
options.destroyed = function() {
for (let i = 0, len = components.length; i < len; i++) {
if (components[i] === this) {
components.splice(i, 1)
break
options.destroyed = function () {
if (isMultiStore) {
for (let key in store) {
removeItem(this, store[key].components)
removeItem(this, store[key].updateSelfComponents)
}
} else {
removeItem(this, store.updateSelfComponents)
removeItem(this, store.components)
}
destroyed && destroyed.apply(this, arguments)
}
options.computed.state = function() {
options.computed.state = function () {
if (isMultiStore) {
let state = {}
Object.keys(store).forEach(k => {
state[k] = store[k].data
})
return state
}
return this.$store.data
}
options.computed.store = function() {
options.computed.store = function () {
return this.$store
}
@ -80,3 +99,44 @@ function recUpdate(root) {
recUpdate(child)
})
}
function observe(store, storeName) {
store.components = []
store.updateSelfComponents = []
obaa(store.data, (prop, val, old, path) => {
const patch = {}
patch[fixPath(path + '-' + prop)] = true
store.components.forEach(component => {
const p = component.__$updatePath_
if (storeName) {
if (p && p[storeName] && needUpdate(patch, p[storeName])) {
recUpdate(component)
}
} else if (p && needUpdate(patch, p)) {
recUpdate(component)
}
})
store.updateSelfComponents.forEach(component => {
const sp = component.__$updateSelfPath_
if (storeName) {
if (sp && sp[storeName] && needUpdate(patch, sp[storeName])) {
component.$forceUpdate()
}
} else if (sp && needUpdate(patch, sp)) {
component.$forceUpdate()
}
})
})
}
function removeItem(item, arr) {
for (let i = 0, len = arr.length; i < len; i++) {
if (arr[i] === item) {
arr.splice(i, 1)
break
}
}
}