Skip to content

Commit c55a0a6

Browse files
committed
[weex] wip: experimenting with transition-group
1 parent 52008d6 commit c55a0a6

File tree

4 files changed

+160
-3
lines changed

4 files changed

+160
-3
lines changed
Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
1-
import Transition from 'web/runtime/components/transition'
1+
import Transition from './transition'
2+
import TransitionGroup from './transition-group'
23

34
export default {
4-
Transition
5+
Transition,
6+
TransitionGroup
57
}
Lines changed: 151 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,151 @@
1+
import { warn, extend } from 'core/util/index'
2+
import { transitionProps, extractTransitionData } from './transition'
3+
4+
const props = extend({
5+
tag: String,
6+
moveClass: String
7+
}, transitionProps)
8+
9+
delete props.mode
10+
11+
export default {
12+
props,
13+
14+
created () {
15+
const dom = this._requireWeexModule('dom')
16+
this.getPosition = el => new Promise((resolve, reject) => {
17+
dom.getComponentRect(el.ref, res => {
18+
if (!res.result) {
19+
reject(new Error(`failed to get rect for element: ${el.tag}`))
20+
} else {
21+
resolve(res.size)
22+
}
23+
})
24+
})
25+
26+
const animation = this._requireWeexModule('animation')
27+
this.animate = (el, options) => new Promise(resolve => {
28+
animation.transition(el.ref, options, resolve)
29+
})
30+
},
31+
32+
render (h) {
33+
const tag = this.tag || this.$vnode.data.tag || 'span'
34+
const map = Object.create(null)
35+
const prevChildren = this.prevChildren = this.children
36+
const rawChildren = this.$slots.default || []
37+
const children = this.children = []
38+
const transitionData = extractTransitionData(this)
39+
40+
for (let i = 0; i < rawChildren.length; i++) {
41+
const c = rawChildren[i]
42+
if (c.tag) {
43+
if (c.key != null && String(c.key).indexOf('__vlist') !== 0) {
44+
children.push(c)
45+
map[c.key] = c
46+
;(c.data || (c.data = {})).transition = transitionData
47+
} else if (process.env.NODE_ENV !== 'production') {
48+
const opts = c.componentOptions
49+
const name = opts
50+
? (opts.Ctor.options.name || opts.tag)
51+
: c.tag
52+
warn(`<transition-group> children must be keyed: <${name}>`)
53+
}
54+
}
55+
}
56+
57+
if (prevChildren) {
58+
const kept = []
59+
const removed = []
60+
const positionPromises = []
61+
prevChildren.forEach(c => {
62+
c.data.transition = transitionData
63+
positionPromises.push(this.getPosition(c.elm).then(pos => {
64+
c.data.pos = pos
65+
}))
66+
if (map[c.key]) {
67+
kept.push(c)
68+
} else {
69+
removed.push(c)
70+
}
71+
})
72+
this.kept = h(tag, null, kept)
73+
this.removed = removed
74+
this.pendingPositions = Promise.all(positionPromises)
75+
}
76+
77+
return h(tag, null, children)
78+
},
79+
80+
beforeUpdate () {
81+
// force removing pass
82+
this.__patch__(
83+
this._vnode,
84+
this.kept,
85+
false, // hydrating
86+
true // removeOnly (!important, avoids unnecessary moves)
87+
)
88+
this._vnode = this.kept
89+
},
90+
91+
updated () {
92+
const children = this.prevChildren
93+
const moveClass = this.moveClass || ((this.name || 'v') + '-move')
94+
const moveData = children.length && this.getMoveData(children[0].context, moveClass)
95+
if (!moveData) {
96+
return
97+
}
98+
99+
children.forEach(callPendingCbs)
100+
this.pendingPositions.then(() => Promise.all(children.map(c => {
101+
// record new position
102+
return this.getPosition(c.elm).then(pos => {
103+
c.data.newPos = pos
104+
})
105+
}))).then(() => Promise.all(children.map(c => {
106+
const oldPos = c.data.pos
107+
const newPos = c.data.newPos
108+
const dx = oldPos.left - newPos.left
109+
const dy = oldPos.top - newPos.top
110+
if (dx || dy) {
111+
c.data.moved = true
112+
return this.animate(c.elm, {
113+
styles: {
114+
transform: `translate(${dx}px,${dy}px)`
115+
}
116+
})
117+
}
118+
}))).then(() => {
119+
children.forEach(c => {
120+
if (c.data.moved) {
121+
this.animate(c.elm, {
122+
styles: {
123+
transform: ''
124+
},
125+
duration: moveData.duration || 0,
126+
delay: moveData.delay || 0,
127+
timingFunction: moveData.timingFunction || 'linear'
128+
})
129+
}
130+
})
131+
})
132+
},
133+
134+
methods: {
135+
getMoveData (context, moveClass) {
136+
const stylesheet = context.$options.style || {}
137+
return stylesheet['@TRANSITION'] && stylesheet['@TRANSITION'][moveClass]
138+
}
139+
}
140+
}
141+
142+
function callPendingCbs (c) {
143+
/* istanbul ignore if */
144+
if (c.elm._moveCb) {
145+
c.elm._moveCb()
146+
}
147+
/* istanbul ignore if */
148+
if (c.elm._enterCb) {
149+
c.elm._enterCb()
150+
}
151+
}
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
// reuse same transition component logic from web
2+
export * from 'web/runtime/components/transition'

src/platforms/weex/runtime/modules/transition.js

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import { warn } from 'core/util/debug'
12
import { extend, once, noop } from 'shared/util'
23
import { activeInstance } from 'core/instance/lifecycle'
34
import { resolveTransition } from 'web/runtime/transition-util'
@@ -233,11 +234,12 @@ function getEnterTargetState (el, stylesheet, startClass, endClass, activeClass,
233234
for (const key in startState) {
234235
targetState[key] = el.style[key]
235236
if (
237+
process.env.NODE_ENV !== 'production' &&
236238
targetState[key] == null &&
237239
(!activeState || activeState[key] == null) &&
238240
(!endState || endState[key] == null)
239241
) {
240-
console.log(
242+
warn(
241243
`transition property "${key}" is declared in enter starting class (.${startClass}), ` +
242244
`but not declared anywhere in enter ending class (.${endClass}), ` +
243245
`enter active cass (.${activeClass}) or the element's default styling. ` +

0 commit comments

Comments
 (0)