Cycle.js 应用未捕获类型错误
Cycle.js app uncaught type error
我正在努力学习 Cycle.js
并且必须说我发现它很有趣。我正在尝试创建一个简单的应用程序,其中有一个 input
和一个 ul
。每次向 input
写入一些值并按回车键时,我想添加一个新的 li
并将值添加到 ul
,但它因以下错误而失败。
Uncaught TypeError: observables[_name2].doOnError is not a function
var view = function (state) {
return CycleDOM.body([
CycleDOM.input({ type: 'text', value: '' }),
CycleDOM.ul({ className: 'text' },
state.map(function (value) {
CycleDOM.li({ innerText: value });
}))
]);
};
var intent = function (DOM) {
return DOM.select('input[type=text]').events('keydown').filter(function (ev) {
return ev.which == 13 && ev.target.value.trim().length > 0;
}).map(function (ev) {
return ev.target.value;
});
};
var model = function (action) {
return action.startWith('');
};
var main = function (sources) {
var actions = intent(sources.DOM);
var state = model(actions);
var sinks = {
DOM: view(state)
};
return sinks;
}
var drivers = {
DOM: CycleDOM.makeDOMDriver(document.body)
};
Cycle.run(main, drivers);
首先,很高兴看到人们对 Cycle 感兴趣!
您在这里遗漏了一些要点,这就是您遇到困难的原因。
您可能还没有完全理解响应式编程的概念。你应该阅读 The introduction to Reactive Programming you've been missing by the creator of Cycle and watch his videos about Cycle。它们确实有助于理解 Cycle 的内部工作原理。
另外,你可以采用Cycle的命名规范,很有帮助。 stream/observable 应该以 $
结尾,比如
var click$ = DOM.select('a').events('click');
正如@juanrpozo 所说,您的主要问题出在您的 view
函数中,因为它 returns 是一个虚拟树,而不是虚拟树的可观察对象。
同样重要的是,您了解 state
变量是可观察的,而不是 javascript 数组。这就是为什么我认为您对 Rx 还不满意。您认为您正在映射一个数组,但实际上您映射的是一个可观察对象,因此返回另一个可观察对象,而不是一个数组。
但是由于 DOM sink 应该是一个可观察的,这很完美,你只需要将你的 VTree 包裹在地图中:
var view = function (state$) {
return state$.map(function (values) {
CycleDOM.body([
CycleDOM.input({ type: 'text', value: '' }),
CycleDOM.ul({ className: 'text' }, values.map(function (value) {
CycleDOM.li(value);
}))
])
};
}
另一个问题是您的 state$
管理。您必须了解 state$
是组件的连续状态流。在 Whosebug 上很难解释这一点,但是如果你 read/watch 我发给你的资源,你会毫无问题地得到它。
我让你 a jsbin of your code 更正并更改了一点,以更加尊重 Intent/Model/View 约定。
您还有其他错误,但这些是最重要的。
我正在努力学习 Cycle.js
并且必须说我发现它很有趣。我正在尝试创建一个简单的应用程序,其中有一个 input
和一个 ul
。每次向 input
写入一些值并按回车键时,我想添加一个新的 li
并将值添加到 ul
,但它因以下错误而失败。
Uncaught TypeError: observables[_name2].doOnError is not a function
var view = function (state) {
return CycleDOM.body([
CycleDOM.input({ type: 'text', value: '' }),
CycleDOM.ul({ className: 'text' },
state.map(function (value) {
CycleDOM.li({ innerText: value });
}))
]);
};
var intent = function (DOM) {
return DOM.select('input[type=text]').events('keydown').filter(function (ev) {
return ev.which == 13 && ev.target.value.trim().length > 0;
}).map(function (ev) {
return ev.target.value;
});
};
var model = function (action) {
return action.startWith('');
};
var main = function (sources) {
var actions = intent(sources.DOM);
var state = model(actions);
var sinks = {
DOM: view(state)
};
return sinks;
}
var drivers = {
DOM: CycleDOM.makeDOMDriver(document.body)
};
Cycle.run(main, drivers);
首先,很高兴看到人们对 Cycle 感兴趣!
您在这里遗漏了一些要点,这就是您遇到困难的原因。
您可能还没有完全理解响应式编程的概念。你应该阅读 The introduction to Reactive Programming you've been missing by the creator of Cycle and watch his videos about Cycle。它们确实有助于理解 Cycle 的内部工作原理。
另外,你可以采用Cycle的命名规范,很有帮助。 stream/observable 应该以 $
结尾,比如
var click$ = DOM.select('a').events('click');
正如@juanrpozo 所说,您的主要问题出在您的 view
函数中,因为它 returns 是一个虚拟树,而不是虚拟树的可观察对象。
同样重要的是,您了解 state
变量是可观察的,而不是 javascript 数组。这就是为什么我认为您对 Rx 还不满意。您认为您正在映射一个数组,但实际上您映射的是一个可观察对象,因此返回另一个可观察对象,而不是一个数组。
但是由于 DOM sink 应该是一个可观察的,这很完美,你只需要将你的 VTree 包裹在地图中:
var view = function (state$) {
return state$.map(function (values) {
CycleDOM.body([
CycleDOM.input({ type: 'text', value: '' }),
CycleDOM.ul({ className: 'text' }, values.map(function (value) {
CycleDOM.li(value);
}))
])
};
}
另一个问题是您的 state$
管理。您必须了解 state$
是组件的连续状态流。在 Whosebug 上很难解释这一点,但是如果你 read/watch 我发给你的资源,你会毫无问题地得到它。
我让你 a jsbin of your code 更正并更改了一点,以更加尊重 Intent/Model/View 约定。
您还有其他错误,但这些是最重要的。