Skip to content

Commit

Permalink
refactor(runtime): 把运行时与框架解耦 (#6646)
Browse files Browse the repository at this point in the history
  • Loading branch information
yuche authored Jun 16, 2020
1 parent c8a2959 commit 5c0fc48
Show file tree
Hide file tree
Showing 26 changed files with 258 additions and 135 deletions.
3 changes: 2 additions & 1 deletion .eslintrc.js
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,8 @@ module.exports = {
'no-prototype-builtins': 0,
'react/jsx-uses-vars': 'warn',
'react/prop-types': 0,
'react/no-find-dom-node': 0
'react/no-find-dom-node': 0,
'no-unused-expressions': 0
// 'camelcase': ['error', {allow: ['^internal_', '^unstable_']}]
},
'env': {
Expand Down
22 changes: 4 additions & 18 deletions packages/taro-h5/src/api/utils/index.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/* eslint-disable prefer-promise-reject-errors */
import { Current } from '@tarojs/runtime'
import { Current, CurrentReconciler } from '@tarojs/runtime'

function shouleBeObject (target) {
if (target && typeof target === 'object') return { res: true }
Expand All @@ -12,25 +12,11 @@ function shouleBeObject (target) {
}
}

let ReactDOM

if (process.env.FRAMEWORK === 'nerv') {
ReactDOM = require('nervjs')
}

// 其它 react-like 框架走 react 模式,在 webpack.resolve.alias 设置 react/react-dom 到对应包
if (process.env.FRAMEWORK === 'react') {
ReactDOM = require('react-dom')
}

export function findDOM (inst) {
if (inst) {
if (process.env.FRAMEWORK === 'vue') {
return inst.$el
}

if (ReactDOM) {
return ReactDOM.findDOMNode(inst)
const find = CurrentReconciler.findDOMNode
if (typeof find === 'function') {
return find(inst)
}
}

Expand Down
12 changes: 7 additions & 5 deletions packages/taro-loader/src/h5.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import * as webpack from 'webpack'
import { getOptions, stringifyRequest } from 'loader-utils'
import { AppConfig, PageConfig } from '@tarojs/taro'
import { join, dirname } from 'path'
import { importFramework, getFrameworkArgs } from './utils'
import { frameworkMeta } from './utils'

function genResource (path: string, pages: Map<string, PageConfig>, loaderContext: webpack.loader.LoaderContext) {
const stringify = (s: string): string => stringifyRequest(loaderContext, s)
Expand All @@ -19,6 +19,7 @@ function genResource (path: string, pages: Map<string, PageConfig>, loaderContex
export default function (this: webpack.loader.LoaderContext) {
const options = getOptions(this)
const stringify = (s: string): string => stringifyRequest(this, s)
const { importFrameworkStatement, frameworkArgs, creator, importFrameworkName } = frameworkMeta[options.framework]
const config: AppConfig = options.config
const pages: Map<string, PageConfig> = options.pages
let tabBarCode = `var tabbarIconPath = []
Expand All @@ -45,11 +46,11 @@ var tabbarSelectedIconPath = []
import '@tarojs/components/h5/vue'
`

const code = `import Taro from '@tarojs/taro'
const code = `import { createRouter } from '@tarojs/taro'
import component from ${stringify(join(dirname(this.resourcePath), options.filename))}
import { window } from '@tarojs/runtime'
import { ${creator}, window } from '@tarojs/runtime'
import { defineCustomElements, applyPolyfills } from '@tarojs/components/loader'
${importFramework(options.framework)}
${importFrameworkStatement}
import '@tarojs/components/dist/taro-components/taro-components.css'
${options.framework === 'vue' ? vue : ''}
${webComponents}
Expand All @@ -71,7 +72,8 @@ if (config.tabBar) {
config.routes = [
${config.pages?.map(path => genResource(path, pages, this)).join('')}
]
Taro.createRouter(component, config, '${options.framework}', ${getFrameworkArgs(options.framework)})
var inst = ${creator}(component, ${frameworkArgs})
createRouter(inst, config, ${importFrameworkName})
`

return code
Expand Down
41 changes: 41 additions & 0 deletions packages/taro-loader/src/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,3 +22,44 @@ export function getFrameworkArgs (framework: string) {
}
return 'React, ReactDOM, config'
}

export const frameworkMeta: Record<string, {
importFrameworkStatement: string
frameworkArgs: string
creator: string
importFrameworkName: string
}> = {
vue: {
importFrameworkStatement: `
import Vue from 'vue';
`,
frameworkArgs: 'Vue, config',
creator: 'createVueApp',
importFrameworkName: 'Vue'
},
vue3: {
importFrameworkStatement: `
import { h } from 'vue'
`,
frameworkArgs: 'h, config',
creator: 'createVue3App',
importFrameworkName: 'h'
},
nerv: {
importFrameworkStatement: `
import Nerv from 'nervjs';
`,
frameworkArgs: 'Nerv, Nerv, config',
creator: 'createReactApp',
importFrameworkName: 'Nerv'
},
react: {
importFrameworkStatement: `
import * as React from 'react'
import ReactDOM from 'react-dom'
`,
frameworkArgs: 'React, ReactDOM, config',
creator: 'createReactApp',
importFrameworkName: 'React'
}
}
57 changes: 0 additions & 57 deletions packages/taro-router/src/pull-down.ts

This file was deleted.

12 changes: 4 additions & 8 deletions packages/taro-router/src/router.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,11 @@
import UniversalRouter, { Routes } from 'universal-router'
import { AppConfig, PageConfig } from '@tarojs/taro'
import { LocationListener, LocationState } from 'history'
import { createReactApp, createPageConfig, Current, createVueApp, PageInstance, eventCenter } from '@tarojs/runtime'
import { createPageConfig, Current, PageInstance, eventCenter, CurrentReconciler, AppInstance } from '@tarojs/runtime'
import { qs } from './qs'
import { history } from './history'
import { stacks } from './stack'
import { init, routerConfig } from './init'
import { createPullDownRefresh, R, V } from './pull-down'

export interface Route extends PageConfig {
path: string
Expand Down Expand Up @@ -96,11 +95,9 @@ function loadPage (page: PageInstance | null) {
}

export function createRouter (
App,
app: AppInstance,
config: RouterConfig,
type: 'react' | 'vue' | 'nerv',
framework: R | V,
reactdom
framework
) {
init(config)

Expand All @@ -117,7 +114,6 @@ export function createRouter (
}

const router = new UniversalRouter(routes)
const app = type === 'vue' ? createVueApp(App, framework as V, config) : createReactApp(App, framework as R, reactdom, config)
app.onLaunch!()

const render: LocationListener<LocationState> = async (location, action) => {
Expand Down Expand Up @@ -161,7 +157,7 @@ export function createRouter (
if (shouldLoad) {
const el = element.default ?? element
const page = createPageConfig(
enablePullDownRefresh ? createPullDownRefresh(el, type, location.pathname, framework) : el,
enablePullDownRefresh ? CurrentReconciler.createPullDownComponent?.(el, location.pathname, framework) : el,
location.pathname
)
loadPage(page)
Expand Down
20 changes: 9 additions & 11 deletions packages/taro-runtime/src/dom/element.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
/* eslint-disable no-dupe-class-members */
import { isArray, isUndefined, Shortcuts, EMPTY_OBJ, warn, isString, toCamelCase, internalComponents, capitalize, hasOwn, isBooleanStringLiteral } from '@tarojs/shared'
import { isArray, isUndefined, Shortcuts, EMPTY_OBJ, warn, isString, toCamelCase } from '@tarojs/shared'
import { TaroNode } from './node'
import { NodeType } from './node_types'
import { TaroEvent, eventSource } from './event'
import { isElement } from '../utils'
import { Style } from './style'
import { PROPERTY_THRESHOLD } from '../constants'
import { CurrentReconciler } from '../reconciler'

interface Attributes {
name: string;
Expand Down Expand Up @@ -98,28 +99,25 @@ export class TaroElement extends TaroNode {
}
}

CurrentReconciler.setAttribute?.(this, qualifiedName, value)

this.enqueueUpdate({
path: `${this._path}.${process.env.FRAMEWORK === 'vue' ? toCamelCase(qualifiedName) : qualifiedName}`,
path: `${this._path}.${toCamelCase(qualifiedName)}`,
value
})
}

public removeAttribute (qualifiedName: string) {
if (qualifiedName === 'style') {
this.style.cssText = ''
} else if (process.env.FRAMEWORK === 'vue') {
const compName = capitalize(toCamelCase(this.tagName.toLowerCase()))
if (compName in internalComponents && hasOwn(internalComponents[compName], qualifiedName) && isBooleanStringLiteral(internalComponents[compName][qualifiedName])) {
// avoid attribute being removed because set false value in vue
this.setAttribute(qualifiedName, false)
} else {
delete this.props[qualifiedName]
}
} else {
delete this.props[qualifiedName]
}

CurrentReconciler.removeAttribute?.(this, qualifiedName)

this.enqueueUpdate({
path: `${this._path}.${process.env.FRAMEWORK === 'vue' ? toCamelCase(qualifiedName) : qualifiedName}`,
path: `${this._path}.${toCamelCase(qualifiedName)}`,
value: ''
})
}
Expand Down
6 changes: 6 additions & 0 deletions packages/taro-runtime/src/dom/node.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import { Shortcuts, ensure } from '@tarojs/shared'
import { hydrate, HydratedData } from '../hydrate'
import { TaroElement } from './element'
import { setInnerHTML } from './html/html'
import { CurrentReconciler } from '../reconciler'

const nodeId = incrementId()

Expand All @@ -16,6 +17,7 @@ export interface UpdatePayload {
}

export type UpdatePayloadValue = string | boolean | HydratedData
export type DataTree = Record<string, UpdatePayloadValue | ReturnType<HydratedData>>

export class TaroNode extends TaroEventTarget {
public nodeType: NodeType
Expand Down Expand Up @@ -100,6 +102,8 @@ export class TaroNode extends TaroEventTarget {
}
}

CurrentReconciler.insertBefore?.(this, newChild, refChild)

this.enqueueUpdate(payload)
return newChild
}
Expand All @@ -108,6 +112,7 @@ export class TaroNode extends TaroEventTarget {

public appendChild (child: TaroNode) {
this.insertBefore(child)
CurrentReconciler.appendChild?.(this, child)
}

public replaceChild (newChild: TaroNode, oldChild: TaroNode) {
Expand All @@ -116,6 +121,7 @@ export class TaroNode extends TaroEventTarget {
oldChild.remove(true)
return oldChild
}
CurrentReconciler.removeChild?.(this, newChild, oldChild)
}

public removeChild<T extends TaroNode> (child: T, isReplace?: boolean): T {
Expand Down
7 changes: 7 additions & 0 deletions packages/taro-runtime/src/dom/root.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import { UpdatePayload, UpdatePayloadValue } from './node'
import { isFunction, Shortcuts } from '@tarojs/shared'
import { perf } from '../perf'
import { SET_DATA, PAGE_INIT } from '../constants'
import { CurrentReconciler } from '../reconciler'

export class TaroRootElement extends TaroElement {
private pendingUpdate = false
Expand Down Expand Up @@ -74,6 +75,12 @@ export class TaroRootElement extends TaroElement {
}
}

CurrentReconciler.prepareUpdateData?.(data, this)

if (initRender) {
CurrentReconciler.appendInitialPage?.(data, this)
}

if (isFunction(prerender)) {
prerender(data)
} else {
Expand Down
13 changes: 2 additions & 11 deletions packages/taro-runtime/src/dsl/common.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import { PAGE_INIT } from '../constants'
import { isBrowser } from '../env'
import { eventCenter } from '../emitter/emitter'
import { raf } from '../bom/raf'
import { CurrentReconciler } from '../reconciler'

const instances = new Map<string, Instance>()

Expand All @@ -33,23 +34,13 @@ function addLeadingSlash (path?: string) {
const pageId = incrementId()

function safeExecute (path: string, lifecycle: keyof PageInstance, ...args: unknown[]) {
const isReact = process.env.FRAMEWORK !== 'vue' // isReact means all kind of react-like library

const instance = instances.get(path)

if (instance == null) {
return
}

if (isReact) {
if (lifecycle === 'onShow') {
lifecycle = 'componentDidShow'
} else if (lifecycle === 'onHide') {
lifecycle = 'componentDidHide'
}
}

const func = isReact ? instance[lifecycle] : instance.$options[lifecycle]
const func = CurrentReconciler.getLifecyle(instance, lifecycle)

if (isArray(func)) {
for (let i = 0; i < func.length; i++) {
Expand Down
3 changes: 2 additions & 1 deletion packages/taro-runtime/src/dsl/instance.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,8 @@ export interface ReactPageComponent<T = PageProps> extends ComponentClass<T>, Sh
}

export interface ReactPageInstance<T = PageProps> extends Component<T>, Show, PageInstance {
//
componentDidShow?(): void
componentDidHide?(): void
}

export interface ReactAppInstance<T = AppInstance> extends Component<T>, Show, AppInstance {
Expand Down
Loading

0 comments on commit 5c0fc48

Please sign in to comment.