From df8c9c6015c093ead2490d1d2ccbac7890af7c2f Mon Sep 17 00:00:00 2001 From: Yukino Song Date: Thu, 30 Mar 2017 03:32:28 +0800 Subject: [PATCH] Destroy method added --- package.json | 4 ++-- src/lib/renderer.js | 40 ++++++++++++++++++++++++++++------- src/lib/utils/array-helper.js | 6 ++++++ src/lib/utils/creator.js | 15 +++++++------ test/test.js | 15 +++++++++++++ 5 files changed, 64 insertions(+), 16 deletions(-) diff --git a/package.json b/package.json index fb0724f..3f86757 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "ef.js", - "version": "0.1.1-alpha.8", + "version": "0.1.1-alpha.9", "description": "(maybe) An elegent HTML template framework", "main": "dist/ef.min.js", "module": "src/ef.js", @@ -43,7 +43,7 @@ }, "dependencies": { "deep-assign": "^2.0.0", - "eft-parser": "^0.2.4", + "eft-parser": "^0.2.5", "object.assign": "^4.0.4" } } diff --git a/src/lib/renderer.js b/src/lib/renderer.js index 4c1ecd0..381b604 100644 --- a/src/lib/renderer.js +++ b/src/lib/renderer.js @@ -81,6 +81,18 @@ const update = function (state) { assign(this, tmpState) } +const destroy = function() { + delete this.$element + delete this.$data + delete this.$methods + delete this.$subscrib + delete this.$unsubscribe + delete this.$attached + delete this.$update + delete this.$destroy + for (let i in this) delete this[i] +} + const render = (ast) => { ast = ARR.fullCopy(ast) const state = {} @@ -97,7 +109,8 @@ const render = (ast) => { }, set(newData) { deepAssign(data, newData) - } + }, + configurable: true }, $methods: { get() { @@ -105,34 +118,45 @@ const render = (ast) => { }, set(newMethods) { deepAssign(methods, newMethods) - } + }, + configurable: true }, $nodes: { get() { return assign({}, nodes) - } + }, + configurable: true }, $subscribe: { value: (pathStr, handler) => { const path = pathStr.split('.') initBinding({bind: [path], state, subscriber, innerData, handler}) - } + }, + configurable: true }, $unsubscribe: { value: (path, fn) => { unsubscribe(path, fn, subscriber) - } + }, + configurable: true }, $attached: { - get: checkAttached + get: checkAttached, + configurable: true }, $update: { - value: update + value: update, + configurable: true + }, + $destroy: { + value: destroy, + configurable: true } }) const element = create({ast, state, innerData, nodes, children, subscriber}) Object.defineProperty(state, '$element', { - value: element + value: element, + configurable: true }) return state } diff --git a/src/lib/utils/array-helper.js b/src/lib/utils/array-helper.js index 7098333..4858bb9 100644 --- a/src/lib/utils/array-helper.js +++ b/src/lib/utils/array-helper.js @@ -4,6 +4,12 @@ const ARR = { copy(arr) { return proto.slice.call(arr, 0) }, + equals(left, right) { + if (left === right) return true + if (left.length !== right.length) return false + for (let i in left) if (left[i] !== right[i]) return false + return true + }, fullCopy(arr) { return JSON.parse(JSON.stringify(arr)) }, diff --git a/src/lib/utils/creator.js b/src/lib/utils/creator.js index e0fafc4..ab9c399 100644 --- a/src/lib/utils/creator.js +++ b/src/lib/utils/creator.js @@ -7,7 +7,7 @@ import initBinding from './binding.js' import { warn, warnAttachment } from '../debug.js' // Reserved names -const reserved = 'attached data element nodes methods subscribe unsubscribe update'.split(' ').map(i => `$${i}`) +const reserved = 'attached data element nodes methods subscribe unsubscribe update destroy'.split(' ').map(i => `$${i}`) const create = ({ast, state, innerData, nodes, children, subscriber}) => { // First create an element according to the description @@ -55,7 +55,7 @@ const create = ({ast, state, innerData, nodes, children, subscriber}) => { return children[node.name] }, set(value) { - if (children[node.name] && children[node.name].value === value) return + if (children[node.name] === value) return if (value.$attached) return warnAttachment(value) // Update component if (children[node.name]) DOM.remove(children[node.name].$element) @@ -63,7 +63,8 @@ const create = ({ast, state, innerData, nodes, children, subscriber}) => { // Update stored value children[node.name] = value }, - enumerable: true + enumerable: true, + configurable: true }) } else if (node.type === 'list') { const initArr = defineArr([], anchor) @@ -74,7 +75,7 @@ const create = ({ast, state, innerData, nodes, children, subscriber}) => { }, set(value) { value = ARR.copy(value) - if (children[node.name] && children[node.name].value === value) return + if (children[node.name] && ARR.equals(children[node.name], value)) return const fragment = document.createDocumentFragment() // Update components if (children[node.name]) { @@ -86,11 +87,13 @@ const create = ({ast, state, innerData, nodes, children, subscriber}) => { for (let j of children[node.name]) DOM.remove(j.$element) } else for (let j of value) DOM.append(fragment, j.$element) // Update stored value - children[node.name] = defineArr(value, anchor) + children[node.name].length = 0 + ARR.push(children[node.name], ...value) // Append to current component DOM.after(anchor, fragment) }, - enumerable: true + enumerable: true, + configurable: true }) } else throw new TypeError(`Not a standard ef.js AST: Unknown mounting point type '${node.type}'`) // Append placeholder diff --git a/test/test.js b/test/test.js index d453412..f8fe833 100644 --- a/test/test.js +++ b/test/test.js @@ -169,6 +169,21 @@ var data2 = { state.$update(data2) +var states = [] + +state2.$methods.sendMsg = function () { + var startTime = Date.now() + for (var i = 0; i < 1000; i++) states.push(module1.render()) + state4.list1.push.apply(state4.list1, states) + var endTime = Date.now() + for (var i = 0; i < states.length; i++) { + states[i].$destroy() + states[i] = null + } + states = [] + console.log('Done in', endTime - startTime, 'ms.') +} + // state4.$methods.sendMsg = function(thisState) { alert('The message is "\n' + thisState.$data.text + '"!') } document.querySelector('body').appendChild(state.$element)