Skip to content

Commit

Permalink
Add useEffect hook
Browse files Browse the repository at this point in the history
  • Loading branch information
Masquerade-Circus committed Nov 29, 2019
1 parent b559b38 commit 5c1b153
Show file tree
Hide file tree
Showing 6 changed files with 299 additions and 133 deletions.
6 changes: 3 additions & 3 deletions .size-snapshot.json
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
{
"dist/valyrian.min.js": {
"bundled": 11941,
"minified": 4901,
"gzipped": 2052
"bundled": 11764,
"minified": 4808,
"gzipped": 2038
},
"dist/store.min.js": {
"bundled": 11415,
Expand Down
2 changes: 1 addition & 1 deletion dist/valyrian.min.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

34 changes: 11 additions & 23 deletions lib/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,15 +17,11 @@ function Vnode(name, props, children) {
this.children = children;
this.name = name;
};
Vnode.prototype = {
isSVG: FALSE
};

function TextVnode() {}
TextVnode.prototype = {
props: emptyObject,
children: emptyArray,
isSVG: FALSE
children: emptyArray
};

let emptyNode = new TextVnode();
Expand Down Expand Up @@ -53,19 +49,16 @@ v.dom2vnode = function (dom) {
vnode = new TextVnode();
vnode.dom = dom;
} else if (dom.nodeType === 1) {
let name = dom.nodeName;
let props = {};
emptyArray.forEach.call(dom.attributes, ({nodeName, nodeValue}) => props[nodeName] = nodeValue);

vnode = new Vnode(
name,
{},
dom.nodeName,
props,
[]
);
vnode.dom = dom;

for (let l = dom.attributes.length; l--;) {
let property = dom.attributes[l];
vnode.props[property.nodeName] = property.nodeValue;
}

for (let i = 0, l = dom.childNodes.length; i < l; i++) {
let childVnode = v.dom2vnode(dom.childNodes[i]);
childVnode && vnode.children.push(childVnode);
Expand Down Expand Up @@ -251,8 +244,8 @@ function patch(parentNode, oldParentNode, isSVG) {
let childVnode = newTree[i];

if (childVnode instanceof Vnode) {
v.current.component = childVnode;
if (typeof childVnode.name !== 'string') {
v.current.component = childVnode;
let viewMethod = 'view' in childVnode.name ? childVnode.name.view : childVnode.name;
newTree.splice(i, 1, ...[viewMethod.call(viewMethod, childVnode.props, ...childVnode.children)]);
i--;
Expand Down Expand Up @@ -319,6 +312,7 @@ function patch(parentNode, oldParentNode, isSVG) {
let newNode = newTree[i];
let oldNode = oldTree[i];


// Is vnode
if (newNode instanceof Vnode) {
isSVG = isSVG || newNode.isSVG;
Expand All @@ -340,7 +334,6 @@ function patch(parentNode, oldParentNode, isSVG) {
// Is text
} else {
let dom;

// Added
if (oldNode === UND) {
dom = document.createTextNode(newNode);
Expand All @@ -353,6 +346,7 @@ function patch(parentNode, oldParentNode, isSVG) {
// Updated
} else {
dom = oldNode.dom;
newNode = String(newNode);
if (newNode !== dom.nodeValue) {
dom.nodeValue = newNode;
}
Expand Down Expand Up @@ -396,21 +390,15 @@ v.mount = (container, component, props, ...children) => {
};

v.unmount = () => {
mountedComponent = () => {};
mountedComponent = () => '';
let result = v.update();
mountedComponent = UND;
v.isMounted = FALSE;
return result;
};

v.directive = (directive, handler) => directive in v.reservedWords === FALSE && (v.reservedWords[directive] = handler);
v.directive('v-for', (set, vnode) => {
let handler = vnode.children[0];
vnode.children = [];
for (let i = 0, l = set.length; i < l; i++) {
vnode.children[i] = handler(set[i], i);
}
});
v.directive('v-for', (set, vnode) => vnode.children = set.map(vnode.children[0]));

let hideDirective = (test) => (bool, vnode, oldnode) => {
if (bool === test) {
Expand Down
105 changes: 76 additions & 29 deletions plugins/hooks.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,51 @@
let plugin = (v) => {
let hookIndex = 0;
let UND;

function createHook(value) {
v.createHook = function ({name, init, update, response}) {
name = `use${name.charAt(0).toUpperCase()}${name.slice(1).toLowerCase()}`;
if (!v[name]) {
v[name] = (...args) => {
let currentComponent = v.current.component;

if (v.current.parentVnode.components === UND) {
v.current.parentVnode.components = [];
}

if (v.current.parentVnode.components.indexOf(currentComponent) === -1) {
v.current.parentVnode.components.push(currentComponent);
}

let hook;
let oldComponentNode = v.current.oldParentVnode.components &&
v.current.oldParentVnode.components[v.current.parentVnode.components.length - 1];
let oldMethod = oldComponentNode && ('view' in oldComponentNode.name ? oldComponentNode.name.view : oldComponentNode.name);
let currentMethod = 'view' in currentComponent.name ? currentComponent.name.view : currentComponent.name;

if (currentComponent.hooks === UND) {
currentComponent.hooks = [];
}
let hookIndex = currentComponent.hooks.length;

if (oldMethod === currentMethod && 'hooks' in oldComponentNode && oldComponentNode.hooks[hookIndex] !== UND) {
currentComponent.hooks = oldComponentNode.hooks;
hook = oldComponentNode.hooks[hookIndex];
if (update) {
update(hook, ...args);
}
} else {
hook = init(...args);
currentComponent.hooks.push(hook);
}

if (response) {
return response(hook);
}
};
}
};

// State hook
function createStateHook(value) {
let method = function (value) {
if (value !== UND) {
hook.state = value;
Expand Down Expand Up @@ -30,40 +73,44 @@ let plugin = (v) => {
hook(value);
return hook;
}
v.createHook({
name: 'state',
init: (initial) => createStateHook(initial),
response: (hook) => [hook, hook.setState]
});

v.useState = function (initial) {
let currentVnode = v.current.component;

if (v.current.parentVnode.components === UND) {
v.current.parentVnode.components = [];
// Effect hook
function callHook(hook, changes) {
let {prev} = hook;
if (!changes) {
hook.onCleanup = hook.effect();
} else if (changes.length > 0) {
for (let i = 0, l = changes.length; i < l; i++) {
if (changes[i] !== prev[i]) {
hook.prev = changes;
hook.onCleanup = hook.effect();
break;
}
}
}

if (v.current.parentVnode.components.indexOf(currentVnode) === -1) {
v.current.parentVnode.components.push(currentVnode);
if (hook.onCleanup) {
v.onCleanup(hook.onCleanup);
}

let hook;
let oldComponentNode = v.current.oldParentVnode.components &&
v.current.oldParentVnode.components[v.current.parentVnode.components.length - 1];
let oldMethod = oldComponentNode && ('view' in oldComponentNode.name ? oldComponentNode.name.view : oldComponentNode.name);
let currentMethod = 'view' in currentVnode.name ? currentVnode.name.view : currentVnode.name;

if (currentVnode.hooks === UND) {
currentVnode.hooks = [];
hookIndex = 0;
}

if (oldMethod === currentMethod && 'hooks' in oldComponentNode && oldComponentNode.hooks[hookIndex] !== UND) {
currentVnode.hooks = oldComponentNode.hooks;
hook = oldComponentNode.hooks[hookIndex];
} else {
hook = createHook(initial);
currentVnode.hooks.push(hook);
}
v.createHook({
name: 'effect',
init: (effect, changes) => {
let hook = {effect, prev: changes};
callHook(hook);
return hook;
},
update: (hook, effect, changes) => {
callHook(hook, changes);
}
});

hookIndex++;
return hook;
};
};

export default plugin;
Loading

0 comments on commit 5c1b153

Please sign in to comment.