omi - fix proxy, no updating when the last element is removed from the array

This commit is contained in:
dntzhang 2018-12-07 09:11:51 +08:00
parent 88ab2ef65e
commit b4f552684f
26 changed files with 241 additions and 73 deletions

View File

@ -1,6 +1,6 @@
[English](./README.md) | 简体中文 | [한국어](./README.KR.md)
<p align="right">v<strong>5.0.10</strong></p>
<p align="right">v<strong>5.0.11</strong></p>
<p align="center"><img src="./assets/omi3.png" alt="omi" width="300"/></p>
<h2 align="center">Omi - 下一代 Web 框架,去万物糟粕,合精华为一</h2>
<p align="center"><b>让 JSX, Web Components, Proxy, Store, Path Updating 在一起</b></p>

View File

@ -1,6 +1,6 @@
[English](./README.md) | [简体中文](./README.CN.md) | 한국어
<p align="right">v<strong>5.0.10</strong></p>
<p align="right">v<strong>5.0.11</strong></p>
<p align="center"><img src="./assets/omi3.png" alt="omi" width="300"/></p>
<h2 align="center">Omi: 4kb 자바스크립트 차세대 웹 프레임워크</h2>
<p align="center"><b>JSX, Web Components, Proxy, Store, Path Updating 지원</b></p>

View File

@ -1,6 +1,6 @@
English | [简体中文](./README.CN.md) | [한국어](./README.KR.md)
<p align="right">v<strong>5.0.10</strong></p>
<p align="right">v<strong>5.0.11</strong></p>
<p align="center"><img src="./assets/omi3.png" alt="omi" width="300"/></p>
<h2 align="center">Omi: Next Generation Web Framework in 4kb JavaScript</h2>
<p align="center"><b>Merge JSX, Web Components, Proxy, Store, Path Updating together</b></p>

Binary file not shown.

After

Width:  |  Height:  |  Size: 619 B

View File

@ -13,6 +13,9 @@ Component({
methods: {
checkboxChange: function(e) {
vm.toogleComplete(e.currentTarget.dataset.id)
},
remove:function(e){
vm.remove(e.currentTarget.dataset.id)
}
}
})

View File

@ -1,5 +1,5 @@
<view >
<label class="checkbox {{item.completed&&'completed'}}" wx:for="{{items}}">
<checkbox bindtap="checkboxChange" data-id="{{item.id}}" checked="{{item.completed}}"/>{{item.text}}
<checkbox bindtap="checkboxChange" data-id="{{item.id}}" checked="{{item.completed}}"/>{{item.text}}<image bindtap="remove" data-id="{{item.id}}" src="./remove.png" />
</label>
</view>

View File

@ -5,4 +5,17 @@
.completed{
color: #d9d9d9;
text-decoration: line-through;
}
image{
width: 40rpx;
height: 40rpx;
position: absolute;
right: 0px;
top: 2px;
}
label{
position: relative;
margin-top: 4px;
}

View File

