diff options
Diffstat (limited to 'node_modules/vue/src/platforms/weex/runtime')
17 files changed, 1121 insertions, 0 deletions
diff --git a/node_modules/vue/src/platforms/weex/runtime/components/index.js b/node_modules/vue/src/platforms/weex/runtime/components/index.js new file mode 100644 index 00000000..449db1ad --- /dev/null +++ b/node_modules/vue/src/platforms/weex/runtime/components/index.js @@ -0,0 +1,9 @@ +import Richtext from './richtext' +import Transition from './transition' +import TransitionGroup from './transition-group' + +export default { + Richtext, + Transition, + TransitionGroup +} diff --git a/node_modules/vue/src/platforms/weex/runtime/components/richtext.js b/node_modules/vue/src/platforms/weex/runtime/components/richtext.js new file mode 100644 index 00000000..a9164c7a --- /dev/null +++ b/node_modules/vue/src/platforms/weex/runtime/components/richtext.js @@ -0,0 +1,82 @@ +/* @flow */ + +function getVNodeType (vnode: VNode): string { + if (!vnode.tag) { + return '' + } + return vnode.tag.replace(/vue\-component\-(\d+\-)?/, '') +} + +function isSimpleSpan (vnode: VNode): boolean { + return vnode.children && + vnode.children.length === 1 && + !vnode.children[0].tag +} + +function parseStyle (vnode: VNode): Object | void { + if (!vnode || !vnode.data) { + return + } + const { staticStyle, staticClass } = vnode.data + if (vnode.data.style || vnode.data.class || staticStyle || staticClass) { + const styles = Object.assign({}, staticStyle, vnode.data.style) + const cssMap = vnode.context.$options.style || {} + const classList = [].concat(staticClass, vnode.data.class) + classList.forEach(name => { + if (name && cssMap[name]) { + Object.assign(styles, cssMap[name]) + } + }) + return styles + } +} + +function convertVNodeChildren (children: Array<VNode>): Array<VNode> | void { + if (!children.length) { + return + } + + return children.map(vnode => { + const type: string = getVNodeType(vnode) + const props: Object = { type } + + // convert raw text node + if (!type) { + props.type = 'span' + props.attr = { + value: (vnode.text || '').trim() + } + } else { + props.style = parseStyle(vnode) + if (vnode.data) { + props.attr = vnode.data.attrs + if (vnode.data.on) { + props.events = vnode.data.on + } + } + if (type === 'span' && isSimpleSpan(vnode)) { + props.attr = props.attr || {} + props.attr.value = vnode.children[0].text.trim() + return props + } + } + + if (vnode.children && vnode.children.length) { + props.children = convertVNodeChildren(vnode.children) + } + + return props + }) +} + +export default { + name: 'richtext', + render (h: Function) { + return h('weex:richtext', { + on: this._events, + attrs: { + value: convertVNodeChildren(this.$options._renderChildren || []) + } + }) + } +} diff --git a/node_modules/vue/src/platforms/weex/runtime/components/transition-group.js b/node_modules/vue/src/platforms/weex/runtime/components/transition-group.js new file mode 100644 index 00000000..4a65965f --- /dev/null +++ b/node_modules/vue/src/platforms/weex/runtime/components/transition-group.js @@ -0,0 +1,148 @@ +import { warn, extend } from 'core/util/index' +import { transitionProps, extractTransitionData } from './transition' + +const props = extend({ + tag: String, + moveClass: String +}, transitionProps) + +delete props.mode + +export default { + props, + + created () { + const dom = this.$requireWeexModule('dom') + this.getPosition = el => new Promise((resolve, reject) => { + dom.getComponentRect(el.ref, res => { + if (!res.result) { + reject(new Error(`failed to get rect for element: ${el.tag}`)) + } else { + resolve(res.size) + } + }) + }) + + const animation = this.$requireWeexModule('animation') + this.animate = (el, options) => new Promise(resolve => { + animation.transition(el.ref, options, resolve) + }) + }, + + render (h) { + const tag = this.tag || this.$vnode.data.tag || 'span' + const map = Object.create(null) + const prevChildren = this.prevChildren = this.children + const rawChildren = this.$slots.default || [] + const children = this.children = [] + const transitionData = extractTransitionData(this) + + for (let i = 0; i < rawChildren.length; i++) { + const c = rawChildren[i] + if (c.tag) { + if (c.key != null && String(c.key).indexOf('__vlist') !== 0) { + children.push(c) + map[c.key] = c + ;(c.data || (c.data = {})).transition = transitionData + } else if (process.env.NODE_ENV !== 'production') { + const opts = c.componentOptions + const name = opts + ? (opts.Ctor.options.name || opts.tag) + : c.tag + warn(`<transition-group> children must be keyed: <${name}>`) + } + } + } + + if (prevChildren) { + const kept = [] + const removed = [] + prevChildren.forEach(c => { + c.data.transition = transitionData + + // TODO: record before patch positions + + if (map[c.key]) { + kept.push(c) + } else { + removed.push(c) + } + }) + this.kept = h(tag, null, kept) + this.removed = removed + } + + return h(tag, null, children) + }, + + beforeUpdate () { + // force removing pass + this.__patch__( + this._vnode, + this.kept, + false, // hydrating + true // removeOnly (!important, avoids unnecessary moves) + ) + this._vnode = this.kept + }, + + updated () { + const children = this.prevChildren + const moveClass = this.moveClass || ((this.name || 'v') + '-move') + const moveData = children.length && this.getMoveData(children[0].context, moveClass) + if (!moveData) { + return + } + + // TODO: finish implementing move animations once + // we have access to sync getComponentRect() + + // children.forEach(callPendingCbs) + + // Promise.all(children.map(c => { + // const oldPos = c.data.pos + // const newPos = c.data.newPos + // const dx = oldPos.left - newPos.left + // const dy = oldPos.top - newPos.top + // if (dx || dy) { + // c.data.moved = true + // return this.animate(c.elm, { + // styles: { + // transform: `translate(${dx}px,${dy}px)` + // } + // }) + // } + // })).then(() => { + // children.forEach(c => { + // if (c.data.moved) { + // this.animate(c.elm, { + // styles: { + // transform: '' + // }, + // duration: moveData.duration || 0, + // delay: moveData.delay || 0, + // timingFunction: moveData.timingFunction || 'linear' + // }) + // } + // }) + // }) + }, + + methods: { + getMoveData (context, moveClass) { + const stylesheet = context.$options.style || {} + return stylesheet['@TRANSITION'] && stylesheet['@TRANSITION'][moveClass] + } + } +} + +// function callPendingCbs (c) { +// /* istanbul ignore if */ +// if (c.elm._moveCb) { +// c.elm._moveCb() +// } +// /* istanbul ignore if */ +// if (c.elm._enterCb) { +// c.elm._enterCb() +// } +// } diff --git a/node_modules/vue/src/platforms/weex/runtime/components/transition.js b/node_modules/vue/src/platforms/weex/runtime/components/transition.js new file mode 100644 index 00000000..20ba632d --- /dev/null +++ b/node_modules/vue/src/platforms/weex/runtime/components/transition.js @@ -0,0 +1,9 @@ +// reuse same transition component logic from web +export { + transitionProps, + extractTransitionData +} from 'web/runtime/components/transition' + +import Transition from 'web/runtime/components/transition' + +export default Transition diff --git a/node_modules/vue/src/platforms/weex/runtime/directives/index.js b/node_modules/vue/src/platforms/weex/runtime/directives/index.js new file mode 100755 index 00000000..efba7fa6 --- /dev/null +++ b/node_modules/vue/src/platforms/weex/runtime/directives/index.js @@ -0,0 +1,2 @@ +export default { +} diff --git a/node_modules/vue/src/platforms/weex/runtime/index.js b/node_modules/vue/src/platforms/weex/runtime/index.js new file mode 100755 index 00000000..b8e09305 --- /dev/null +++ b/node_modules/vue/src/platforms/weex/runtime/index.js @@ -0,0 +1,42 @@ +/* @flow */ + +import Vue from 'core/index' +import { patch } from 'weex/runtime/patch' +import { mountComponent } from 'core/instance/lifecycle' +import platformDirectives from 'weex/runtime/directives/index' +import platformComponents from 'weex/runtime/components/index' + +import { + query, + mustUseProp, + isReservedTag, + isRuntimeComponent, + isUnknownElement +} from 'weex/util/element' + +// install platform specific utils +Vue.config.mustUseProp = mustUseProp +Vue.config.isReservedTag = isReservedTag +Vue.config.isRuntimeComponent = isRuntimeComponent +Vue.config.isUnknownElement = isUnknownElement + +// install platform runtime directives and components +Vue.options.directives = platformDirectives +Vue.options.components = platformComponents + +// install platform patch function +Vue.prototype.__patch__ = patch + +// wrap mount +Vue.prototype.$mount = function ( + el?: any, + hydrating?: boolean +): Component { + return mountComponent( + this, + el && query(el, this.$document), + hydrating + ) +} + +export default Vue diff --git a/node_modules/vue/src/platforms/weex/runtime/modules/attrs.js b/node_modules/vue/src/platforms/weex/runtime/modules/attrs.js new file mode 100755 index 00000000..1b6185ca --- /dev/null +++ b/node_modules/vue/src/platforms/weex/runtime/modules/attrs.js @@ -0,0 +1,44 @@ +/* @flow */ + +import { extend } from 'shared/util' + +function updateAttrs (oldVnode: VNodeWithData, vnode: VNodeWithData) { + if (!oldVnode.data.attrs && !vnode.data.attrs) { + return + } + let key, cur, old + const elm = vnode.elm + const oldAttrs = oldVnode.data.attrs || {} + let attrs = vnode.data.attrs || {} + // clone observed objects, as the user probably wants to mutate it + if (attrs.__ob__) { + attrs = vnode.data.attrs = extend({}, attrs) + } + + const supportBatchUpdate = typeof elm.setAttrs === 'function' + const batchedAttrs = {} + for (key in attrs) { + cur = attrs[key] + old = oldAttrs[key] + if (old !== cur) { + supportBatchUpdate + ? (batchedAttrs[key] = cur) + : elm.setAttr(key, cur) + } + } + for (key in oldAttrs) { + if (attrs[key] == null) { + supportBatchUpdate + ? (batchedAttrs[key] = undefined) + : elm.setAttr(key) + } + } + if (supportBatchUpdate) { + elm.setAttrs(batchedAttrs) + } +} + +export default { + create: updateAttrs, + update: updateAttrs +} diff --git a/node_modules/vue/src/platforms/weex/runtime/modules/class.js b/node_modules/vue/src/platforms/weex/runtime/modules/class.js new file mode 100755 index 00000000..029b9e9e --- /dev/null +++ b/node_modules/vue/src/platforms/weex/runtime/modules/class.js @@ -0,0 +1,75 @@ +/* @flow */ + +import { extend } from 'shared/util' + +function updateClass (oldVnode: VNodeWithData, vnode: VNodeWithData) { + const el = vnode.elm + const ctx = vnode.context + + const data: VNodeData = vnode.data + const oldData: VNodeData = oldVnode.data + if (!data.staticClass && + !data.class && + (!oldData || (!oldData.staticClass && !oldData.class)) + ) { + return + } + + const oldClassList = [] + // unlike web, weex vnode staticClass is an Array + const oldStaticClass: any = oldData.staticClass + if (oldStaticClass) { + oldClassList.push.apply(oldClassList, oldStaticClass) + } + if (oldData.class) { + oldClassList.push.apply(oldClassList, oldData.class) + } + + const classList = [] + // unlike web, weex vnode staticClass is an Array + const staticClass: any = data.staticClass + if (staticClass) { + classList.push.apply(classList, staticClass) + } + if (data.class) { + classList.push.apply(classList, data.class) + } + + if (typeof el.setClassList === 'function') { + el.setClassList(classList) + } else { + const style = getStyle(oldClassList, classList, ctx) + if (typeof el.setStyles === 'function') { + el.setStyles(style) + } else { + for (const key in style) { + el.setStyle(key, style[key]) + } + } + } +} + +function getStyle (oldClassList: Array<string>, classList: Array<string>, ctx: Component): Object { + // style is a weex-only injected object + // compiled from <style> tags in weex files + const stylesheet: any = ctx.$options.style || {} + const result = {} + classList.forEach(name => { + const style = stylesheet[name] + extend(result, style) + }) + oldClassList.forEach(name => { + const style = stylesheet[name] + for (const key in style) { + if (!result.hasOwnProperty(key)) { + result[key] = '' + } + } + }) + return result +} + +export default { + create: updateClass, + update: updateClass +} diff --git a/node_modules/vue/src/platforms/weex/runtime/modules/events.js b/node_modules/vue/src/platforms/weex/runtime/modules/events.js new file mode 100755 index 00000000..a3f9e25a --- /dev/null +++ b/node_modules/vue/src/platforms/weex/runtime/modules/events.js @@ -0,0 +1,57 @@ +/* @flow */ + +import { updateListeners } from 'core/vdom/helpers/update-listeners' + +let target: any + +function add ( + event: string, + handler: Function, + once: boolean, + capture: boolean, + passive?: boolean, + params?: Array<any> +) { + if (capture) { + console.log('Weex do not support event in bubble phase.') + return + } + if (once) { + const oldHandler = handler + const _target = target // save current target element in closure + handler = function (ev) { + const res = arguments.length === 1 + ? oldHandler(ev) + : oldHandler.apply(null, arguments) + if (res !== null) { + remove(event, null, null, _target) + } + } + } + target.addEvent(event, handler, params) +} + +function remove ( + event: string, + handler: any, + capture: any, + _target?: any +) { + (_target || target).removeEvent(event) +} + +function updateDOMListeners (oldVnode: VNodeWithData, vnode: VNodeWithData) { + if (!oldVnode.data.on && !vnode.data.on) { + return + } + const on = vnode.data.on || {} + const oldOn = oldVnode.data.on || {} + target = vnode.elm + updateListeners(on, oldOn, add, remove, vnode.context) + target = undefined +} + +export default { + create: updateDOMListeners, + update: updateDOMListeners +} diff --git a/node_modules/vue/src/platforms/weex/runtime/modules/index.js b/node_modules/vue/src/platforms/weex/runtime/modules/index.js new file mode 100755 index 00000000..dd384484 --- /dev/null +++ b/node_modules/vue/src/platforms/weex/runtime/modules/index.js @@ -0,0 +1,13 @@ +import attrs from './attrs' +import klass from './class' +import events from './events' +import style from './style' +import transition from './transition' + +export default [ + attrs, + klass, + events, + style, + transition +] diff --git a/node_modules/vue/src/platforms/weex/runtime/modules/style.js b/node_modules/vue/src/platforms/weex/runtime/modules/style.js new file mode 100755 index 00000000..bdabd17b --- /dev/null +++ b/node_modules/vue/src/platforms/weex/runtime/modules/style.js @@ -0,0 +1,84 @@ +/* @flow */ + +import { extend, cached, camelize } from 'shared/util' + +const normalize = cached(camelize) + +function createStyle (oldVnode: VNodeWithData, vnode: VNodeWithData) { + if (!vnode.data.staticStyle) { + updateStyle(oldVnode, vnode) + return + } + const elm = vnode.elm + const staticStyle = vnode.data.staticStyle + const supportBatchUpdate = typeof elm.setStyles === 'function' + const batchedStyles = {} + for (const name in staticStyle) { + if (staticStyle[name]) { + supportBatchUpdate + ? (batchedStyles[normalize(name)] = staticStyle[name]) + : elm.setStyle(normalize(name), staticStyle[name]) + } + } + if (supportBatchUpdate) { + elm.setStyles(batchedStyles) + } + updateStyle(oldVnode, vnode) +} + +function updateStyle (oldVnode: VNodeWithData, vnode: VNodeWithData) { + if (!oldVnode.data.style && !vnode.data.style) { + return + } + let cur, name + const elm = vnode.elm + const oldStyle: any = oldVnode.data.style || {} + let style: any = vnode.data.style || {} + + const needClone = style.__ob__ + + // handle array syntax + if (Array.isArray(style)) { + style = vnode.data.style = toObject(style) + } + + // clone the style for future updates, + // in case the user mutates the style object in-place. + if (needClone) { + style = vnode.data.style = extend({}, style) + } + + const supportBatchUpdate = typeof elm.setStyles === 'function' + const batchedStyles = {} + for (name in oldStyle) { + if (!style[name]) { + supportBatchUpdate + ? (batchedStyles[normalize(name)] = '') + : elm.setStyle(normalize(name), '') + } + } + for (name in style) { + cur = style[name] + supportBatchUpdate + ? (batchedStyles[normalize(name)] = cur) + : elm.setStyle(normalize(name), cur) + } + if (supportBatchUpdate) { + elm.setStyles(batchedStyles) + } +} + +function toObject (arr) { + const res = {} + for (var i = 0; i < arr.length; i++) { + if (arr[i]) { + extend(res, arr[i]) + } + } + return res +} + +export default { + create: createStyle, + update: updateStyle +} diff --git a/node_modules/vue/src/platforms/weex/runtime/modules/transition.js b/node_modules/vue/src/platforms/weex/runtime/modules/transition.js new file mode 100644 index 00000000..e474c2b3 --- /dev/null +++ b/node_modules/vue/src/platforms/weex/runtime/modules/transition.js @@ -0,0 +1,270 @@ +import { warn } from 'core/util/debug' +import { extend, once, noop } from 'shared/util' +import { activeInstance } from 'core/instance/lifecycle' +import { resolveTransition } from 'web/runtime/transition-util' + +export default { + create: enter, + activate: enter, + remove: leave +} + +function enter (_, vnode) { + const el = vnode.elm + + // call leave callback now + if (el._leaveCb) { + el._leaveCb.cancelled = true + el._leaveCb() + } + + const data = resolveTransition(vnode.data.transition) + if (!data) { + return + } + + /* istanbul ignore if */ + if (el._enterCb) { + return + } + + const { + enterClass, + enterToClass, + enterActiveClass, + appearClass, + appearToClass, + appearActiveClass, + beforeEnter, + enter, + afterEnter, + enterCancelled, + beforeAppear, + appear, + afterAppear, + appearCancelled + } = data + + let context = activeInstance + let transitionNode = activeInstance.$vnode + while (transitionNode && transitionNode.parent) { + transitionNode = transitionNode.parent + context = transitionNode.context + } + + const isAppear = !context._isMounted || !vnode.isRootInsert + + if (isAppear && !appear && appear !== '') { + return + } + + const startClass = isAppear ? appearClass : enterClass + const toClass = isAppear ? appearToClass : enterToClass + const activeClass = isAppear ? appearActiveClass : enterActiveClass + const beforeEnterHook = isAppear ? (beforeAppear || beforeEnter) : beforeEnter + const enterHook = isAppear ? (typeof appear === 'function' ? appear : enter) : enter + const afterEnterHook = isAppear ? (afterAppear || afterEnter) : afterEnter + const enterCancelledHook = isAppear ? (appearCancelled || enterCancelled) : enterCancelled + + const userWantsControl = + enterHook && + // enterHook may be a bound method which exposes + // the length of original fn as _length + (enterHook._length || enterHook.length) > 1 + + const stylesheet = vnode.context.$options.style || {} + const startState = stylesheet[startClass] + const transitionProperties = (stylesheet['@TRANSITION'] && stylesheet['@TRANSITION'][activeClass]) || {} + const endState = getEnterTargetState(el, stylesheet, startClass, toClass, activeClass, vnode.context) + const needAnimation = Object.keys(endState).length > 0 + + const cb = el._enterCb = once(() => { + if (cb.cancelled) { + enterCancelledHook && enterCancelledHook(el) + } else { + afterEnterHook && afterEnterHook(el) + } + el._enterCb = null + }) + + // We need to wait until the native element has been inserted, but currently + // there's no API to do that. So we have to wait "one frame" - not entirely + // sure if this is guaranteed to be enough (e.g. on slow devices?) + setTimeout(() => { + const parent = el.parentNode + const pendingNode = parent && parent._pending && parent._pending[vnode.key] + if (pendingNode && + pendingNode.context === vnode.context && + pendingNode.tag === vnode.tag && + pendingNode.elm._leaveCb + ) { + pendingNode.elm._leaveCb() + } + enterHook && enterHook(el, cb) + + if (needAnimation) { + const animation = vnode.context.$requireWeexModule('animation') + animation.transition(el.ref, { + styles: endState, + duration: transitionProperties.duration || 0, + delay: transitionProperties.delay || 0, + timingFunction: transitionProperties.timingFunction || 'linear' + }, userWantsControl ? noop : cb) + } else if (!userWantsControl) { + cb() + } + }, 16) + + // start enter transition + beforeEnterHook && beforeEnterHook(el) + + if (startState) { + if (typeof el.setStyles === 'function') { + el.setStyles(startState) + } else { + for (const key in startState) { + el.setStyle(key, startState[key]) + } + } + } + + if (!needAnimation && !userWantsControl) { + cb() + } +} + +function leave (vnode, rm) { + const el = vnode.elm + + // call enter callback now + if (el._enterCb) { + el._enterCb.cancelled = true + el._enterCb() + } + + const data = resolveTransition(vnode.data.transition) + if (!data) { + return rm() + } + + if (el._leaveCb) { + return + } + + const { + leaveClass, + leaveToClass, + leaveActiveClass, + beforeLeave, + leave, + afterLeave, + leaveCancelled, + delayLeave + } = data + + const userWantsControl = + leave && + // leave hook may be a bound method which exposes + // the length of original fn as _length + (leave._length || leave.length) > 1 + + const stylesheet = vnode.context.$options.style || {} + const startState = stylesheet[leaveClass] + const endState = stylesheet[leaveToClass] || stylesheet[leaveActiveClass] + const transitionProperties = (stylesheet['@TRANSITION'] && stylesheet['@TRANSITION'][leaveActiveClass]) || {} + + const cb = el._leaveCb = once(() => { + if (el.parentNode && el.parentNode._pending) { + el.parentNode._pending[vnode.key] = null + } + if (cb.cancelled) { + leaveCancelled && leaveCancelled(el) + } else { + rm() + afterLeave && afterLeave(el) + } + el._leaveCb = null + }) + + if (delayLeave) { + delayLeave(performLeave) + } else { + performLeave() + } + + function performLeave () { + const animation = vnode.context.$requireWeexModule('animation') + // the delayed leave may have already been cancelled + if (cb.cancelled) { + return + } + // record leaving element + if (!vnode.data.show) { + (el.parentNode._pending || (el.parentNode._pending = {}))[vnode.key] = vnode + } + beforeLeave && beforeLeave(el) + + if (startState) { + animation.transition(el.ref, { + styles: startState + }, next) + } else { + next() + } + + function next () { + animation.transition(el.ref, { + styles: endState, + duration: transitionProperties.duration || 0, + delay: transitionProperties.delay || 0, + timingFunction: transitionProperties.timingFunction || 'linear' + }, userWantsControl ? noop : cb) + } + + leave && leave(el, cb) + if (!endState && !userWantsControl) { + cb() + } + } +} + +// determine the target animation style for an entering transition. +function getEnterTargetState (el, stylesheet, startClass, endClass, activeClass, vm) { + const targetState = {} + const startState = stylesheet[startClass] + const endState = stylesheet[endClass] + const activeState = stylesheet[activeClass] + // 1. fallback to element's default styling + if (startState) { + for (const key in startState) { + targetState[key] = el.style[key] + if ( + process.env.NODE_ENV !== 'production' && + targetState[key] == null && + (!activeState || activeState[key] == null) && + (!endState || endState[key] == null) + ) { + warn( + `transition property "${key}" is declared in enter starting class (.${startClass}), ` + + `but not declared anywhere in enter ending class (.${endClass}), ` + + `enter active cass (.${activeClass}) or the element's default styling. ` + + `Note in Weex, CSS properties need explicit values to be transitionable.` + ) + } + } + } + // 2. if state is mixed in active state, extract them while excluding + // transition properties + if (activeState) { + for (const key in activeState) { + if (key.indexOf('transition') !== 0) { + targetState[key] = activeState[key] + } + } + } + // 3. explicit endState has highest priority + if (endState) { + extend(targetState, endState) + } + return targetState +} diff --git a/node_modules/vue/src/platforms/weex/runtime/node-ops.js b/node_modules/vue/src/platforms/weex/runtime/node-ops.js new file mode 100755 index 00000000..0438ec5c --- /dev/null +++ b/node_modules/vue/src/platforms/weex/runtime/node-ops.js @@ -0,0 +1,91 @@ +/* @flow */ +declare var document: WeexDocument; + +import TextNode from 'weex/runtime/text-node' + +export const namespaceMap = {} + +export function createElement (tagName: string): WeexElement { + return document.createElement(tagName) +} + +export function createElementNS (namespace: string, tagName: string): WeexElement { + return document.createElement(namespace + ':' + tagName) +} + +export function createTextNode (text: string) { + return new TextNode(text) +} + +export function createComment (text: string) { + return document.createComment(text) +} + +export function insertBefore ( + node: WeexElement, + target: WeexElement, + before: WeexElement +) { + if (target.nodeType === 3) { + if (node.type === 'text') { + node.setAttr('value', target.text) + target.parentNode = node + } else { + const text = createElement('text') + text.setAttr('value', target.text) + node.insertBefore(text, before) + } + return + } + node.insertBefore(target, before) +} + +export function removeChild (node: WeexElement, child: WeexElement) { + if (child.nodeType === 3) { + node.setAttr('value', '') + return + } + node.removeChild(child) +} + +export function appendChild (node: WeexElement, child: WeexElement) { + if (child.nodeType === 3) { + if (node.type === 'text') { + node.setAttr('value', child.text) + child.parentNode = node + } else { + const text = createElement('text') + text.setAttr('value', child.text) + node.appendChild(text) + } + return + } + + node.appendChild(child) +} + +export function parentNode (node: WeexElement): WeexElement | void { + return node.parentNode +} + +export function nextSibling (node: WeexElement): WeexElement | void { + return node.nextSibling +} + +export function tagName (node: WeexElement): string { + return node.type +} + +export function setTextContent (node: WeexElement, text: string) { + if (node.parentNode) { + node.parentNode.setAttr('value', text) + } +} + +export function setAttribute (node: WeexElement, key: string, val: any) { + node.setAttr(key, val) +} + +export function setStyleScope (node: WeexElement, scopeId: string) { + node.setAttr('@styleScope', scopeId) +} diff --git a/node_modules/vue/src/platforms/weex/runtime/patch.js b/node_modules/vue/src/platforms/weex/runtime/patch.js new file mode 100644 index 00000000..5e70d143 --- /dev/null +++ b/node_modules/vue/src/platforms/weex/runtime/patch.js @@ -0,0 +1,16 @@ +/* @flow */ + +import * as nodeOps from 'weex/runtime/node-ops' +import { createPatchFunction } from 'core/vdom/patch' +import baseModules from 'core/vdom/modules/index' +import platformModules from 'weex/runtime/modules/index' + +// the directive module should be applied last, after all +// built-in modules have been applied. +const modules = platformModules.concat(baseModules) + +export const patch: Function = createPatchFunction({ + nodeOps, + modules, + LONG_LIST_THRESHOLD: 10 +}) diff --git a/node_modules/vue/src/platforms/weex/runtime/recycle-list/render-component-template.js b/node_modules/vue/src/platforms/weex/runtime/recycle-list/render-component-template.js new file mode 100644 index 00000000..17e8c018 --- /dev/null +++ b/node_modules/vue/src/platforms/weex/runtime/recycle-list/render-component-template.js @@ -0,0 +1,34 @@ +/* @flow */ + +import { warn } from 'core/util/debug' +import { handleError } from 'core/util/error' +import { RECYCLE_LIST_MARKER } from 'weex/util/index' +import { createComponentInstanceForVnode } from 'core/vdom/create-component' +import { resolveVirtualComponent } from './virtual-component' + +export function isRecyclableComponent (vnode: VNodeWithData): boolean { + return vnode.data.attrs + ? (RECYCLE_LIST_MARKER in vnode.data.attrs) + : false +} + +export function renderRecyclableComponentTemplate (vnode: MountedComponentVNode): VNode { + // $flow-disable-line + delete vnode.data.attrs[RECYCLE_LIST_MARKER] + resolveVirtualComponent(vnode) + const vm = createComponentInstanceForVnode(vnode) + const render = (vm.$options: any)['@render'] + if (render) { + try { + return render.call(vm) + } catch (err) { + handleError(err, vm, `@render`) + } + } else { + warn( + `@render function not defined on component used in <recycle-list>. ` + + `Make sure to declare \`recyclable="true"\` on the component's template.`, + vm + ) + } +} diff --git a/node_modules/vue/src/platforms/weex/runtime/recycle-list/virtual-component.js b/node_modules/vue/src/platforms/weex/runtime/recycle-list/virtual-component.js new file mode 100644 index 00000000..e5498d26 --- /dev/null +++ b/node_modules/vue/src/platforms/weex/runtime/recycle-list/virtual-component.js @@ -0,0 +1,136 @@ +/* @flow */ + +// https://github.com/Hanks10100/weex-native-directive/tree/master/component + +import { mergeOptions, isPlainObject, noop } from 'core/util/index' +import Watcher from 'core/observer/watcher' +import { initProxy } from 'core/instance/proxy' +import { initState, getData } from 'core/instance/state' +import { initRender } from 'core/instance/render' +import { initEvents } from 'core/instance/events' +import { initProvide, initInjections } from 'core/instance/inject' +import { initLifecycle, callHook } from 'core/instance/lifecycle' +import { initInternalComponent, resolveConstructorOptions } from 'core/instance/init' +import { registerComponentHook, updateComponentData } from '../../util/index' + +let uid = 0 + +// override Vue.prototype._init +function initVirtualComponent (options: Object = {}) { + const vm: Component = this + const componentId = options.componentId + + // virtual component uid + vm._uid = `virtual-component-${uid++}` + + // a flag to avoid this being observed + vm._isVue = true + // merge options + if (options && options._isComponent) { + // optimize internal component instantiation + // since dynamic options merging is pretty slow, and none of the + // internal component options needs special treatment. + initInternalComponent(vm, options) + } else { + vm.$options = mergeOptions( + resolveConstructorOptions(vm.constructor), + options || {}, + vm + ) + } + + /* istanbul ignore else */ + if (process.env.NODE_ENV !== 'production') { + initProxy(vm) + } else { + vm._renderProxy = vm + } + + vm._self = vm + initLifecycle(vm) + initEvents(vm) + initRender(vm) + callHook(vm, 'beforeCreate') + initInjections(vm) // resolve injections before data/props + initState(vm) + initProvide(vm) // resolve provide after data/props + callHook(vm, 'created') + + // send initial data to native + const data = vm.$options.data + const params = typeof data === 'function' + ? getData(data, vm) + : data || {} + if (isPlainObject(params)) { + updateComponentData(componentId, params) + } + + registerComponentHook(componentId, 'lifecycle', 'attach', () => { + callHook(vm, 'beforeMount') + + const updateComponent = () => { + vm._update(vm._vnode, false) + } + new Watcher(vm, updateComponent, noop, null, true) + + vm._isMounted = true + callHook(vm, 'mounted') + }) + + registerComponentHook(componentId, 'lifecycle', 'detach', () => { + vm.$destroy() + }) +} + +// override Vue.prototype._update +function updateVirtualComponent (vnode?: VNode) { + const vm: Component = this + const componentId = vm.$options.componentId + if (vm._isMounted) { + callHook(vm, 'beforeUpdate') + } + vm._vnode = vnode + if (vm._isMounted && componentId) { + // TODO: data should be filtered and without bindings + const data = Object.assign({}, vm._data) + updateComponentData(componentId, data, () => { + callHook(vm, 'updated') + }) + } +} + +// listening on native callback +export function resolveVirtualComponent (vnode: MountedComponentVNode): VNode { + const BaseCtor = vnode.componentOptions.Ctor + const VirtualComponent = BaseCtor.extend({}) + const cid = VirtualComponent.cid + VirtualComponent.prototype._init = initVirtualComponent + VirtualComponent.prototype._update = updateVirtualComponent + + vnode.componentOptions.Ctor = BaseCtor.extend({ + beforeCreate () { + // const vm: Component = this + + // TODO: listen on all events and dispatch them to the + // corresponding virtual components according to the componentId. + // vm._virtualComponents = {} + const createVirtualComponent = (componentId, propsData) => { + // create virtual component + // const subVm = + new VirtualComponent({ + componentId, + propsData + }) + // if (vm._virtualComponents) { + // vm._virtualComponents[componentId] = subVm + // } + } + + registerComponentHook(cid, 'lifecycle', 'create', createVirtualComponent) + }, + beforeDestroy () { + delete this._virtualComponents + } + }) +} + diff --git a/node_modules/vue/src/platforms/weex/runtime/text-node.js b/node_modules/vue/src/platforms/weex/runtime/text-node.js new file mode 100644 index 00000000..0720a05a --- /dev/null +++ b/node_modules/vue/src/platforms/weex/runtime/text-node.js @@ -0,0 +1,9 @@ +let latestNodeId = 1 + +export default function TextNode (text) { + this.instanceId = '' + this.nodeId = latestNodeId++ + this.parentNode = null + this.nodeType = 3 + this.text = text +} |
