From 2aaa7ad832f33ef7f6c921ccee54361de1c882ab Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=AE=87=E5=A4=A9?= Date: Sat, 21 Jul 2018 22:40:04 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BC=98=E5=8C=96=E7=BB=84=E4=BB=B6=E5=AD=90?= =?UTF-8?q?=E7=88=B6=E5=85=B3=E7=B3=BB=E7=9A=84=E5=AE=9A=E4=B9=89;?= =?UTF-8?q?=E7=A7=BB=E9=99=A4=E7=BB=84=E4=BB=B6:if=E6=8C=87=E4=BB=A4?= =?UTF-8?q?=E7=9A=84=E6=94=AF=E6=8C=81;=E5=AE=8C=E6=88=90tree=E7=BB=84?= =?UTF-8?q?=E4=BB=B6=E7=9A=84=E7=A7=BB=E6=A4=8D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/js/anot-touch.js | 44 ++++----- src/js/anot-touch.shim.js | 44 ++++----- src/js/anot.js | 44 ++++----- src/js/anot.shim.js | 44 ++++----- src/js/tree/index.js | 186 ++++++++++++++++++++------------------ src/js/tree/main.scss | 11 ++- 6 files changed, 172 insertions(+), 201 deletions(-) diff --git a/src/js/anot-touch.js b/src/js/anot-touch.js index 5fca328..084659d 100644 --- a/src/js/anot-touch.js +++ b/src/js/anot-touch.js @@ -227,14 +227,11 @@ const _Anot = (function() { } else { var _parent = $elem while ((_parent = _parent.parentNode)) { - if (_parent.anotctrl) { + if (_parent.__VM__) { break } } - scanTag( - $elem.parentNode, - _parent ? [VMODELS[_parent.anotctrl]] : [] - ) + scanTag($elem.parentNode, _parent ? [_parent.__VM__] : []) } } }) @@ -3283,10 +3280,6 @@ const _Anot = (function() { }) } - function createSignalTower(elem, vmodel) { - elem.anotctrl = elem.anotctrl || vmodel.$id - } - function getBindingCallback(elem, name, vmodels) { var callback = elem.getAttribute(name) if (callback) { @@ -3559,7 +3552,8 @@ const _Anot = (function() { vm = [newVmodel] elem.removeAttribute(node.name) //removeAttributeNode不会刷新xx[anot]样式规则 - createSignalTower(elem, newVmodel) + // 挂载VM对象到相应的元素上 + elem.__VM__ = newVmodel hideProperty(newVmodel, '$elem', elem) if (vmodels.length) { @@ -3827,19 +3821,12 @@ const _Anot = (function() { var state = {} var props = getOptionsFromTag(elem, host.vmodels) var $id = props.uuid || generateID(widget) - var __willpush__ = null var slots = null if (elem.firstElementChild) { slots = parseSlot(elem.children) } - if (props.hasOwnProperty('hostPush')) { - elem.removeAttribute('host-push') - __willpush__ = props.hostPush - props.hostPush = parseVmValue(parentVm, __willpush__) - } - if (props.hasOwnProperty(':disabled')) { var disabledKey = props[':disabled'] var disabledKeyReverse = false @@ -3891,7 +3878,7 @@ const _Anot = (function() { var childValueWatcher = function() { var val = this.value if (val && typeof val === 'object') { - val = val.$model || val + val = val.$model } parseVmValue(parentVm, valueKey, val) } @@ -3978,19 +3965,21 @@ const _Anot = (function() { var vmodel = Anot(hooks) hideProperty(vmodel, '__WIDGET__', name) delete vmodel.$mounted - parentVm.$components.push(vmodel) - if (parentVm.__WIDGET__ === name) { - vmodel.$up = parentVm + + // 对象组件的子父vm关系, 只存最顶层的$components对象中, + // 而子vm, 无论向下多少级, 他们的$up对象也只存最顶层的组件vm + var __pvm__ = parentVm + while (__pvm__.$up && __pvm__.$up.__WIDGET__ === name) { + __pvm__ = __pvm__.$up } + __pvm__.$components.push(vmodel) + if (__pvm__.__WIDGET__ === name) { + vmodel.$up = __pvm__ + } + __pvm__ = undefined elem.msResolved = 1 //防止二进扫描此元素 - if (__willpush__) { - hideProperty(vmodel, '$push', function(val) { - parseVmValue(parentVm, __willpush__, val) - }) - } - componentWillMount.call(vmodel) globalHooks.componentWillMount.call(null, vmodel) @@ -4051,6 +4040,7 @@ const _Anot = (function() { } } }) + elem.__VM__ = vmodel scanTag(elem, [vmodel]) Anot.vmodels[vmodel.$id] = vmodel if (!elem.childNodes.length) { diff --git a/src/js/anot-touch.shim.js b/src/js/anot-touch.shim.js index 95bd1aa..9ac332e 100644 --- a/src/js/anot-touch.shim.js +++ b/src/js/anot-touch.shim.js @@ -242,14 +242,11 @@ } else { var _parent = $elem while ((_parent = _parent.parentNode)) { - if (_parent.anotctrl) { + if (_parent.__VM__) { break } } - scanTag( - $elem.parentNode, - _parent ? [VMODELS[_parent.anotctrl]] : [] - ) + scanTag($elem.parentNode, _parent ? [_parent.__VM__] : []) } } }) @@ -3298,10 +3295,6 @@ }) } - function createSignalTower(elem, vmodel) { - elem.anotctrl = elem.anotctrl || vmodel.$id - } - function getBindingCallback(elem, name, vmodels) { var callback = elem.getAttribute(name) if (callback) { @@ -3574,7 +3567,8 @@ vm = [newVmodel] elem.removeAttribute(node.name) //removeAttributeNode不会刷新xx[anot]样式规则 - createSignalTower(elem, newVmodel) + // 挂载VM对象到相应的元素上 + elem.__VM__ = newVmodel hideProperty(newVmodel, '$elem', elem) if (vmodels.length) { @@ -3842,19 +3836,12 @@ var state = {} var props = getOptionsFromTag(elem, host.vmodels) var $id = props.uuid || generateID(widget) - var __willpush__ = null var slots = null if (elem.firstElementChild) { slots = parseSlot(elem.children) } - if (props.hasOwnProperty('hostPush')) { - elem.removeAttribute('host-push') - __willpush__ = props.hostPush - props.hostPush = parseVmValue(parentVm, __willpush__) - } - if (props.hasOwnProperty(':disabled')) { var disabledKey = props[':disabled'] var disabledKeyReverse = false @@ -3906,7 +3893,7 @@ var childValueWatcher = function() { var val = this.value if (val && typeof val === 'object') { - val = val.$model || val + val = val.$model } parseVmValue(parentVm, valueKey, val) } @@ -3993,19 +3980,21 @@ var vmodel = Anot(hooks) hideProperty(vmodel, '__WIDGET__', name) delete vmodel.$mounted - parentVm.$components.push(vmodel) - if (parentVm.__WIDGET__ === name) { - vmodel.$up = parentVm + + // 对象组件的子父vm关系, 只存最顶层的$components对象中, + // 而子vm, 无论向下多少级, 他们的$up对象也只存最顶层的组件vm + var __pvm__ = parentVm + while (__pvm__.$up && __pvm__.$up.__WIDGET__ === name) { + __pvm__ = __pvm__.$up } + __pvm__.$components.push(vmodel) + if (__pvm__.__WIDGET__ === name) { + vmodel.$up = __pvm__ + } + __pvm__ = undefined elem.msResolved = 1 //防止二进扫描此元素 - if (__willpush__) { - hideProperty(vmodel, '$push', function(val) { - parseVmValue(parentVm, __willpush__, val) - }) - } - componentWillMount.call(vmodel) globalHooks.componentWillMount.call(null, vmodel) @@ -4066,6 +4055,7 @@ } } }) + elem.__VM__ = vmodel scanTag(elem, [vmodel]) Anot.vmodels[vmodel.$id] = vmodel if (!elem.childNodes.length) { diff --git a/src/js/anot.js b/src/js/anot.js index c7c9873..b165391 100644 --- a/src/js/anot.js +++ b/src/js/anot.js @@ -227,14 +227,11 @@ const _Anot = (function() { } else { var _parent = $elem while ((_parent = _parent.parentNode)) { - if (_parent.anotctrl) { + if (_parent.__VM__) { break } } - scanTag( - $elem.parentNode, - _parent ? [VMODELS[_parent.anotctrl]] : [] - ) + scanTag($elem.parentNode, _parent ? [_parent.__VM__] : []) } } }) @@ -3283,10 +3280,6 @@ const _Anot = (function() { }) } - function createSignalTower(elem, vmodel) { - elem.anotctrl = elem.anotctrl || vmodel.$id - } - function getBindingCallback(elem, name, vmodels) { var callback = elem.getAttribute(name) if (callback) { @@ -3559,7 +3552,8 @@ const _Anot = (function() { vm = [newVmodel] elem.removeAttribute(node.name) //removeAttributeNode不会刷新xx[anot]样式规则 - createSignalTower(elem, newVmodel) + // 挂载VM对象到相应的元素上 + elem.__VM__ = newVmodel hideProperty(newVmodel, '$elem', elem) if (vmodels.length) { @@ -3827,19 +3821,12 @@ const _Anot = (function() { var state = {} var props = getOptionsFromTag(elem, host.vmodels) var $id = props.uuid || generateID(widget) - var __willpush__ = null var slots = null if (elem.firstElementChild) { slots = parseSlot(elem.children) } - if (props.hasOwnProperty('hostPush')) { - elem.removeAttribute('host-push') - __willpush__ = props.hostPush - props.hostPush = parseVmValue(parentVm, __willpush__) - } - if (props.hasOwnProperty(':disabled')) { var disabledKey = props[':disabled'] var disabledKeyReverse = false @@ -3891,7 +3878,7 @@ const _Anot = (function() { var childValueWatcher = function() { var val = this.value if (val && typeof val === 'object') { - val = val.$model || val + val = val.$model } parseVmValue(parentVm, valueKey, val) } @@ -3978,19 +3965,21 @@ const _Anot = (function() { var vmodel = Anot(hooks) hideProperty(vmodel, '__WIDGET__', name) delete vmodel.$mounted - parentVm.$components.push(vmodel) - if (parentVm.__WIDGET__ === name) { - vmodel.$up = parentVm + + // 对象组件的子父vm关系, 只存最顶层的$components对象中, + // 而子vm, 无论向下多少级, 他们的$up对象也只存最顶层的组件vm + var __pvm__ = parentVm + while (__pvm__.$up && __pvm__.$up.__WIDGET__ === name) { + __pvm__ = __pvm__.$up } + __pvm__.$components.push(vmodel) + if (__pvm__.__WIDGET__ === name) { + vmodel.$up = __pvm__ + } + __pvm__ = undefined elem.msResolved = 1 //防止二进扫描此元素 - if (__willpush__) { - hideProperty(vmodel, '$push', function(val) { - parseVmValue(parentVm, __willpush__, val) - }) - } - componentWillMount.call(vmodel) globalHooks.componentWillMount.call(null, vmodel) @@ -4051,6 +4040,7 @@ const _Anot = (function() { } } }) + elem.__VM__ = vmodel scanTag(elem, [vmodel]) Anot.vmodels[vmodel.$id] = vmodel if (!elem.childNodes.length) { diff --git a/src/js/anot.shim.js b/src/js/anot.shim.js index 86508e1..45b39c7 100644 --- a/src/js/anot.shim.js +++ b/src/js/anot.shim.js @@ -242,14 +242,11 @@ } else { var _parent = $elem while ((_parent = _parent.parentNode)) { - if (_parent.anotctrl) { + if (_parent.__VM__) { break } } - scanTag( - $elem.parentNode, - _parent ? [VMODELS[_parent.anotctrl]] : [] - ) + scanTag($elem.parentNode, _parent ? [_parent.__VM__] : []) } } }) @@ -3298,10 +3295,6 @@ }) } - function createSignalTower(elem, vmodel) { - elem.anotctrl = elem.anotctrl || vmodel.$id - } - function getBindingCallback(elem, name, vmodels) { var callback = elem.getAttribute(name) if (callback) { @@ -3574,7 +3567,8 @@ vm = [newVmodel] elem.removeAttribute(node.name) //removeAttributeNode不会刷新xx[anot]样式规则 - createSignalTower(elem, newVmodel) + // 挂载VM对象到相应的元素上 + elem.__VM__ = newVmodel hideProperty(newVmodel, '$elem', elem) if (vmodels.length) { @@ -3842,19 +3836,12 @@ var state = {} var props = getOptionsFromTag(elem, host.vmodels) var $id = props.uuid || generateID(widget) - var __willpush__ = null var slots = null if (elem.firstElementChild) { slots = parseSlot(elem.children) } - if (props.hasOwnProperty('hostPush')) { - elem.removeAttribute('host-push') - __willpush__ = props.hostPush - props.hostPush = parseVmValue(parentVm, __willpush__) - } - if (props.hasOwnProperty(':disabled')) { var disabledKey = props[':disabled'] var disabledKeyReverse = false @@ -3906,7 +3893,7 @@ var childValueWatcher = function() { var val = this.value if (val && typeof val === 'object') { - val = val.$model || val + val = val.$model } parseVmValue(parentVm, valueKey, val) } @@ -3993,19 +3980,21 @@ var vmodel = Anot(hooks) hideProperty(vmodel, '__WIDGET__', name) delete vmodel.$mounted - parentVm.$components.push(vmodel) - if (parentVm.__WIDGET__ === name) { - vmodel.$up = parentVm + + // 对象组件的子父vm关系, 只存最顶层的$components对象中, + // 而子vm, 无论向下多少级, 他们的$up对象也只存最顶层的组件vm + var __pvm__ = parentVm + while (__pvm__.$up && __pvm__.$up.__WIDGET__ === name) { + __pvm__ = __pvm__.$up } + __pvm__.$components.push(vmodel) + if (__pvm__.__WIDGET__ === name) { + vmodel.$up = __pvm__ + } + __pvm__ = undefined elem.msResolved = 1 //防止二进扫描此元素 - if (__willpush__) { - hideProperty(vmodel, '$push', function(val) { - parseVmValue(parentVm, __willpush__, val) - }) - } - componentWillMount.call(vmodel) globalHooks.componentWillMount.call(null, vmodel) @@ -4066,6 +4055,7 @@ } } }) + elem.__VM__ = vmodel scanTag(elem, [vmodel]) Anot.vmodels[vmodel.$id] = vmodel if (!elem.childNodes.length) { diff --git a/src/js/tree/index.js b/src/js/tree/index.js index d224ccb..22ce836 100644 --- a/src/js/tree/index.js +++ b/src/js/tree/index.js @@ -11,26 +11,26 @@ import './main.scss' //储存版本信息 Anot.ui.tree = '1.0.0' -const log = console.log -function format(arr, { id, parent, label }) { +function format(arr, expand, { id, parent, label } = {}) { let tmp = {} let farr = [] + this.__path__ = {} arr = Anot.deepCopy(arr) arr.sort(function(a, b) { return a[parent] === b[parent] ? a.sort - b.sort : a[parent] - b[parent] }) - arr.forEach(function(it) { - // Anot.hideProperty(it, '__checked__', !!it.__checked__) - it.__checked__ = !!it.__checked__ - it.open = !!it.open - // console.log(it.hasOwnProperty('__checked__'), it.__checked__) + arr.forEach(it => { + this.__path__[it[id]] = [] tmp[it[id]] = it - var parentItem = tmp[it[parent]] + let parentItem = tmp[it[parent]] if (!parentItem) { return farr.push(tmp[it[id]]) } + this.__path__[it[id]] = this.__path__[parentItem[id]].concat(parentItem[id]) + parentItem.__open__ = + typeof expand === 'boolean' ? expand : expand.includes(parentItem[id]) parentItem.children = parentItem.children || [] parentItem.children.push(it) }) @@ -40,41 +40,49 @@ function format(arr, { id, parent, label }) { export default Anot.component('tree', { __init__: function(props, state, next) { this.classList.add('do-tree') - // this.setAttribute(':visible', 'list.size()') + this.setAttribute(':visible', 'list.size()') + + if (props.hasOwnProperty('expand')) { + if (Array.isArray(props.expand)) { + state.expand = props.expand + } else { + state.expand = true + } + } if (props.list) { for (let it of props.list) { - state.__LIST__.push(it) state.__LIST_DICT__[it[props.id]] = it } } - state.value = state.value || [] - state.list = format(props.list || [], props) + state.list = format.call(this, props.list || [], state.expand, props) state.multiCheck = props.hasOwnProperty('multiCheck') + delete props.list delete props.multiCheck + delete props.expand next() }, render: function() { let { multiCheck } = this return ` -
+
- +
@@ -82,8 +90,7 @@ export default Anot.component('tree', { :value="value" :attr="{ list: el.children, - '@itemClick': props.itemClick, - '@itemPicked': __check, + expand: expand, id: props.id, label: props.label, parent: props.parent, @@ -94,108 +101,111 @@ export default Anot.component('tree', { }, componentDidMount: function() { - this.list.forEach(it => { - if (it.__checked__) { - this.checkedItems[it[this.props.id]] = it.$model - } - }) if (typeof this.props.created === 'function') { this.props.created(this) } }, state: { - __LIST__: [], __LIST_DICT__: {}, list: [], - value: [], - multiCheck: false, - currItem: -1, - checkedItems: {} + value: null, + multiCheck: false }, - skip: ['checkedItems', '__LIST__', '__LIST_DICT__'], + skip: ['__LIST_DICT__'], props: { id: 'id', label: 'label', parent: 'parent', + checked: [], created: Anot.PropsTypes.isFunction(), itemClick: Anot.PropsTypes.isFunction(), - itemPicked: Anot.PropsTypes.isFunction() + itemCheck: Anot.PropsTypes.isFunction() }, methods: { // 子目录的开关 - __toggle: function(obj) { - if (!obj.children) { + __toggle: function(item) { + if (!item.children) { return } - obj.open = !obj.open + item.__open__ = !item.__open__ + }, + __isChecked(item) { + let vm = this + if (vm.$up) { + vm = vm.$up + } + let { checked, id } = vm.props + return checked.includes(item[id]) }, // 选中条目, 并将选中的列表向上冒泡, 直到最外层将结果通过回调返回给外部 - __check: function(el, itemsFromChild, ev) { - if (ev) { - Anot(ev.target).toggleClass('do-icon-get') - } - - // return - let item = null - let arr = [] - let vm, id, itemPicked, checkedItems - - if (this.props) { - vm = this - id = this.props.id - itemPicked = this.props.itemPicked - checkedItems = this.checkedItems - } else { - vm = this.$up - id = vm.props.id - itemPicked = vm.props.itemPicked - checkedItems = vm.checkedItems - } - - if (itemsFromChild) { - item = el - Object.assign(checkedItems, itemsFromChild) - } else { - el.__checked__ = !el.__checked__ - // Anot.hideProperty(el, '__checked__', !el.__checked__) - item = el.$model - checkedItems[item[id]] = el.__checked__ ? item : null - } + __check: function(item, ev) { + Anot(ev.target).toggleClass('do-icon-get') + let vm = this if (vm.$up) { - arr = checkedItems - } else { - // 冒泡到最高一层时, 将对象转为数组 - for (let i in checkedItems) { - if (checkedItems[i]) { - arr.push(checkedItems[i]) - } else { - delete checkedItems[i] - } - } + vm = vm.$up } - if (typeof itemPicked === 'function') { - itemPicked(item, arr) + let { + props: { checked, id, itemCheck }, + __LIST_DICT__ + } = vm + if (checked.includes(item[id])) { + Anot.Array.remove(checked, item[id]) + } else { + checked.push(item[id]) + } + if (typeof itemCheck === 'function') { + itemCheck(__LIST_DICT__[item[id]], checked) } }, // 单个条目的点击选择 - __select: function(el) { - let { id, itemClick } = this.props - this.currItem = el[id] + __pick: function(el) { + let vm = this + let id = this.props.id + // 只取最顶层的VM的字典, 因为子VM的字典已经被污染了 + if (vm.$up) { + vm = vm.$up + } + let { + __LIST_DICT__, + props: { itemClick } + } = vm + this.value = el[id] if (typeof itemClick === 'function') { - itemClick(this.__LIST_DICT__[el[id]]) - // itemClick(el.$model) + itemClick(__LIST_DICT__[el[id]]) + } + }, + update(itemId, data) { + let vm = this + let path = this.$elem.__path__[itemId] + let { id } = this.props + // 主键ID不可修改 + delete data[id] + + if (path.length) { + for (let tmp of vm.$components) { + if (tmp.__LIST_DICT__[itemId]) { + vm = tmp + break + } + } + } + + for (let it of vm.list) { + if (it[id] === itemId) { + Object.assign(it, data) + } } }, // 以给定的列表重置组件渲染 resetWith: function(arr = []) { - this.checked = {} this.list.clear() for (let it of arr) { - this.__LIST__.push(it) this.__LIST_DICT__[it[this.props.id]] = it } - this.list.pushArray(format(arr || [], this.props)) + this.list.pushArray( + format.call(this.$elem, arr || [], this.expand, this.props) + ) } } }) diff --git a/src/js/tree/main.scss b/src/js/tree/main.scss index 4fc48fb..558e24f 100644 --- a/src/js/tree/main.scss +++ b/src/js/tree/main.scss @@ -9,20 +9,21 @@ @import '../../css/var.scss'; -.do-tree {overflow:hidden;overflow-y:auto;position:relative;display:inline-block;width:100%;height:100%;line-height:36px;font-size:15px;color:nth($cd, 2); +.do-tree {overflow:hidden;overflow-y:auto;position:relative;display:block;width:100%;height:100%;line-height:34px;font-size:15px;color:nth($cd, 2); - &__item {overflow:hidden; min-height:35px;margin:1px 0; white-space:nowrap; text-overflow:ellipsis; + &__item {overflow:hidden; min-height:34px; - .sub-tree {display:none;margin-left:20px;} + .sub-tree {display:none;width:100%;padding-left:20px;} - em,span {display:inline-block;cursor:pointer;color:nth($cd, 1);} - em {float:left;padding:0 5px;font-size:20px;} + em,span {display:block;cursor:pointer;} + em {float:left;padding:0 5px;font-size:20px;color:nth($cd, 1);} span { &:hover {color:nth($cd, 1);} &.active {color:nth($cd, 3);font-weight:bold;} &.checkbox {float:left;position:relative;width:18px;height:18px;margin:8px 5px 8px 0;line-height:16px;border:1px solid nth($cd, 2);border-radius:3px; font-size:16px;text-align:center;} + &.label { white-space:nowrap; text-overflow:ellipsis;} } } &__item.open>.sub-tree {display:block;}