@ -2,14 +2,32 @@ import JSONProxy from './proxy'
const create = {}
create.Page = function(vm, options) {
create.Page = function (vm, options) {
options.data = vm.data
const onLoad = options.onLoad
options.onLoad = function(e) {
vm.data = new JSONProxy(vm.data).observe(false, info => {
this.setData(vm.data)
let timeout = null
let patchs = {}
options.onLoad = function (e) {
vm.data = new JSONProxy(vm.data).observe(false, patch => {
clearTimeout(timeout)
console.log(patch )
if (patch.op === 'remove') {//fix arr splice
const kv = getArrayPatch(patch.path)
patchs[kv.k] = kv.v
timeout = setTimeout(() => {
console.log(patchs)
this.setData(patchs)
patchs = {}
})
} else {
const key = fixPath(patch.path)
patchs[key] = patch.value
timeout = setTimeout(() => {
this.setData(patchs)
patchs = {}
})
}
})
this.setData(vm.data)
onLoad && onLoad.call(this, e)
@ -17,12 +35,32 @@ create.Page = function(vm, options) {
Page(options)
}
create.Component = function(vm, options) {
create.Component = function (vm, options) {
const ready = options.ready
options.ready = function(e) {
vm.data = new JSONProxy(vm.data).observe(false, info => {
this.setData(vm.data)
let timeout = null
let patchs = {}
options.ready = function (e) {
vm.data = new JSONProxy(vm.data).observe(false, patch => {
console.log(11)
clearTimeout(timeout)
if (patch.op === 'remove') {//fix arr splice
const kv = getArrayPatch(patch.path)
patchs[kv.k] = kv.v
timeout = setTimeout(() => {
console.log(patchs)
this.setData(patchs)
patchs = {}
})
} else {
const key = fixPath(patch.path)
patchs[key] = patch.value
timeout = setTimeout(() => {
this.setData(patchs)
patchs = {}
})
}
})
this.setData(vm.data)
ready && ready.call(this, e)
@ -30,12 +68,62 @@ create.Component = function(vm, options) {
Component(options)
}
function getArrayPatch(path) {
const arr = path.replace('/', '').split('/')
let current = currentData[arr[0]]
for (let i = 1, len = arr.length; i < len - 1; i++) {
current = current[arr[i]]
}
return { k: fixArrPath(path), v: current }
}
function fixArrPath(path) {
let mpPath = ''
const arr = path.replace('/', '').split('/')
const len = arr.length
arr.forEach((item, index) => {
if (index < len - 1) {
if (index) {
if (isNaN(parseInt(item))) {
mpPath += '.' + item
} else {
mpPath += '[' + item + ']'
}
} else {
mpPath += item
}
}
})
return mpPath
}
function fixPath(path) {
let mpPath = ''
const arr = path.replace('/', '').split('/')
arr.forEach((item, index) => {
if (index) {
if (isNaN(parseInt(item))) {
mpPath += '.' + item
} else {
mpPath += '[' + item + ']'
}
} else {
mpPath += item
}
})
return mpPath
}
if (typeof exports == 'object') {
module.exports = create
} else if (typeof define == 'function' && define.amd) {
define([], function() {
define([], function () {
return create
})
} else {
window.create = create
}
}

View File

@ -33,6 +33,11 @@ class TodoViewModel {
this.update()
}
remove(id) {
todo.remove(id)
this.update()
}
getAll() {
todo.getAll(() => {
this.update()

View File

@ -1,5 +1,5 @@
/**
* omi v5.0.10 http://omijs.org
* omi v5.0.11 http://omijs.org
* Omi === Preact + Scoped CSS + Store System + Native Support in 3kb javascript.
* By dntzhang https://github.com/dntzhang
* Github: https://github.com/Tencent/omi
@ -1036,8 +1036,8 @@
function proxyUpdate(ele) {
var timeout = null;
ele.data = new JSONPatcherProxy(ele.data).observe(false, function (info) {
if (ele._willUpdate || info.op === 'replace' && info.oldValue === info.value) {
ele.data = new JSONPatcherProxy(ele.data).observe(false, function () {
if (ele._willUpdate) {
return;
}
if (ele.constructor.mergeUpdate) {
@ -1533,7 +1533,7 @@
};
options.root.Omi = omi;
options.root.Omi.version = '5.0.10';
options.root.Omi.version = '5.0.11';
if (typeof module != 'undefined') module.exports = omi;else self.Omi = omi;
}());

File diff suppressed because one or more lines are too long

View File

@ -1,5 +1,5 @@
/**
* omi v5.0.10 http://omijs.org
* omi v5.0.11 http://omijs.org
* Omi === Preact + Scoped CSS + Store System + Native Support in 3kb javascript.
* By dntzhang https://github.com/dntzhang
* Github: https://github.com/Tencent/omi
@ -1033,8 +1033,8 @@ function observe(target) {
function proxyUpdate(ele) {
var timeout = null;
ele.data = new JSONPatcherProxy(ele.data).observe(false, function (info) {
if (ele._willUpdate || info.op === 'replace' && info.oldValue === info.value) {
ele.data = new JSONPatcherProxy(ele.data).observe(false, function () {
if (ele._willUpdate) {
return;
}
if (ele.constructor.mergeUpdate) {
@ -1530,7 +1530,7 @@ var omi = {
};
options.root.Omi = omi;
options.root.Omi.version = '5.0.10';
options.root.Omi.version = '5.0.11';
export default omi;
export { tag, WeElement, Component, render, h, h as createElement, options, define, observe, cloneElement, getHost, rpx, tick, nextTick, ModelView, defineElement };

File diff suppressed because one or more lines are too long

View File

@ -299,8 +299,8 @@
}
function proxyUpdate(ele) {
var timeout = null;
ele.data = new JSONPatcherProxy(ele.data).observe(!1, function(info) {
if (!(ele.J || 'replace' === info.op && info.oldValue === info.value)) if (ele.constructor.mergeUpdate) {
ele.data = new JSONPatcherProxy(ele.data).observe(!1, function() {
if (!ele.J) if (ele.constructor.mergeUpdate) {
clearTimeout(timeout);
timeout = setTimeout(function() {
ele.update();
@ -909,7 +909,7 @@
defineElement: defineElement
};
options.root.Omi = omi;
options.root.Omi.version = '5.0.10';
options.root.Omi.version = '5.0.11';
if ('undefined' != typeof module) module.exports = omi; else self.Omi = omi;
}();
//# sourceMappingURL=omi.js.map

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -255,14 +255,14 @@
node.addEventListener(name, eventProxy, useCapture);
if (name == 'tap') {
node.addEventListener('touchstart', touchStart, useCapture);
node.addEventListener('touchstart', touchEnd, useCapture);
node.addEventListener('touchend', touchEnd, useCapture);
}
}
} else {
node.removeEventListener(name, eventProxy, useCapture);
if (name == 'tap') {
node.removeEventListener('touchstart', touchStart, useCapture);
node.removeEventListener('touchstart', touchEnd, useCapture);
node.removeEventListener('touchend', touchEnd, useCapture);
}
}
(node._listeners || (node._listeners = {}))[name] = value;
@ -599,6 +599,10 @@
var name = void 0;
var update = false;
var isWeElement = dom.update;
var oldClone = void 0;
if (dom.receiveProps) {
oldClone = Object.assign({}, old);
}
// remove attributes no longer present on the vnode by setting them to undefined
for (name in old) {
if (!(attrs && attrs[name] != null) && old[name] != null) {
@ -612,9 +616,17 @@
// add new & update changed attributes
for (name in attrs) {
//diable when using store system?
//!dom.store &&
if (isWeElement && typeof attrs[name] === 'object') {
if (name === 'style') {
setAccessor(dom, name, old[name], old[name] = attrs[name], isSvgMode);
}
if (dom.receiveProps) {
try {
old[name] = JSON.parse(JSON.stringify(attrs[name]));
} catch (e) {
console.warn('When using receiveProps, you cannot pass prop of cyclic dependencies down.');
}
}
dom.props[npn(name)] = attrs[name];
update = true;
} else if (name !== 'children' && name !== 'innerHTML' && (!(name in old) || attrs[name] !== (name === 'value' || name === 'checked' ? dom[name] : old[name]))) {
@ -628,7 +640,7 @@
if (isWeElement && dom.parentNode) {
if (update || children.length > 0) {
dom.receiveProps(dom.props, dom.data);
dom.receiveProps(dom.props, dom.data, oldClone);
dom.update();
}
}
@ -1020,17 +1032,22 @@
function proxyUpdate(ele) {
var timeout = null;
ele.data = new JSONPatcherProxy(ele.data).observe(false, function (info) {
if (ele._willUpdate || info.op === 'replace' && info.oldValue === info.value) {
ele.data = new JSONPatcherProxy(ele.data).observe(false, function () {
if (ele._willUpdate) {
return;
}
if (ele.constructor.mergeUpdate) {
clearTimeout(timeout);
clearTimeout(timeout);
timeout = setTimeout(function () {
timeout = setTimeout(function () {
ele.update();
fireTick();
}, 0);
} else {
console.log(1111);
ele.update();
fireTick();
}, 0);
}
});
}
@ -1063,7 +1080,7 @@
var p = this.parentNode;
while (p && !this.store) {
this.store = p.store;
p = p.parentNode || p._host;
p = p.parentNode || p.host;
}
if (this.store) {
this.store.instances.push(this);
@ -1494,6 +1511,7 @@
}(WeElement), _class$1.observe = true, _temp$1);
var Component = WeElement;
var defineElement = define;
var omi = {
tag: tag,
@ -1510,11 +1528,12 @@
rpx: rpx,
tick: tick,
nextTick: nextTick,
ModelView: ModelView
ModelView: ModelView,
defineElement: defineElement
};
options.root.Omi = omi;
options.root.Omi.version = '5.0.4';
options.root.Omi.version = '5.0.10';
function createCommonjsModule(fn, module) {
return module = { exports: {} }, fn(module, module.exports), module.exports;
@ -1702,6 +1721,7 @@
item.content = content;
return false;
}
return true;
});
};
@ -1733,6 +1753,7 @@
_this2.items.splice(index, 1);
return false;
}
return true;
});
};
@ -1756,35 +1777,45 @@
function _classCallCheck$5(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
var TodoViewData = function () {
function TodoViewData() {
_classCallCheck$5(this, TodoViewData);
var TodoViewModel = function () {
function TodoViewModel() {
_classCallCheck$5(this, TodoViewModel);
this.data = {
items: []
};
}
TodoViewData.prototype.update = function update() {
TodoViewModel.prototype.update = function update() {
//will automatically update the view!!!
mappingjs.auto(todo, this.data);
};
TodoViewData.prototype.complete = function complete(id) {
TodoViewModel.prototype.complete = function complete(id) {
todo.complete(id);
this.update();
};
TodoViewData.prototype.uncomplete = function uncomplete(id) {
TodoViewModel.prototype.uncomplete = function uncomplete(id) {
todo.uncomplete(id);
this.update();
};
TodoViewData.prototype.add = function add(text) {
TodoViewModel.prototype.add = function add(text) {
todo.add(text);
this.update();
};
TodoViewData.prototype.getAll = function getAll() {
TodoViewModel.prototype.remove = function remove(id) {
todo.remove(id);
console.log(id);
console.log(this.data.items);
//empty first
this.data.items.length = 0;
this.update();
};
TodoViewModel.prototype.getAll = function getAll() {
var _this = this;
todo.getAll(function () {
@ -1792,10 +1823,10 @@
});
};
return TodoViewData;
return TodoViewModel;
}();
var vd = new TodoViewData();
var vm = new TodoViewModel();
function _classCallCheck$6(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
@ -1817,10 +1848,12 @@
return _ret = (_temp = (_this = _possibleConstructorReturn$3(this, _WeElement.call.apply(_WeElement, [this].concat(args))), _this), _this.onChange = function (evt, id) {
if (evt.target.checked) {
vd.complete(id);
vm.complete(id);
} else {
vd.uncomplete(id);
vm.uncomplete(id);
}
}, _this.onClick = function (id) {
vm.remove(id);
}, _temp), _possibleConstructorReturn$3(_this, _ret);
}
@ -1844,7 +1877,14 @@
_this2.onChange(evt, item.id);
}
}),
item.text
item.text,
Omi.h(
'button',
{ onClick: function onClick() {
_this2.onClick(item.id);
} },
'remove'
)
);
})
);
@ -1871,19 +1911,20 @@
args[_key] = arguments[_key];
}
return _ret = (_temp = (_this = _possibleConstructorReturn$4(this, _ModelView.call.apply(_ModelView, [this].concat(args))), _this), _this.vm = vd, _this.handleChange = function (e) {
return _ret = (_temp = (_this = _possibleConstructorReturn$4(this, _ModelView.call.apply(_ModelView, [this].concat(args))), _this), _this.vm = vm, _this.handleChange = function (e) {
_this.text = e.target.value;
}, _this.handleSubmit = function (e) {
e.preventDefault();
if (_this.text !== '') {
vd.add(_this.text);
var text = _this.text;
if (text !== '') {
_this.text = '';
vm.add(text);
}
}, _temp), _possibleConstructorReturn$4(_this, _ret);
}
_class2.prototype.install = function install() {
vd.getAll();
vm.getAll();
};
_class2.prototype.css = function css() {

File diff suppressed because one or more lines are too long

View File

@ -28,6 +28,15 @@ class TodoViewModel {
this.update()
}
remove(id) {
todo.remove(id)
console.log(id)
console.log(this.data.items)
//empty first
this.data.items.length = 0
this.update()
}
getAll() {
todo.getAll(() => {
this.update()

View File

@ -40,9 +40,10 @@ define('todo-app', class extends ModelView {
handleSubmit = e => {
e.preventDefault()
if (this.text !== '') {
vm.add(this.text)
const text = this.text
if (text !== '') {
this.text = ''
vm.add(text)
}
}
})

View File

@ -19,6 +19,10 @@ define('todo-list', class extends WeElement {
}
}
onClick = id => {
vm.remove(id)
}
render(props) {
return (
<ul>
@ -31,6 +35,13 @@ define('todo-list', class extends WeElement {
}}
/>
{item.text}
<button
onClick={() => {
this.onClick(item.id)
}}
>
remove
</button>
</li>
))}
</ul>

View File

@ -7,7 +7,7 @@ define('my-app', class extends WeElement {
install() {
this.dd = { a: 1 }
}
onAbc = evt => {
this.data.abc = ' by ' + evt.detail.name
this.data.passToChild = 1234

View File

@ -1,6 +1,6 @@
{
"name": "omi",
"version": "5.0.10",
"version": "5.0.11",
"description": "Next generation web framework.",
"main": "dist/omi.js",
"jsnext:main": "dist/omi.esm.js",

View File

@ -7,11 +7,8 @@ export function observe(target) {
export function proxyUpdate(ele) {
let timeout = null
ele.data = new JSONProxy(ele.data).observe(false, info => {
if (
ele._willUpdate ||
(info.op === 'replace' && info.oldValue === info.value)
) {
ele.data = new JSONProxy(ele.data).observe(false, () => {
if (ele._willUpdate) {
return
}
if (ele.constructor.mergeUpdate) {

View File

@ -34,7 +34,7 @@ const omi = {
}
options.root.Omi = omi
options.root.Omi.version = '5.0.10'
options.root.Omi.version = '5.0.11'
export default omi