diff --git a/apps/test/app/app.js b/apps/test/app/app.js index f7659f96..21bc01ea 100755 --- a/apps/test/app/app.js +++ b/apps/test/app/app.js @@ -1,4 +1,23 @@ -import { createApp, h, ref, onUnmounted } from '@nativescript-vue/runtime' +import { + createApp, + h, + ref, + onMounted, + onUnmounted, + dumpOps +} from '@nativescript-vue/runtime' + +const dumpDebug = () => + dumpOps().map(op => { + if (op.nodeType) { + console.log( + ` +++ ${op.type}${op.nodeType[0].toUpperCase() + + op.nodeType.substr(1)}(${op.tag})` + ) + } else { + console.log(` +++ ${op.type}`) + } + }) createApp({ render() { @@ -9,6 +28,8 @@ createApp({ }) }, setup() { + onMounted(dumpDebug) + const counter = ref(0) const interval = setInterval(() => counter.value++, 1000) diff --git a/packages/runtime/src/index.ts b/packages/runtime/src/index.ts index 0fd44b0d..424370ce 100644 --- a/packages/runtime/src/index.ts +++ b/packages/runtime/src/index.ts @@ -9,7 +9,6 @@ import { run } from '@nativescript/core/application' import { nodeOps } from './nodeOps' import { patchProp } from './patchProp' import { NSVElement, NSVViewNode } from './nodes' -import { Label } from '@nativescript/core' import './registry' const rendererOptions = { @@ -27,15 +26,7 @@ function runApp(root: ComponentPublicInstance): ComponentPublicInstance { console.log('->runApp') run({ create: () => { - // component.$el - return root.$el._nativeView - // console.log(root.$el) - // - // const label = new Label() - // label.text = 'Hello World' - // label.verticalAlignment = 'middle' - // label.textAlignment = 'center' - // return label + return root.$el.nativeView } }) @@ -51,7 +42,7 @@ export const createApp = ((...args) => { const { mount } = app app.mount = (): any => { - return runApp(mount(nodeOps.createElement('ContentView'))) + return runApp(mount(nodeOps.createRoot())) } return app diff --git a/packages/runtime/src/modules/events.ts b/packages/runtime/src/modules/events.ts new file mode 100644 index 00000000..3c505067 --- /dev/null +++ b/packages/runtime/src/modules/events.ts @@ -0,0 +1,12 @@ +import { NSVViewNode } from '../nodes' +import { ComponentInternalInstance } from '@vue/runtime-core' + +export function patchEvent( + el: NSVViewNode, + name: string, + prevValue: any, + nextValue: any, + instance: ComponentInternalInstance | null = null +) { + // todo implement patchEvent +} diff --git a/packages/runtime/src/nodeOps.ts b/packages/runtime/src/nodeOps.ts index ae382a63..92212fc9 100644 --- a/packages/runtime/src/nodeOps.ts +++ b/packages/runtime/src/nodeOps.ts @@ -39,6 +39,21 @@ export function dumpOps(): NodeOp[] { return ops } +function createRoot(tag: string = 'root') { + const node: NSVElement = new NSVElement(tag, NSVNodeTypes.ROOT) + + logNodeOp({ + type: NodeOpTypes.CREATE, + nodeType: NSVNodeTypes.ELEMENT, + targetNode: node, + tag + }) + // avoid test nodes from being observed + markNonReactive(node) + + return node +} + function createElement(tag: string): NSVViewNode { const node: NSVElement = new NSVElement(tag, NSVNodeTypes.ELEMENT) @@ -193,6 +208,7 @@ function setScopeId(el: NSVElement, id: string) { export const nodeOps = { insert, remove, + createRoot, createElement, createText, createComment, diff --git a/packages/runtime/src/nodes/NSVElement.ts b/packages/runtime/src/nodes/NSVElement.ts index 1d1264bf..dbac5236 100644 --- a/packages/runtime/src/nodes/NSVElement.ts +++ b/packages/runtime/src/nodes/NSVElement.ts @@ -1,12 +1,14 @@ import { getViewClass, getViewMeta, normalizeElementName } from '../registry' import { insertChild, removeChild } from './index' import { ELEMENT_REF } from '@nativescript-vue/runtime' +import { ViewBase } from '@nativescript/core' // import {ELEMENT_REF} from "@nativescript-vue/runtime"; export const enum NSVNodeTypes { TEXT = 'text', ELEMENT = 'element', - COMMENT = 'comment' + COMMENT = 'comment', + ROOT = 'root' } export interface NSVViewNode { @@ -18,7 +20,7 @@ export interface NSVViewNode { nextSibling: NSVViewNode | null firstChild: NSVViewNode | null lastChild: NSVViewNode | null - nativeView: any + nativeView: ViewBase getAttribute: Function text: string } @@ -78,8 +80,6 @@ export class NSVElement implements NSVViewNode { if (nodeType === NSVNodeTypes.ELEMENT) { const viewClass = getViewClass(elementName) - console.log(`->construct ${elementName}`) - console.log(viewClass) this._nativeView = new viewClass() this._nativeView[ELEMENT_REF] = this } diff --git a/packages/runtime/src/patchProp.ts b/packages/runtime/src/patchProp.ts index 5882116e..81cc7100 100644 --- a/packages/runtime/src/patchProp.ts +++ b/packages/runtime/src/patchProp.ts @@ -2,14 +2,18 @@ import { isAndroid, isIOS } from '@nativescript/core/platform' import { logNodeOp, NodeOpTypes } from './nodeOps' // import { isOn } from '@vue/shared' import { NSVViewNode } from './nodes/NSVElement' +import { isOn } from '@vue/shared' +import set = Reflect.set +import { patchEvent } from './modules/events' +import { isAndroidKey, isIOSKey } from './runtimeHelpers' // import set from 'set-value' -const XML_ATTRIBUTES = Object.freeze([ - 'style', - 'rows', - 'columns', - 'fontAttributes' -]) +// const XML_ATTRIBUTES = Object.freeze([ +// 'style', +// 'rows', +// 'columns', +// 'fontAttributes' +// ]) export function patchProp( el: NSVViewNode, @@ -17,42 +21,33 @@ export function patchProp( nextValue: any, prevValue: any ) { - console.log('->patchProp') + // console.log('->patchProp') - // @ts-ignore - el._nativeView[key] = nextValue - // try { - // if (XML_ATTRIBUTES.includes(key)) { - // //nv[key] = value - // } else { - // // // detect expandable attrs for boolean values - // // // See https://vuejs.org/v2/guide/components-props.html#Passing-a-Boolean - // // if ( - // // typeof nv[key] === 'boolean' && - // // value === '' - // // ) { - // // value = true - // // } - // - // if (isAndroid && key.startsWith('android:')) { - // // set(nv, key.substr(8), value) - // } else if (isIOS && key.startsWith('ios:')) { - // // set(nv, key.substr(4), value) - // } else if (key.endsWith('.decode')) { - // // set( - // // nv, - // // key.slice(0, -7), - // // require('@nativescript/core/xml').XmlParser._dereferenceEntities( - // // value - // // ) - // // ) - // } else { - // // set(nv, key, value) - // } - // } - // } catch (e) { - // // ignore - // } + switch (key) { + // special + case 'class': + // todo + console.log('->patchProp+Class') + break + case 'style': + // todo + console.log('->patchProp+Style') + break + case 'modelValue': + case 'onUpdate:modelValue': + // handled by v-model directive + break + default: + if (isOn(key)) { + patchEvent(el, key.substr(2).toLowerCase(), prevValue, nextValue) + } else if (isAndroidKey(key) && isAndroid) { + set(el.nativeView, key.substr(8), nextValue) + } else if (isIOSKey(key) && isIOS) { + set(el.nativeView, key.substr(4), nextValue) + } else { + set(el.nativeView, key, nextValue) + } + } logNodeOp({ type: NodeOpTypes.PATCH, @@ -61,9 +56,4 @@ export function patchProp( propPrevValue: prevValue, propNextValue: nextValue }) - // el.props[key] = nextValue - // if (isOn(key)) { - // const event = key.slice(2).toLowerCase() - // ;(el.eventListeners || (el.eventListeners = {}))[event] = nextValue - // } } diff --git a/packages/runtime/src/registry/index.ts b/packages/runtime/src/registry/index.ts index 13562dec..a7488288 100644 --- a/packages/runtime/src/registry/index.ts +++ b/packages/runtime/src/registry/index.ts @@ -1,6 +1,7 @@ import { Component } from '@nativescript-vue/runtime' -console.log('REGISTRY??') -export type NSVElementResolver = () => any +import { ViewBase } from '@nativescript/core' + +export type NSVElementResolver = () => ViewBase export interface NSVViewMeta { skipAddToDom?: boolean diff --git a/packages/runtime/src/runtimeHelpers.ts b/packages/runtime/src/runtimeHelpers.ts index 210fb694..c4cede06 100644 --- a/packages/runtime/src/runtimeHelpers.ts +++ b/packages/runtime/src/runtimeHelpers.ts @@ -1,7 +1,14 @@ export const ELEMENT_REF = Symbol(__DEV__ ? `elementRef` : ``) -if (__DEV__) { - console.log('IT IS DEV') -} else { - console.log('IT IS NOT DEV') -} +export const isAndroidKey = (key: string) => + key[0] === 'a' && + key[1] === 'n' && + key[2] === 'd' && + key[3] === 'r' && + key[4] === 'o' && + key[5] === 'i' && + key[6] === 'd' && + key[7] === ':' + +export const isIOSKey = (key: string) => + key[0] === 'i' && key[1] === 'o' && key[2] === 's' && key[3] === ':'