Skip to content

Commit

Permalink
feat(react,vue): improve managing node performance
Browse files Browse the repository at this point in the history
  • Loading branch information
zoomchan-cxj committed Nov 17, 2021
1 parent a902743 commit 6470d12
Show file tree
Hide file tree
Showing 9 changed files with 99 additions and 252 deletions.
16 changes: 13 additions & 3 deletions docs/hippy-vue/native-event.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@

# 事件监听器

这里是向前端发送一个名叫 rotate 的事件,里面有个参数是 result,这样就发送到前端去了
这里监听 rotate 的事件,里面有回调参数 result。

```js
// 将入口文件中 setApp() 时保存的 Vue 实例取出来。
Expand All @@ -18,19 +18,29 @@ export default {
console.log(rsp.result);
}
},
didMount() {
mounted() {
// 通过 app 监听 rotate 事件,并通过 this.listener 在事件发生时触发回调。
app.$on('rotate', this.listener);
}
}

```

# 事件触发

如果需要手动发送事件,可以通过 `app.$emit` 触发。

```js
const app = getApp();
app.$emit('rotate', { width: 100, height: 100 });
```

# 事件卸载

如果不需要使用的时候记得调用一下移除监听的方法,一般放在组件的卸载生命周期中执行。

```jsx
```js
const app = getApp();
app.$off('rotate', this.listener);
```

Expand Down
132 changes: 28 additions & 104 deletions packages/hippy-react/src/dom/view-node.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,10 +42,6 @@ class ViewNode {

public parentNode: ViewNode | null = null;

public prevSibling: ViewNode | null = null;

public nextSibling: ViewNode | null = null;

constructor() {
// Virtual DOM node id, will used in native to identify.
this.nodeId = getNodeId();
Expand All @@ -56,16 +52,6 @@ class ViewNode {
return this.constructor.name;
}

get firstChild() {
return this.childNodes.length ? this.childNodes[0] : null;
}

get lastChild() {
return this.childNodes.length
? this.childNodes[this.childNodes.length - 1]
: null;
}

get isMounted() {
return this.mounted;
}
Expand All @@ -79,141 +65,85 @@ class ViewNode {
if (!childNode) {
throw new Error('Can\'t insert child.');
}

if (childNode.meta.skipAddToDom) {
return;
}
if (!referenceNode) {
return this.appendChild(childNode);
}

if (referenceNode.parentNode !== this) {
throw new Error('Can\'t insert child, because the reference node has a different parent.');
}

if (childNode.parentNode && childNode.parentNode !== this) {
throw new Error('Can\'t insert child, because it already has a different parent.');
}

const index = this.childNodes.indexOf(referenceNode);

childNode.parentNode = this;
childNode.nextSibling = referenceNode;
childNode.prevSibling = this.childNodes[index - 1];

referenceNode.prevSibling = childNode;
this.childNodes.splice(index, 0, childNode);

return insertChild(this, childNode, index);
}

moveChild(childNode: ViewNode, referenceNode: ViewNode) {
if (!childNode) {
throw new Error('Can\'t mvoe child.');
throw new Error('Can\'t move child.');
}
if (childNode.meta.skipAddToDom) {
return;
}

if (!referenceNode) {
return this.appendChild(childNode);
}

if (referenceNode.parentNode !== this) {
throw new Error('Can\'t move child, because the reference node has a different parent.');
}

if (childNode.parentNode && childNode.parentNode !== this) {
throw new Error('Can\'t move child, because it already has a different parent.');
}

const oldIndex = this.childNodes.indexOf(childNode);
const newIndex = this.childNodes.indexOf(referenceNode);

const referenceIndex = this.childNodes.indexOf(referenceNode);
// return if the moved index is the same as the previous one
if (newIndex === oldIndex) {
if (referenceIndex === oldIndex) {
return childNode;
}

// set new siblings relations
childNode.nextSibling = referenceNode;
childNode.prevSibling = referenceNode.prevSibling;
referenceNode.prevSibling = childNode;

if (this.childNodes[newIndex - 1]) {
this.childNodes[newIndex - 1].nextSibling = childNode;
}
if (this.childNodes[newIndex + 1]) {
this.childNodes[newIndex + 1].prevSibling = childNode;
}
if (this.childNodes[oldIndex - 1]) {
this.childNodes[oldIndex - 1].nextSibling = this.childNodes[oldIndex + 1];
}
if (this.childNodes[oldIndex + 1]) {
this.childNodes[oldIndex + 1].prevSibling = this.childNodes[oldIndex - 1];
}

// remove old child node from native
removeChild(this, childNode);

// remove old child and insert new child, which is like moving child
this.childNodes.splice(oldIndex, 1);
removeChild(this, childNode, oldIndex);
const newIndex = this.childNodes.indexOf(referenceNode);
this.childNodes.splice(newIndex, 0, childNode);
this.childNodes.splice(oldIndex + (newIndex < oldIndex ? 1 : 0), 1);

// should filter empty nodes before finding the index of node
const atIndex = this.childNodes.filter(ch => ch.index > -1).indexOf(childNode);
return insertChild(this, childNode, atIndex);
return insertChild(this, childNode, newIndex);
}

appendChild(childNode: ViewNode) {
if (!childNode) {
throw new Error('Can\'t append child.');
}

if (childNode.meta.skipAddToDom) {
return;
}
if (childNode.parentNode && childNode.parentNode !== this) {
throw new Error('Can\'t append child, because it already has a different parent.');
}

childNode.parentNode = this;

if (this.lastChild) {
childNode.prevSibling = this.lastChild;
this.lastChild.nextSibling = childNode;
}

this.childNodes.push(childNode);

insertChild(this, childNode, this.childNodes.length - 1);
}

removeChild(childNode: ViewNode) {
if (!childNode) {
throw new Error('Can\'t remove child.');
}

if (childNode.meta.skipAddToDom) {
return;
}
if (!childNode.parentNode) {
throw new Error('Can\'t remove child, because it has no parent.');
}

if (childNode.parentNode !== this) {
throw new Error('Can\'t remove child, because it has a different parent.');
}

if (childNode.meta.skipAddToDom) {
return;
}

removeChild(this, childNode);

// FIXME: parentNode should be null when removeChild, But it breaks add the node again.
// Issue position: https://github.com/vuejs/vue/tree/master/src/core/vdom/patch.js#L250
// childNode.parentNode = null;

if (childNode.prevSibling) {
childNode.prevSibling.nextSibling = childNode.nextSibling;
childNode.prevSibling = null;
}

if (childNode.nextSibling) {
childNode.nextSibling.prevSibling = childNode.prevSibling;
childNode.nextSibling = null;
}

this.childNodes = this.childNodes.filter(node => node !== childNode);
const index = this.childNodes.indexOf(childNode);
this.childNodes.splice(index, 1);
removeChild(this, childNode, index);
}

/**
Expand All @@ -238,22 +168,16 @@ class ViewNode {

/**
* Traverse the children and execute callback
* @param callback - callback function
* @param newIndex - index to be updated
*/
traverseChildren(callback: Function) {
// Find the index and apply callback
let index;
if (this.parentNode) {
index = this.parentNode.childNodes.filter(node => !node.meta.skipAddToDom).indexOf(this);
} else {
index = 0;
}
this.index = index;
traverseChildren(callback: Function, newIndex: number | undefined = 0) {
this.index = !this.parentNode ? 0 : newIndex;
callback(this);

// Find the children
if (this.childNodes.length) {
this.childNodes.forEach((childNode) => {
this.traverseChildren.call(childNode, callback);
this.childNodes.forEach((childNode, index) => {
this.traverseChildren.call(childNode, callback, index);
});
}
}
Expand Down
2 changes: 1 addition & 1 deletion packages/hippy-react/src/hippy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,7 @@ class HippyReact implements HippyReact {
const { __instanceId__: rootViewId } = superProps;
trace(...componentName, 'Start', appName, 'with rootViewId', rootViewId, superProps);

// Update nodeId for contaienr
// Update nodeId for container
this.rootContainer.containerInfo.nodeId = rootViewId;
if (silent) {
setSilent(silent);
Expand Down
2 changes: 1 addition & 1 deletion packages/hippy-react/src/renderer/host-configs.ts
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ function createInstance(
}
}
});
// only HostComponent(5) or Fragment(7) render to native
if ([5, 7].indexOf(workInProgress.tag) < 0) {
element.meta.skipAddToDom = true;
}
Expand All @@ -71,7 +72,6 @@ function createTextInstance(newText: string, rootContainerInstance: Document) {
element.meta = {
component: {
name: 'Text',
skipAddToDom: true,
},
};
return element;
Expand Down
Loading

0 comments on commit 6470d12

Please sign in to comment.