Fix adding extra deps
This commit is contained in:
@@ -79,7 +79,8 @@
|
|||||||
*/
|
*/
|
||||||
export let initialPageIndex = 0
|
export let initialPageIndex = 0
|
||||||
$: {
|
$: {
|
||||||
data.initialPageIndexInit = initialPageIndex
|
console.log('initialPageIndex', initialPageIndex)
|
||||||
|
data.initialPageIndex = initialPageIndex
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -217,7 +218,6 @@
|
|||||||
|
|
||||||
// call after adding clones
|
// call after adding clones
|
||||||
data.particlesCount = particlesContainer.children.length
|
data.particlesCount = particlesContainer.children.length
|
||||||
data.initialPageIndex = initialPageIndex
|
|
||||||
|
|
||||||
pageWindowElementResizeObserver.observe(pageWindowElement);
|
pageWindowElementResizeObserver.observe(pageWindowElement);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import simplyReactive from 'simply-reactive'
|
import simplyReactive from '../../../../simply-reactive/main'
|
||||||
|
|
||||||
import { NEXT, PREV } from '../../direction'
|
import { NEXT, PREV } from '../../direction'
|
||||||
import {
|
import {
|
||||||
@@ -22,257 +22,233 @@ function createCarousel(onChange) {
|
|||||||
|
|
||||||
const [data, methods, service] = simplyReactive(
|
const [data, methods, service] = simplyReactive(
|
||||||
{
|
{
|
||||||
particlesCountWithoutClones: 0,
|
data: {
|
||||||
particlesToShow: 1, // normalized
|
particlesCountWithoutClones: 0,
|
||||||
particlesToShowInit: 1, // initial value
|
particlesToShow: 1, // normalized
|
||||||
particlesToScroll: 1, // normalized
|
particlesToShowInit: 1, // initial value
|
||||||
particlesToScrollInit: 1, // initial value
|
particlesToScroll: 1, // normalized
|
||||||
initialPageIndex: 1, // normalized
|
particlesToScrollInit: 1, // initial value
|
||||||
initialPageIndexInit: 1, // initial value
|
initialPageIndex: 0,
|
||||||
particlesCount: 1,
|
particlesCount: 1,
|
||||||
currentParticleIndex: 1,
|
currentParticleIndex: 1,
|
||||||
infinite: false,
|
infinite: false,
|
||||||
autoplayDuration: 1000,
|
autoplayDuration: 1000,
|
||||||
clonesCountHead: 0,
|
clonesCountHead: 0,
|
||||||
clonesCountTail: 0,
|
clonesCountTail: 0,
|
||||||
clonesCountTotal: 0,
|
clonesCountTotal: 0,
|
||||||
partialPageSize: 1,
|
partialPageSize: 1,
|
||||||
currentPageIndex: 1,
|
currentPageIndex: 1,
|
||||||
pagesCount: 1,
|
pagesCount: 1,
|
||||||
pauseOnFocus: false,
|
pauseOnFocus: false,
|
||||||
focused: false,
|
focused: false,
|
||||||
autoplay: false,
|
autoplay: false,
|
||||||
autoplayDirection: 'next',
|
autoplayDirection: 'next',
|
||||||
disabled: false, // Disable page change while animation is in progress
|
disabled: false, // Disable page change while animation is in progress
|
||||||
durationMsInit: 1000,
|
durationMsInit: 1000,
|
||||||
durationMs: 1000,
|
durationMs: 1000,
|
||||||
offset: 0,
|
offset: 0,
|
||||||
particleWidth: 0,
|
particleWidth: 0,
|
||||||
loaded: [],
|
loaded: [],
|
||||||
},
|
|
||||||
{
|
|
||||||
setCurrentPageIndex: (data) => {
|
|
||||||
data.currentPageIndex = getCurrentPageIndexByCurrentParticleIndex({
|
|
||||||
currentParticleIndex: data.currentParticleIndex,
|
|
||||||
particlesCount: data.particlesCount,
|
|
||||||
clonesCountHead: data.clonesCountHead,
|
|
||||||
clonesCountTotal: data.clonesCountTotal,
|
|
||||||
infinite: data.initialPageIndex,
|
|
||||||
particlesToScroll: data.particlesToScroll,
|
|
||||||
})
|
|
||||||
},
|
},
|
||||||
setPartialPageSize: (data) => {
|
watch: {
|
||||||
data.partialPageSize = getPartialPageSize({
|
setLoaded({ data }) {
|
||||||
particlesToScroll: data.particlesToScroll,
|
data.loaded = getAdjacentIndexes({
|
||||||
particlesToShow: data.particlesToShow,
|
infinite: data.infinite,
|
||||||
particlesCountWithoutClones: data.particlesCountWithoutClones,
|
pageIndex: data.currentPageIndex,
|
||||||
})
|
pagesCount: data.pagesCount,
|
||||||
},
|
particlesCount: data.particlesCountWithoutClones,
|
||||||
setClonesCount: (data) => {
|
particlesToShow: data.particlesToShow,
|
||||||
const { head, tail } = getClonesCount({
|
particlesToScroll: data.particlesToScroll,
|
||||||
infinite: data.infinite,
|
}).particleIndexes
|
||||||
particlesToShow: data.particlesToShow,
|
},
|
||||||
partialPageSize: data.partialPageSize,
|
setCurrentPageIndex({ data }) {
|
||||||
})
|
data.currentPageIndex = getCurrentPageIndexByCurrentParticleIndex({
|
||||||
|
currentParticleIndex: data.currentParticleIndex,
|
||||||
data.clonesCountHead = head
|
particlesCount: data.particlesCount,
|
||||||
data.clonesCountTail = tail
|
clonesCountHead: data.clonesCountHead,
|
||||||
data.clonesCountTotal = head + tail
|
clonesCountTotal: data.clonesCountTotal,
|
||||||
},
|
infinite: data.infinite,
|
||||||
setPagesCount: (data) => {
|
particlesToScroll: data.particlesToScroll,
|
||||||
data.pagesCount = getPagesCountByParticlesCount({
|
})
|
||||||
infinite: data.infinite,
|
},
|
||||||
particlesCountWithoutClones: data.particlesCountWithoutClones,
|
setPartialPageSize({ data }) {
|
||||||
particlesToScroll: data.particlesToScroll,
|
data.partialPageSize = getPartialPageSize({
|
||||||
})
|
particlesToScroll: data.particlesToScroll,
|
||||||
},
|
particlesToShow: data.particlesToShow,
|
||||||
setProgressManagerAutoplayDuration: (data) => {
|
particlesCountWithoutClones: data.particlesCountWithoutClones,
|
||||||
progressManager.setAutoplayDuration(data.autoplayDuration)
|
})
|
||||||
},
|
},
|
||||||
toggleProgressManager: ({ pauseOnFocus, focused }) => {
|
setClonesCount({ data }) {
|
||||||
if (pauseOnFocus) {
|
const { head, tail } = getClonesCount({
|
||||||
if (focused) {
|
infinite: data.infinite,
|
||||||
progressManager.pause()
|
particlesToShow: data.particlesToShow,
|
||||||
} else {
|
partialPageSize: data.partialPageSize,
|
||||||
progressManager.resume()
|
})
|
||||||
|
data.clonesCountHead = head
|
||||||
|
data.clonesCountTail = tail
|
||||||
|
data.clonesCountTotal = head + tail
|
||||||
|
},
|
||||||
|
setProgressManagerAutoplayDuration({ data }) {
|
||||||
|
progressManager.setAutoplayDuration(data.autoplayDuration)
|
||||||
|
},
|
||||||
|
toggleProgressManager({ data: { pauseOnFocus, focused } }) {
|
||||||
|
// as focused is in if block, it will not be put to deps, read them in data: {}
|
||||||
|
if (pauseOnFocus) {
|
||||||
|
if (focused) {
|
||||||
|
progressManager.pause()
|
||||||
|
} else {
|
||||||
|
progressManager.resume()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
},
|
|
||||||
initDuration: (data) => {
|
|
||||||
data.durationMs = data.durationMsInit
|
|
||||||
},
|
|
||||||
applyAutoplay: (data, { _applyAutoplayIfNeeded }) => {
|
|
||||||
// prevent _applyAutoplayIfNeeded to be called with watcher
|
|
||||||
// to prevent its data added to deps
|
|
||||||
data.autoplay && _applyAutoplayIfNeeded(data.autoplay)
|
|
||||||
},
|
|
||||||
setParticlesToShow(data) {
|
|
||||||
data.particlesToShow = getValueInRange(
|
|
||||||
1,
|
|
||||||
data.particlesToShowInit,
|
|
||||||
data.particlesCountWithoutClones
|
|
||||||
)
|
|
||||||
},
|
|
||||||
setParticlesToScroll(data) {
|
|
||||||
data.particlesToScroll = getValueInRange(
|
|
||||||
1,
|
|
||||||
data.particlesToScrollInit,
|
|
||||||
data.particlesCountWithoutClones
|
|
||||||
)
|
|
||||||
},
|
|
||||||
setInitialPageIndex(data) {
|
|
||||||
data.initialPageIndex = getValueInRange(
|
|
||||||
1,
|
|
||||||
data.initialPageIndexInit,
|
|
||||||
data.pagesCount
|
|
||||||
)
|
|
||||||
},
|
|
||||||
setLoaded(data) {
|
|
||||||
data.loaded = getAdjacentIndexes({
|
|
||||||
infinite: data.infinite,
|
|
||||||
pageIndex: data.currentPageIndex,
|
|
||||||
pagesCount: data.pagesCount,
|
|
||||||
particlesCount: data.particlesCountWithoutClones,
|
|
||||||
particlesToShow: data.particlesToShow,
|
|
||||||
particlesToScroll: data.particlesToScroll,
|
|
||||||
}).particleIndexes
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
_prev: (data) => {
|
|
||||||
const newCurrentParticleIndex = getParticleIndexByPageIndex({
|
|
||||||
infinite: data.infinite,
|
|
||||||
pageIndex: data.currentPageIndex - 1,
|
|
||||||
clonesCountHead: data.clonesCountHead,
|
|
||||||
clonesCountTail: data.clonesCountTail,
|
|
||||||
particlesToScroll: data.particlesToScroll,
|
|
||||||
particlesCount: data.particlesCount,
|
|
||||||
particlesToShow: data.particlesToShow,
|
|
||||||
})
|
|
||||||
data.currentParticleIndex = newCurrentParticleIndex
|
|
||||||
},
|
|
||||||
_next: (data) => {
|
|
||||||
const newCurrentParticleIndex = getParticleIndexByPageIndex({
|
|
||||||
infinite: data.infinite,
|
|
||||||
pageIndex: data.currentPageIndex + 1,
|
|
||||||
clonesCountHead: data.clonesCountHead,
|
|
||||||
clonesCountTail: data.clonesCountTail,
|
|
||||||
particlesToScroll: data.particlesToScroll,
|
|
||||||
particlesCount: data.particlesCount,
|
|
||||||
particlesToShow: data.particlesToShow,
|
|
||||||
})
|
|
||||||
data.currentParticleIndex = newCurrentParticleIndex
|
|
||||||
},
|
|
||||||
_moveToParticle: (data, _, particleIndex) => {
|
|
||||||
const newCurrentParticleIndex = getValueInRange(
|
|
||||||
0,
|
|
||||||
particleIndex,
|
|
||||||
data.particlesCount - 1
|
|
||||||
)
|
|
||||||
data.currentParticleIndex = newCurrentParticleIndex
|
|
||||||
},
|
|
||||||
toggleFocused: (data) => {
|
|
||||||
data.focused = !data.focused
|
|
||||||
},
|
|
||||||
async _applyAutoplayIfNeeded(
|
|
||||||
{
|
|
||||||
infinite,
|
|
||||||
autoplayDirection,
|
|
||||||
currentParticleIndex,
|
|
||||||
particlesCount,
|
|
||||||
autoplay,
|
|
||||||
},
|
},
|
||||||
{ showNextPage, showPrevPage }
|
initDuration({ data }) {
|
||||||
) {
|
data.durationMs = data.durationMsInit
|
||||||
// prevent progress change if not infinite for first and last page
|
|
||||||
if (
|
|
||||||
!infinite &&
|
|
||||||
((autoplayDirection === NEXT &&
|
|
||||||
currentParticleIndex === particlesCount - 1) ||
|
|
||||||
(autoplayDirection === PREV && currentParticleIndex === 0))
|
|
||||||
) {
|
|
||||||
progressManager.reset()
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
if (autoplay) {
|
|
||||||
const onFinish = () =>
|
|
||||||
switcher({
|
|
||||||
[NEXT]: async () => showNextPage(),
|
|
||||||
[PREV]: async () => showPrevPage(),
|
|
||||||
})(autoplayDirection)
|
|
||||||
|
|
||||||
await progressManager.start(onFinish)
|
|
||||||
}
|
|
||||||
},
|
|
||||||
// makes delayed jump to 1st or last element
|
|
||||||
_jumpIfNeeded: async (
|
|
||||||
{
|
|
||||||
infinite,
|
|
||||||
currentParticleIndex,
|
|
||||||
particlesCount,
|
|
||||||
clonesCountTotal,
|
|
||||||
clonesCountTail,
|
|
||||||
clonesCountHead,
|
|
||||||
},
|
},
|
||||||
{ showParticle }
|
applyAutoplay({ data, methods: { _applyAutoplayIfNeeded } }) {
|
||||||
) => {
|
// prevent _applyAutoplayIfNeeded to be called with watcher
|
||||||
let jumped = false
|
// to prevent its data added to deps
|
||||||
if (infinite) {
|
data.autoplay && _applyAutoplayIfNeeded(data.autoplay)
|
||||||
if (currentParticleIndex === 0) {
|
},
|
||||||
await showParticle(particlesCount - clonesCountTotal, {
|
setParticlesToShow({ data }) {
|
||||||
animated: false,
|
data.particlesToShow = getValueInRange(
|
||||||
})
|
1,
|
||||||
jumped = true
|
data.particlesToShowInit,
|
||||||
} else if (
|
data.particlesCountWithoutClones
|
||||||
currentParticleIndex ===
|
)
|
||||||
particlesCount - clonesCountTail
|
},
|
||||||
|
setPagesCount({ data }) {
|
||||||
|
data.pagesCount = getPagesCountByParticlesCount({
|
||||||
|
infinite: data.infinite,
|
||||||
|
particlesCountWithoutClones: data.particlesCountWithoutClones,
|
||||||
|
particlesToScroll: data.particlesToScroll,
|
||||||
|
})
|
||||||
|
},
|
||||||
|
setParticlesToScroll({ data }) {
|
||||||
|
data.particlesToScroll = getValueInRange(
|
||||||
|
1,
|
||||||
|
data.particlesToScrollInit,
|
||||||
|
data.particlesCountWithoutClones
|
||||||
|
)
|
||||||
|
},
|
||||||
|
setInitialPageIndex({ data, methods: { showPage } }) {
|
||||||
|
const ind = getValueInRange(0, data.initialPageIndex, data.pagesCount)
|
||||||
|
console.log('ind', data.initialPageIndex, ind)
|
||||||
|
showPage(5, {
|
||||||
|
animated: false,
|
||||||
|
})
|
||||||
|
},
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
_prev({ data }) {
|
||||||
|
const newCurrentParticleIndex = getParticleIndexByPageIndex({
|
||||||
|
infinite: data.infinite,
|
||||||
|
pageIndex: data.currentPageIndex - 1,
|
||||||
|
clonesCountHead: data.clonesCountHead,
|
||||||
|
clonesCountTail: data.clonesCountTail,
|
||||||
|
particlesToScroll: data.particlesToScroll,
|
||||||
|
particlesCount: data.particlesCount,
|
||||||
|
particlesToShow: data.particlesToShow,
|
||||||
|
})
|
||||||
|
data.currentParticleIndex = newCurrentParticleIndex
|
||||||
|
},
|
||||||
|
_next({ data }) {
|
||||||
|
const newCurrentParticleIndex = getParticleIndexByPageIndex({
|
||||||
|
infinite: data.infinite,
|
||||||
|
pageIndex: data.currentPageIndex + 1,
|
||||||
|
clonesCountHead: data.clonesCountHead,
|
||||||
|
clonesCountTail: data.clonesCountTail,
|
||||||
|
particlesToScroll: data.particlesToScroll,
|
||||||
|
particlesCount: data.particlesCount,
|
||||||
|
particlesToShow: data.particlesToShow,
|
||||||
|
})
|
||||||
|
data.currentParticleIndex = newCurrentParticleIndex
|
||||||
|
},
|
||||||
|
_moveToParticle({ data }, particleIndex) {
|
||||||
|
const newCurrentParticleIndex = getValueInRange(
|
||||||
|
0,
|
||||||
|
particleIndex,
|
||||||
|
data.particlesCount - 1
|
||||||
|
)
|
||||||
|
data.currentParticleIndex = newCurrentParticleIndex
|
||||||
|
},
|
||||||
|
toggleFocused({ data }) {
|
||||||
|
data.focused = !data.focused
|
||||||
|
},
|
||||||
|
async _applyAutoplayIfNeeded({ data, methods }) {
|
||||||
|
// prevent progress change if not infinite for first and last page
|
||||||
|
if (
|
||||||
|
!data.infinite &&
|
||||||
|
((data.autoplayDirection === NEXT &&
|
||||||
|
data.currentParticleIndex === data.particlesCount - 1) ||
|
||||||
|
(data.autoplayDirection === PREV &&
|
||||||
|
data.currentParticleIndex === 0))
|
||||||
) {
|
) {
|
||||||
await showParticle(clonesCountHead, {
|
progressManager.reset()
|
||||||
animated: false,
|
return
|
||||||
})
|
|
||||||
jumped = true
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
return jumped
|
|
||||||
},
|
|
||||||
|
|
||||||
changePage: async (
|
if (data.autoplay) {
|
||||||
data,
|
const onFinish = () =>
|
||||||
{ offsetPage, _applyAutoplayIfNeeded, _jumpIfNeeded },
|
switcher({
|
||||||
updateStoreFn,
|
[NEXT]: async () => methods.showNextPage(),
|
||||||
options
|
[PREV]: async () => methods.showPrevPage(),
|
||||||
) => {
|
})(data.autoplayDirection)
|
||||||
progressManager.reset()
|
|
||||||
if (data.disabled) return
|
|
||||||
data.disabled = true
|
|
||||||
|
|
||||||
updateStoreFn()
|
await progressManager.start(onFinish)
|
||||||
await offsetPage({ animated: get(options, 'animated', true) })
|
}
|
||||||
data.disabled = false
|
},
|
||||||
|
// makes delayed jump to 1st or last element
|
||||||
|
async _jumpIfNeeded({ data, methods }) {
|
||||||
|
let jumped = false
|
||||||
|
if (data.infinite) {
|
||||||
|
if (data.currentParticleIndex === 0) {
|
||||||
|
await methods.showParticle(
|
||||||
|
data.particlesCount - data.clonesCountTotal,
|
||||||
|
{
|
||||||
|
animated: false,
|
||||||
|
}
|
||||||
|
)
|
||||||
|
jumped = true
|
||||||
|
} else if (
|
||||||
|
data.currentParticleIndex ===
|
||||||
|
data.particlesCount - data.clonesCountTail
|
||||||
|
) {
|
||||||
|
await methods.showParticle(data.clonesCountHead, {
|
||||||
|
animated: false,
|
||||||
|
})
|
||||||
|
jumped = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return jumped
|
||||||
|
},
|
||||||
|
async changePage({ data, methods }, updateStoreFn, options) {
|
||||||
|
progressManager.reset()
|
||||||
|
if (data.disabled) return
|
||||||
|
data.disabled = true
|
||||||
|
|
||||||
const jumped = await _jumpIfNeeded()
|
updateStoreFn()
|
||||||
!jumped && _applyAutoplayIfNeeded() // no need to wait it finishes
|
await methods.offsetPage({ animated: get(options, 'animated', true) })
|
||||||
},
|
data.disabled = false
|
||||||
showNextPage: async ({ disabled }, { changePage, _next }, options) => {
|
|
||||||
if (disabled) return
|
const jumped = await methods._jumpIfNeeded()
|
||||||
await changePage(_next, options)
|
!jumped && methods._applyAutoplayIfNeeded() // no need to wait it finishes
|
||||||
},
|
},
|
||||||
showPrevPage: async ({ disabled }, { changePage, _prev }, options) => {
|
async showNextPage({ data, methods }, options) {
|
||||||
if (disabled) return
|
if (data.disabled) return
|
||||||
await changePage(_prev, options)
|
await methods.changePage(methods._next, options)
|
||||||
},
|
},
|
||||||
showParticle: async (
|
async showPrevPage({ data, methods }, options) {
|
||||||
_,
|
if (data.disabled) return
|
||||||
{ changePage, _moveToParticle },
|
await methods.changePage(methods._prev, options)
|
||||||
particleIndex,
|
},
|
||||||
options
|
async showParticle({ methods }, particleIndex, options) {
|
||||||
) => {
|
await methods.changePage(
|
||||||
await changePage(() => _moveToParticle(particleIndex), options)
|
() => methods._moveToParticle(particleIndex),
|
||||||
},
|
options
|
||||||
showPage: async (data, { showParticle }, pageIndex, options) => {
|
)
|
||||||
await showParticle(
|
},
|
||||||
getParticleIndexByPageIndex({
|
async showPage({ data, methods }, pageIndex, options) {
|
||||||
|
const ind = getParticleIndexByPageIndex({
|
||||||
infinite: data.infinite,
|
infinite: data.infinite,
|
||||||
pageIndex,
|
pageIndex,
|
||||||
clonesCountHead: data.clonesCountHead,
|
clonesCountHead: data.clonesCountHead,
|
||||||
@@ -280,23 +256,26 @@ function createCarousel(onChange) {
|
|||||||
particlesToScroll: data.particlesToScroll,
|
particlesToScroll: data.particlesToScroll,
|
||||||
particlesCount: data.particlesCount,
|
particlesCount: data.particlesCount,
|
||||||
particlesToShow: data.particlesToShow,
|
particlesToShow: data.particlesToShow,
|
||||||
}),
|
})
|
||||||
options
|
console.log('ParticleIndex', ind)
|
||||||
)
|
await methods.showParticle(ind, options)
|
||||||
},
|
},
|
||||||
offsetPage(data, _, options) {
|
offsetPage({ data }, options) {
|
||||||
const animated = get(options, 'animated', true)
|
const animated = get(options, 'animated', true)
|
||||||
return new Promise((resolve) => {
|
return new Promise((resolve) => {
|
||||||
// durationMs is an offset animation time
|
// durationMs is an offset animation time
|
||||||
data.durationMs = animated ? data.durationMsInit : 0
|
data.durationMs = animated ? data.durationMsInit : 0
|
||||||
data.offset = -data.currentParticleIndex * data.particleWidth
|
data.offset = -data.currentParticleIndex * data.particleWidth
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
resolve()
|
resolve()
|
||||||
}, data.durationMs)
|
}, data.durationMs)
|
||||||
})
|
})
|
||||||
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
onChange
|
{
|
||||||
|
onChange,
|
||||||
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
return [{ data, progressManager }, methods, service]
|
return [{ data, progressManager }, methods, service]
|
||||||
|
|||||||
@@ -1,111 +0,0 @@
|
|||||||
// Code that has to run when a
|
|
||||||
// reactive property changes it's value.
|
|
||||||
|
|
||||||
const objectsAreSame = (x, y) => {
|
|
||||||
// return false
|
|
||||||
let _objectsAreSame = true
|
|
||||||
for (let propertyName in x) {
|
|
||||||
if (Number.isNaN(x[propertyName]) || Number.isNaN(y[propertyName])) {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
if (x[propertyName] !== y[propertyName]) {
|
|
||||||
_objectsAreSame = false
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return _objectsAreSame
|
|
||||||
}
|
|
||||||
|
|
||||||
const getObject = (oldData, newData) => {
|
|
||||||
const newDeps = {}
|
|
||||||
|
|
||||||
Object.entries(oldData).forEach(([key, value]) => {
|
|
||||||
// console.log('oldData', key, value)
|
|
||||||
newDeps[key] = newData[key]
|
|
||||||
})
|
|
||||||
// console.log('isDiff', oldData, newDeps)
|
|
||||||
|
|
||||||
return newDeps
|
|
||||||
}
|
|
||||||
|
|
||||||
const useSubscription = () => {
|
|
||||||
const subscribers = {}
|
|
||||||
|
|
||||||
const memoDependency = (target, dep) => {
|
|
||||||
const { watcherName, fn } = target
|
|
||||||
const { key, value } = dep
|
|
||||||
|
|
||||||
if (!subscribers[watcherName]) {
|
|
||||||
subscribers[watcherName] = {
|
|
||||||
deps: {},
|
|
||||||
fn,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
subscribers[watcherName].deps[key] = value
|
|
||||||
}
|
|
||||||
|
|
||||||
return {
|
|
||||||
subscribe: (target, dep) => {
|
|
||||||
if (target) {
|
|
||||||
memoDependency(target, dep)
|
|
||||||
}
|
|
||||||
},
|
|
||||||
notify: (data) => {
|
|
||||||
Object.entries(subscribers).forEach(([watcherName, { deps }]) => {
|
|
||||||
const newDeps = getObject(deps, data)
|
|
||||||
if (!objectsAreSame(deps, newDeps)) {
|
|
||||||
subscribers[watcherName].deps = newDeps
|
|
||||||
subscribers[watcherName].fn()
|
|
||||||
}
|
|
||||||
})
|
|
||||||
},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const useWatcher = () => {
|
|
||||||
let target = null
|
|
||||||
|
|
||||||
return {
|
|
||||||
watch: (watcherName, fn) => {
|
|
||||||
target = {
|
|
||||||
watcherName,
|
|
||||||
fn,
|
|
||||||
}
|
|
||||||
target.fn()
|
|
||||||
target = null
|
|
||||||
},
|
|
||||||
getTarget: () => {
|
|
||||||
return target
|
|
||||||
},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export const reactive = (data, watchers, methods, onChange) => {
|
|
||||||
const { subscribe, notify } = useSubscription()
|
|
||||||
const { watch, getTarget } = useWatcher()
|
|
||||||
|
|
||||||
const _data = new Proxy(data, {
|
|
||||||
get(target, key) {
|
|
||||||
subscribe(getTarget(), { key, value: target[key] })
|
|
||||||
return Reflect.get(...arguments)
|
|
||||||
},
|
|
||||||
set(_, key, value) {
|
|
||||||
Reflect.set(...arguments)
|
|
||||||
onChange && onChange(key, value)
|
|
||||||
notify(_data)
|
|
||||||
return true
|
|
||||||
},
|
|
||||||
})
|
|
||||||
|
|
||||||
Object.entries(watchers).forEach(([watcherName, watcher]) => {
|
|
||||||
watch(watcherName, () => watcher(_data))
|
|
||||||
})
|
|
||||||
|
|
||||||
const _methods = {}
|
|
||||||
Object.entries(methods).forEach(([methodName, method]) => {
|
|
||||||
_methods[methodName] = (...args) => method(_data, _methods, ...args)
|
|
||||||
})
|
|
||||||
|
|
||||||
return [_data, _methods]
|
|
||||||
}
|
|
||||||
Reference in New Issue
Block a user