diff --git a/website/docs-cn.html b/website/docs-cn.html index 3bba248d5..3af2904dd 100644 --- a/website/docs-cn.html +++ b/website/docs-cn.html @@ -27,11 +27,11 @@ - + - + \ No newline at end of file diff --git a/website/docs-en.html b/website/docs-en.html index 7caab93c5..40ee85216 100644 --- a/website/docs-en.html +++ b/website/docs-en.html @@ -28,11 +28,11 @@ - + - + \ No newline at end of file diff --git a/website/js/docs-cn.8b99c3b2.js b/website/js/docs-cn.8b99c3b2.js deleted file mode 100644 index fe411b95d..000000000 --- a/website/js/docs-cn.8b99c3b2.js +++ /dev/null @@ -1,1401 +0,0 @@ -window.Root ={}; Root.isDev = false;webpackJsonp([0],[ -/* 0 */ -/***/ function(module, exports, __webpack_require__) { - - 'use strict'; - - var _frame = __webpack_require__(1); - - var _frame2 = _interopRequireDefault(_frame); - - function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - - Omi.render(new _frame2.default({ lan: 'cn' }), 'body', true); - -/***/ }, -/* 1 */ -/***/ function(module, exports, __webpack_require__) { - - 'use strict'; - - Object.defineProperty(exports, "__esModule", { - value: true - }); - - var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); - - var _omi = __webpack_require__(2); - - var _omi2 = _interopRequireDefault(_omi); - - var _index = __webpack_require__(3); - - var _index2 = _interopRequireDefault(_index); - - var _index3 = __webpack_require__(38); - - var _index4 = _interopRequireDefault(_index3); - - var _index5 = __webpack_require__(44); - - var _index6 = _interopRequireDefault(_index5); - - var _config = __webpack_require__(4); - - var _config2 = _interopRequireDefault(_config); - - var _index7 = __webpack_require__(49); - - var _index8 = _interopRequireDefault(_index7); - - function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - - function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } - - function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; } - - function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } - - _omi2.default.makeHTML('Content', _index2.default); - _omi2.default.makeHTML('Sidebar', _index4.default); - _omi2.default.makeHTML('Head', _index6.default); - _omi2.default.makeHTML('Pager', _index8.default); - - var Frame = function (_Omi$Component) { - _inherits(Frame, _Omi$Component); - - function Frame(data) { - _classCallCheck(this, Frame); - - return _possibleConstructorReturn(this, (Frame.__proto__ || Object.getPrototypeOf(Frame)).call(this, data)); - } - - _createClass(Frame, [{ - key: 'install', - value: function install() { - var _this2 = this; - - this.setViewport(); - window.onresize = function () { - if (window.innerWidth < 768) { - _this2.refs.main.style.width = '100%'; - } else { - _this2.refs.main.style.width = window.innerWidth - 220 + 'px'; - } - }; - } - }, { - key: 'setViewport', - value: function setViewport() { - if (window.innerWidth < 768) { - this.data.width = '100%'; - } else { - this.data.width = window.innerWidth - 220 + 'px'; - } - } - }, { - key: 'style', - value: function style() { - return '\n \n '; - } - }, { - key: 'render', - value: function render() { - return '
\n \n
\n \n \n
\n \n
'; - } - }]); - - return Frame; - }(_omi2.default.Component); - - exports.default = Frame; - -/***/ }, -/* 2 */, -/* 3 */ -/***/ function(module, exports, __webpack_require__) { - - 'use strict'; - - Object.defineProperty(exports, "__esModule", { - value: true - }); - - var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); - - var _omi = __webpack_require__(2); - - var _omi2 = _interopRequireDefault(_omi); - - var _config = __webpack_require__(4); - - var _config2 = _interopRequireDefault(_config); - - var _highlightLines = __webpack_require__(5); - - var _highlightLines2 = _interopRequireDefault(_highlightLines); - - function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - - function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } - - function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; } - - function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } - - var tpl = __webpack_require__(6); - var css = __webpack_require__(7); - - var Content = function (_Omi$Component) { - _inherits(Content, _Omi$Component); - - function Content(data) { - _classCallCheck(this, Content); - - data = Object.assign({ - lan: 'cn', - name: 'installation' - }, data); - - var _this = _possibleConstructorReturn(this, (Content.__proto__ || Object.getPrototypeOf(Content)).call(this, data)); - - _this.md = new Remarkable({ html: true }); - return _this; - } - - _createClass(Content, [{ - key: 'getMarkDown', - value: function getMarkDown(name, lan) { - return __webpack_require__(8)("./" + lan + "/" + name + ".md"); - } - }, { - key: 'installed', - value: function installed() { - this.initCodeStyle(); - } - }, { - key: 'afterUpdate', - value: function afterUpdate() { - this.initCodeStyle(); - } - }, { - key: 'initCodeStyle', - value: function initCodeStyle() { - var _this2 = this; - - var codes = _omi2.default.$$("code"); - var codeHlNumArr = []; - codes.forEach(function (code) { - hljs.highlightBlock(code); - var arr = code.className.match(/{\S*}/); - var hllNums = null; - if (arr) { - var numArr = arr[0].replace(/[{|}]/g, '').split(','); - hllNums = _this2._arrToNumber(numArr); - } - codeHlNumArr.push(hllNums); - }); - - (0, _highlightLines2.default)(); - - codes.forEach(function (code, index) { - _this2._hll(code, codeHlNumArr[index]); - }); - } - }, { - key: '_arrToNumber', - value: function _arrToNumber(numArr) { - var arr = []; - numArr.forEach(function (item) { - if (item.indexOf('-') !== -1) { - var tempArr = item.split('-'); - var begin = Number(tempArr[0]); - var end = Number(tempArr[1]); - for (var i = begin; i < end + 1; i++) { - arr.push(i); - } - } else { - arr.push(Number(item)); - } - }); - return arr; - } - }, { - key: '_hll', - value: function _hll(code, hllNums) { - var spans = _omi2.default.$$('.line', code); - hllNums && hllNums.forEach(function (num) { - spans[num] && spans[num].classList.add('highlight'); - }); - } - }, { - key: 'render', - value: function render() { - this.data.html = this.md.render(this.getMarkDown(this.data.name, this.data.lan)); - return tpl; - } - }, { - key: 'style', - value: function style() { - return css; - } - }]); - - return Content; - }(_omi2.default.Component); - - exports.default = Content; - -/***/ }, -/* 4 */ -/***/ function(module, exports) { - - 'use strict'; - - Object.defineProperty(exports, "__esModule", { - value: true - }); - var config = { - menus: { - cn: [{ - active: true, - title: '快速开始', - currentIndex: 0, - list: [{ 'name': '安装', md: 'installation' }, { 'name': 'Hello World', md: 'hello_world' }, { 'name': '组件', md: 'components' }, { 'name': '组件通讯', md: 'communication' }, { 'name': '生命周期', md: 'lifecycle' }, { 'name': '事件处理', md: 'events' }, { 'name': '条件判断', md: 'condition' }, { 'name': '循环遍历', md: 'loop' }, { 'name': 'Store体系', md: 'store' }, { 'name': '表单', md: 'form' }, { 'name': '继承', md: 'inherit' }, { 'name': '模板切换', md: 'template' }, { 'name': '获取DOM节点', md: 'get_dom' }, { 'name': '插件体系', md: 'plugin' }, { 'name': 'Omi的理念', md: 'thinking_in_omi' }] - }], - en: [{ - title: 'QUICK START', - active: true, - currentIndex: 0, - list: [{ 'name': 'Installation', md: 'installation' }, { 'name': 'Hello World', md: 'hello_world' }, { 'name': 'Components', md: 'components' }, { 'name': 'Communication', md: 'communication' }, { 'name': 'Lifecycle', md: 'lifecycle' }, { 'name': 'Handling Events', md: 'events' }, { 'name': 'Conditional Rendering', md: 'condition' }, { 'name': 'Loop', md: 'loop' }, { 'name': 'Forms', md: 'form' }, { 'name': 'Inheritance', md: 'inherit' }, { 'name': 'Templates', md: 'template' }, { 'name': 'Get DOM', md: 'get_dom' }, { 'name': 'Plugin', md: 'plugin' }, { 'name': 'Thinking in Omi', md: 'thinking_in_omi' }] - }] - } - }; - - exports.default = config; - -/***/ }, -/* 5 */ -/***/ function(module, exports) { - - 'use strict'; - - Object.defineProperty(exports, "__esModule", { - value: true - }); - - // Iterates through `array`, running `callback` for each `array` element. - function forEach(array, callback) { - var i = -1, - length = array ? array.length : 0; - while (++i < length) { - callback(array[i]); - } - } - - function indexOf(array, elem) { - var i = -1, - length = array ? array.length : 0; - while (++i < length) { - if (array[i] === elem) { - return i; - } - } - } - function highlightLines() { - // TODO: mark as parsed. - forEach(document.querySelectorAll('pre code'), function (element) { - // Trim whitespace if the `data-trim` attribute is present. - if (element.hasAttribute('data-trim') && typeof element.innerHTML.trim == 'function') { - element.innerHTML = element.innerHTML.trim(); - } - - // Highlight code using highlight.js. - hljs.highlightBlock(element); - - // Split highlighted code into lines. - var openTags = [], - reHtmlTag = /<(\/?)span(?:\s+(?:class=(['"])hljs-.*?\2)?\s*|\s*)>/g; - element.innerHTML = element.innerHTML.replace(/(.*?)\r?\n/g, function (_, string) { - if (!string) { - return ' '; - } - var openTag, stringPrepend; - // Re-open all tags that were previously closed. - if (openTags.length) { - stringPrepend = openTags.join(''); - } - // Match all HTML `` tags. - reHtmlTag.lastIndex = 0; - while (openTag = reHtmlTag.exec(string)) { - // If it is a closing tag, remove the opening tag from the list. - if (openTag[1]) { - openTags.pop(); - } - // Otherwise if it is an opening tag, push it to the list. - else { - openTags.push(openTag[0]); - } - } - // Close all opened tags, so that strings can be wrapped with `span.line`. - if (openTags.length) { - string += Array(openTags.length + 1).join(''); - } - if (stringPrepend) { - string = stringPrepend + string; - } - return '' + string + ''; - }); - }); - } - - exports.default = highlightLines; - -/***/ }, -/* 6 */ -/***/ function(module, exports) { - - module.exports = "
{{{html}}}
" - -/***/ }, -/* 7 */ -/***/ function(module, exports) { - - module.exports = ".content{ width: 80%;}h3{ color:#444444;}pre{ border: 1px solid #eee; width: 100%;}li{ text-indent: 20px; list-style:disc inside ;}@media only screen and (max-width: 768px) { .content{ width: 100%; }}" - -/***/ }, -/* 8 */ -/***/ function(module, exports, __webpack_require__) { - - var map = { - "./cn/communication.md": 9, - "./cn/components.md": 10, - "./cn/condition.md": 11, - "./cn/events.md": 12, - "./cn/form.md": 13, - "./cn/get_dom.md": 14, - "./cn/hello_world.md": 15, - "./cn/inherit.md": 16, - "./cn/installation.md": 17, - "./cn/lifecycle.md": 18, - "./cn/loop.md": 19, - "./cn/plugin.md": 20, - "./cn/store.md": 21, - "./cn/template.md": 22, - "./cn/thinking_in_omi.md": 23, - "./en/communication.md": 24, - "./en/components.md": 25, - "./en/condition.md": 26, - "./en/events.md": 27, - "./en/form.md": 28, - "./en/get_dom.md": 29, - "./en/hello_world.md": 30, - "./en/inherit.md": 31, - "./en/installation.md": 32, - "./en/lifecycle.md": 33, - "./en/loop.md": 34, - "./en/plugin.md": 35, - "./en/template.md": 36, - "./en/thinking_in_omi.md": 37 - }; - function webpackContext(req) { - return __webpack_require__(webpackContextResolve(req)); - }; - function webpackContextResolve(req) { - return map[req] || (function() { throw new Error("Cannot find module '" + req + "'.") }()); - }; - webpackContext.keys = function webpackContextKeys() { - return Object.keys(map); - }; - webpackContext.resolve = webpackContextResolve; - module.exports = webpackContext; - webpackContext.id = 8; - - -/***/ }, -/* 9 */ -/***/ function(module, exports) { - - module.exports = "## 组件通讯\r\n\r\n[Omi框架](https://github.com/AlloyTeam/omi)组建间的通讯非常遍历灵活,因为有许多可选方案进行通讯:\r\n\r\n* 通过在组件上声明 data-* 传递给子节点 \r\n* 通过在组件上声明 data 传递给子节点 (支持复杂数据类型的映射)\r\n* 声明 group-data 传递(支持复杂数据类型的映射)\r\n* 完全面向对象,可以非常容易地拿到对象的实例,之后可以设置实例属性和调用实例的方法\r\n\r\n所以通讯变得畅通无阻,下面一一来举例说明。\r\n\r\n### data-*通讯 \r\n\r\n```js {36}\r\nclass Hello extends Omi.Component {\r\n constructor(data) {\r\n super(data);\r\n }\r\n \r\n style () {\r\n return `\r\n h1{\r\n \tcursor:pointer;\r\n }\r\n `;\r\n }\r\n \r\n handleClick(target, evt){\r\n alert(target.innerHTML);\r\n }\r\n \r\n render() {\r\n return `\r\n
\r\n \t

Hello ,{{name}}!

\r\n
\r\n \t\t`;\r\n }\r\n}\r\n\r\nOmi.makeHTML('Hello', Hello);\r\n\r\nclass App extends Omi.Component {\r\n constructor(data) {\r\n super(data);\r\n }\r\n \r\n render() {\r\n return `\r\n
\r\n \r\n
\r\n `;\r\n }\r\n}\r\n\r\nOmi.render(new App(),\"#container\");\r\n```\r\n\r\n一般data-*用来传递值类型,如string、number。值得注意的是,通过data-*接收到的数据类型都是string,需要自行转成number类型。\r\n通常情况下,data-*能满足我们的要求,但是遇到复杂的数据类型是没有办法通过大量data-*去表达,所以可以通过data通讯,请往下看。\r\n\r\n### data通讯 \r\n\r\n如上面代码所示,通过 data-name=\"Omi\"可以把name传递给子组件。下面的代码也可以达到同样的效果。\r\n\r\n```js {4,10}\r\n...\r\nclass App extends Omi.Component {\r\n constructor(data) {\r\n super(data);\r\n this.helloData = { name : 'Omi' };\r\n }\r\n \r\n render() {\r\n return `\r\n
\r\n \r\n
\r\n `;\r\n }\r\n}\r\n\r\nOmi.render(new App(),\"#container\");\r\n```\r\n\r\n使用data声明,会去组件的instance(也就是this)下找对应的属性,this下可以挂载任意复杂的对象。所以这也就突破了data-*的局限性。\r\n\r\n如果instance下面的某个属性下面的某个属性下面的某个数组的第一个元素的某个属性要作为data传递Hello怎么办?\r\n没关系,data声明是支持复杂类型的,使用方式如下:\r\n\r\n```js\r\n...\r\nclass App extends Omi.Component {\r\n constructor(data) {\r\n super(data);\r\n this.complexData ={\r\n a:{\r\n b:{\r\n c:[\r\n {\r\n e:[{\r\n name:'ComplexData Support1'\r\n },{\r\n name:'ComplexData Support2'\r\n }]\r\n },\r\n {\r\n name: 'ComplexData Support3'\r\n }\r\n ]\r\n }\r\n }\r\n };\r\n }\r\n \r\n render() {\r\n return `\r\n
\r\n \r\n
\r\n `;\r\n }\r\n}\r\n...\r\n```\r\n\r\n点击这里→data映射复杂数据\r\n\r\n### group-data通讯\r\n\r\ngroup-data专门是为了给一组组件批量传递data而设计。\r\n\r\n```js\r\nimport Hello from './hello.js';\r\n\r\n\r\nOmi.makeHTML('Hello', Hello);\r\n\r\nclass App extends Omi.Component {\r\n constructor(data) {\r\n super(data);\r\n this.testData = [{name: 'Omi'}, {name: 'dntzhang'}, {name: 'AlloyTeam'}];\r\n }\r\n\r\n render() {\r\n return `\r\n
\r\n \r\n \r\n \r\n
\r\n `;\r\n\r\n }\r\n}\r\n\r\nOmi.render(new App(),\"#container\");\r\n```\r\n\r\n只需要在声明的子组件上标记group-data,就会去当前组件的instance(也就是this)下面找对应的属性,然后根据当前的位置,和对应数组的位置会一一对应起来。\r\n\r\n运行结果如下:\r\n![](http://images2015.cnblogs.com/blog/105416/201702/105416-20170216110701535-1698390390.png)\r\n\r\n点击这里→group-data\r\n\r\n同样group-data支持复杂数据类型的映射,需要注意的是,group-data映射的终点必须是一个数组:\r\n\r\n```js\r\nimport Hello from './hello.js';\r\n\r\n\r\nOmi.makeHTML('Hello', Hello);\r\n\r\nclass App extends Omi.Component {\r\n constructor(data) {\r\n super(data);\r\n this.complexData ={\r\n a:{\r\n b:{\r\n c:[\r\n {\r\n e:[{\r\n name:'ComplexData Support1'\r\n },{\r\n name:'ComplexData Support2'\r\n }]\r\n },\r\n {\r\n name: 'ComplexData Support3'\r\n }\r\n ]\r\n }\r\n }\r\n };\r\n }\r\n\r\n render() {\r\n return `\r\n
\r\n \r\n \r\n
\r\n `;\r\n\r\n }\r\n}\r\n\r\nOmi.render(new App(),\"#container\");\r\n```\r\n\r\n点击这里→group-data映射复杂数据\r\n\r\n### 通过对象实例\r\n\r\n```js {7}\r\n...\r\nclass App extends Omi.Component {\r\n constructor(data) {\r\n super(data);\r\n }\r\n \r\n installed(){\r\n this.hello.data.name = \"Omi\";\r\n this.update()\r\n }\r\n \r\n render() {\r\n return `\r\n
\r\n \r\n
\r\n `;\r\n }\r\n}\r\n\r\nOmi.render(new App(),\"#container\");\r\n```\r\n\r\n### 通过omi-id\r\n\r\n```js {7,14}\r\n...\r\nclass App extends Omi.Component {\r\n constructor(data) {\r\n super(data);\r\n }\r\n \r\n installed(){\r\n Omi.get(\"hello\").data.name = \"Omi\";\r\n this.update()\r\n }\r\n \r\n render() {\r\n return `\r\n
\r\n \r\n
\r\n `;\r\n }\r\n}\r\n\r\nOmi.render(new App(),\"#container\");\r\n```\r\n\r\n通过在组件上声明omi-id,在程序任何地方拿到该对象的实例。这个可以算是跨任意组件通讯神器。\r\n\r\n" - -/***/ }, -/* 10 */ -/***/ function(module, exports) { - - module.exports = "## 组件\r\n\r\n[Omi框架](https://github.com/AlloyTeam/omi)完全基于组件体系设计,我们希望开发者可以像搭积木一样制作Web程序,一切皆是组件,组件也可以嵌套子组件形成新的组件,新的组件又可以当作子组件嵌套至任意组件形成新的组件...\r\n\r\n![](http://images2015.cnblogs.com/blog/105416/201702/105416-20170210093427338-1536910080.png)\r\n\r\n## 简单组件\r\n\r\n这里使用Todo的例子来讲解Omi组件体系的使用。\r\n\r\n```js\r\nclass Todo extends Omi.Component {\r\n constructor(data) {\r\n super(data);\r\n }\r\n \r\n add (evt) {\r\n evt.preventDefault();\r\n this.data.items.push(this.data.text);\r\n this.data.text = '';\r\n this.update();\r\n }\r\n\r\n style () {\r\n return `\r\n h3 { color:red; }\r\n button{ color:green;}\r\n `;\r\n }\r\n\r\n handleChange(target){\r\n this.data.text = target.value;\r\n }\r\n\r\n render () {\r\n return `
\r\n

TODO

\r\n \r\n
\r\n \r\n \r\n
\r\n
`;\r\n }\r\n}\r\n\r\nOmi.render(new Todo({ items: [] ,text : '' }),\"body\");\r\n```\r\n\r\n组件生成的HTML最终会插入到body中。上面的例子展示了Omi的部分特性:\r\n\r\n- data传递: new Todo(data,..)的data可以直接提供给render方法里的模板\r\n- 局部CSS: h3只对render里的h3生效,不会污染外面的h3;button也是同样的\r\n- 声明式事件绑定: onchange调用的就是组件内的handleChange,this可以拿到当然的DOM元素,还可以拿到当前的event\r\n- 需要手动调用update方法才能更新组件\r\n\r\n这里需要特别强调的是,为了更加的自由和灵活度。Omi没有内置数据变更的自动更新,需要开发者自己调用update方法。\r\n\r\n点击这里→在线试试\r\n\r\n## 组件嵌套\r\n\r\n如果页面超级简单的话,可以没有组件嵌套。但是绝大部分Web网页或者Web应用,需要嵌套定义的组件来完成所有的功能和展示。比如上面的Todo,我们也是可以抽取出List。\r\n这样让程序易维护、可扩展、方便复用。如,我们抽取出List:\r\n\r\n```js\r\nclass List extends Omi.Component {\r\n constructor(data) {\r\n super(data);\r\n }\r\n\r\n render () {\r\n return ``;\r\n }\r\n}\r\n```\r\n\r\n怎么使用这个List?我们需要使用Omi.makeHTML把List制作成可以声明式的标签,在render方法中就能直接使用该标签。如下所示:\r\n\r\n```js\r\nimport List from './list.js';\r\n\r\nOmi.makeHTML('List', List);\r\n\r\nclass Todo extends Omi.Component {\r\n constructor(data) {\r\n super(data);\r\n this.data.length = this.data.items.length;\r\n this.listData = { items : this.data.items };\r\n }\r\n\r\n add (evt) {\r\n evt.preventDefault();\r\n this.list.data.items.push(this.data.text);\r\n this.data.length = this.list.data.items.length;\r\n this.data.text = '';\r\n this.update();\r\n }\r\n\r\n style () {\r\n return `\r\n h3 { color:red; }\r\n button{ color:green;}\r\n `;\r\n }\r\n\r\n handleChange(target){\r\n this.data.text = target.value;\r\n }\r\n\r\n render () {\r\n return `
\r\n

TODO

\r\n \r\n
\r\n \r\n \r\n
\r\n
`;\r\n }\r\n}\r\n```\r\n\r\n* 第3行,通过makeHTML方法把组件制作成可以在render中使用的标签。当然Omi.makeHTML('List', List);也可以写在List组件的代码下面。\r\n* 第9行,在父组件上定义listData属性用来传递给子组件。\r\n* 第34行,在render方法中使用List组件。其中name方法可以让你在代码里通过this快速方法到该组件的实例。data=\"listData\"可以让你把this.listData传递给子组件。\r\n\r\n需要注意的是,父组件的this.listData会被通过Object.assign浅拷贝到子组件。\r\n这样做的目的主要是希望以后DOM的变更都尽量修改子组件自身的data,然后再调用其update方法,而不是去更改父组件的listData。\r\n\r\n关于Omi组件通讯其实有4种方案,这个后续教程会专门来讲。\r\n\r\n点击这里→在线试试\r\n" - -/***/ }, -/* 11 */ -/***/ function(module, exports) { - - module.exports = "## 条件判断\r\n\r\n我们经常需要根据不同的状态呈现不同的界面,比如有的用户是vip要显示vip的Logo。Omi有许多种方式满足你的要求。\r\n\r\n### 方式一\r\n\r\n```js\r\nclass ConditionTest extends Omi.Component {\r\n constructor(data) {\r\n super(data);\r\n }\r\n\r\n render () {\r\n return `{{#isVip}}\r\n
you are VIP.
\r\n {{/isVip}}\r\n {{^isVip}}\r\n
you are not VIP.
\r\n {{/isVip}}`;\r\n }\r\n}\r\n```\r\n\r\n上面完全使用mustachejs的条件判断的语法。当然Omi不强制你使用mustachejs。你可以是omi.lite.js,然后重写Omi.template方法去使用任意你喜爱的模板引擎。\r\n\r\n### 方式二\r\n\r\n```js\r\nclass ConditionTest extends Omi.Component {\r\n constructor(data) {\r\n super(data);\r\n }\r\n\r\n render () {\r\n if(this.data.isVip){\r\n return '
you are VIP.
';\r\n }else{\r\n return '
you are not VIP.
';\r\n }\r\n }\r\n}\r\n```\r\n\r\nrender就是提供了很好的可编程性,里面可以写任意js逻辑代码。对了,差点忘了,style方法里面也可以写js逻辑的。\r\n\r\n```js\r\nclass ConditionTest extends Omi.Component {\r\n constructor(data) {\r\n super(data);\r\n }\r\n\r\n style (){\r\n if(this.data.isVip){\r\n return 'div{ color : red; }';\r\n }else{\r\n return 'div{ color : green; }';\r\n }\r\n }\r\n\r\n render () {\r\n if(this.data.isVip){\r\n return '
you are VIP.
';\r\n }else{\r\n return '
you are not VIP.
';\r\n }\r\n }\r\n}\r\n```\r\n\r\n### 方式三\r\n\r\n```js\r\nclass ConditionTest extends Omi.Component {\r\n constructor(data) {\r\n super(data);\r\n }\r\n\r\n render() {\r\n return `\r\n ${this.data.isVip\r\n ?\"
you are VIP.
\"\r\n :\"
you are not VIP.
\"\r\n \t\t}\r\n `;\r\n }\r\n}\r\n```\r\n\r\n当然可以使用${ }里面写javascript代码进行输出。" - -/***/ }, -/* 12 */ -/***/ function(module, exports) { - - module.exports = "## 事件处理\r\n\r\nOmi的事件分内置事件和自定义事件。在内置事件处理方面巧妙地利用了浏览器自身的管线机制,可以通过event和this轻松拿到事件实例和触发该事件的元素。\r\n\r\n### 内置事件\r\n\r\n什么算内置事件?只要下面正则能匹配到就算内置事件。\r\n\r\n```js\r\non(abort|blur|cancel|canplay|canplaythrough|change|click|close|contextmenu|cuechange|dblclick|drag|dragend|dragenter|dragleave|dragover|dragstart|drop|durationchange|emptied|ended|error|focus|input|invalid|keydown|keypress|keyup|load|loadeddata|loadedmetadata|loadstart|mousedown|mouseenter|mouseleave|mousemove|mouseout|mouseover|mouseup|mousewheel|pause|play|playing|progress|ratechange|reset|resize|scroll|seeked|seeking|select|show|stalled|submit|suspend|timeupdate|toggle|volumechange|waiting|autocomplete|autocompleteerror|beforecopy|beforecut|beforepaste|copy|cut|paste|search|selectstart|wheel|webkitfullscreenchange|webkitfullscreenerror|touchstart|touchmove|touchend|touchcancel|pointerdown|pointerup|pointercancel|pointermove|pointerover|pointerout|pointerenter|pointerleave)\r\n```\r\n\r\n内置事件怎么绑定?如下所示:\r\n\r\n```js\r\nclass EventTest extends Omi.Component {\r\n constructor(data) {\r\n super(data);\r\n }\r\n\r\n handleClick(dom, evt){\r\n alert(dom.innerHTML);\r\n }\r\n\r\n render () {\r\n return `
Hello, Omi!
`;\r\n }\r\n}\r\n```\r\n\r\n### 自定义事件\r\n\r\n开发者自己定义的组件的事件,称为自定义事件,自定义事件必须以on开头,即onXXXX的格式,不然Omi识别不到。这里拿分页作为例子:\r\n\r\n```js\r\nimport Omi from '../../src/index.js';\r\nimport Pagination from './pagination.js';\r\nimport Content from './content.js';\r\n\r\nOmi.makeHTML('Pagination', Pagination);\r\nOmi.makeHTML('Content', Content);\r\n\r\nclass Main extends Omi.Component {\r\n constructor(data) {\r\n super(data);\r\n }\r\n\r\n installed(){\r\n this.content.goto(this.pagination.data.currentPage+1);\r\n }\r\n \r\n handlePageChange(index){\r\n this.content.goto(index+1);\r\n }\r\n\r\n render () {\r\n return `
\r\n

Pagination Example

\r\n \r\n \r\n
`;\r\n }\r\n}\r\n\r\nOmi.render( new Main(),'body');\r\n```\r\n\r\n如上面的onPageChange就是自定义事件,触发会执行handlePageChange。onPageChange方法是在Pagination中执行:\r\n\r\n```js\r\nimport Omi from '../../src/index.js';\r\n\r\nclass Pagination extends Omi.Component {\r\n ...\r\n ...\r\n ...\r\n linkTo: \"#\",\r\n prevText: \"Prev\",\r\n nextText: \"Next\",\r\n ellipseText: \"...\",\r\n prevShow: true,\r\n nextShow: true,\r\n onPageChange: function () { return false; }\r\n }, this.data);\r\n\r\n this.pageNum = Math.ceil(this.data.total / this.data.pageSize);\r\n }\r\n \r\n goto (index,evt) {\r\n evt.preventDefault();\r\n this.data.currentPage=index;\r\n this.update();\r\n this.data.onPageChange(index);\r\n }\r\n ...\r\n ...\r\n ...\r\n}\r\n```\r\n\r\n这里取了Pagination组件的部分代码。高亮的就是执行onPageChange的地方。\r\n\r\n### 相关地址\r\n\r\n* [演示地址](http://alloyteam.github.io/omi/example/pagination/)\r\n* [源码地址](https://github.com/AlloyTeam/omi/tree/master/example/pagination)\r\n" - -/***/ }, -/* 13 */ -/***/ function(module, exports) { - - module.exports = "## 表单\r\n\r\nOmi让一些表单操控起来更加方便,特别是select!\r\n\r\n### select标签\r\n\r\n以前,我们需要像如下的方式选中一个选项:\r\n\r\n```html\r\n\r\n```\r\n\r\n第三个option由于加上了selected,所有会被选中。这样带来的问题就是,开发者写的程序可能要操遍历每个option。而使用Omi,你只需要这样子:\r\n\r\n```html\r\n\r\n```\r\n\r\n这样就能达到同样的效果。比如你想选择第一项:\r\n\r\n```html\r\n\r\n```\r\n\r\n是不是非常方便?\r\n\r\n### 举个例子\r\n\r\n```js\r\nclass FormTest extends Omi.Component {\r\n constructor(data) {\r\n super(data);\r\n \r\n }\r\n\r\n handleChange(target){\r\n console.log(target.value)\r\n this.data.value = target.value;\r\n }\r\n\r\n handleSubmit(evt) {\r\n alert('Your favorite flavor is: ' + this.data.value);\r\n evt.preventDefault();\r\n }\r\n \r\n render () {\r\n return `\r\n
\r\n \r\n \r\n
`;\r\n }\r\n}\r\n\r\nOmi.render(new FormTest({ value: 'mango' }),'#container');\r\n```\r\n\r\n点击这里→在线试试" - -/***/ }, -/* 14 */ -/***/ function(module, exports) { - - module.exports = "## 获取DOM节点\r\n\r\n虽然绝大部分情况下,开发者不需要去查找获取DOM,但是还是有需要获取DOM的场景,所以Omi提供了方便获取DOM节点的方式。\r\n\r\n### ref和refs\r\n\r\n```js\r\nclass Hello extends Omi.Component {\r\n constructor(data) {\r\n super(data);\r\n }\r\n \r\n style () {\r\n return `\r\n h1{\r\n cursor:pointer;\r\n }\r\n `;\r\n }\r\n \r\n handleClick(){\r\n alert(this.refs.abc.innerHTML);\r\n }\r\n \r\n render() {\r\n return `\r\n
\r\n

Hello ,{{name}}!

\r\n
\r\n `;\r\n }\r\n}\r\n\r\nOmi.render(new Hello({ name : \"Omi\" }),\"#container\");\r\n```\r\n\r\n可以看到通过在HTML中标记ref为abc,那么就通过this.refs.abc访问到该DOM节点。\r\n\r\n点击这里→在线试试" - -/***/ }, -/* 15 */ -/***/ function(module, exports) { - - module.exports = "## Hello World\r\n\r\n你可以使用ES6+或者ES5的方式编写Omi程序来搭建你的Web程序。\r\n\r\n### Hello World with ES6+\r\n\r\n你可以使用 [webpack](https://webpack.github.io/) 打包工具,webpack会把你的模块代码打成一个很小的包,优化加载时间。使用[babel](http://babeljs.io/),让你立刻马上使用ES6+来编写你的web程序。你只需要在webpack配置的module设置好[babel-loader](https://github.com/babel/babel-loader)便可。\r\n\r\n一个Omi的简短的例子如下所示:\r\n\r\n```js\r\nimport Omi from './omi.js';\r\n\r\nclass Hello extends Omi.Component {\r\n constructor(data) {\r\n super(data);\r\n }\r\n \r\n style () {\r\n //注意,return中的包裹是可选的。主要是为了识别为JSX文件可以有CSS高亮。\r\n return `\r\n \r\n `;\r\n }\r\n \r\n handleClick(target, evt){\r\n alert(target.innerHTML);\r\n }\r\n \r\n render() {\r\n return `\r\n
\r\n

Hello ,{{name}}!

\r\n
\r\n `;\r\n }\r\n}\r\n\r\nOmi.render(new Hello({ name : \"Omi\" }),\"#container\");\r\n```\r\n\r\n组件生成的HTML最终会插入到#container中。上面的例子展示了Omi的部分特性:\r\n\r\n- data传递: new Hello(data,..)的data可以直接提供给render方法里的模板\r\n- 局部CSS: h1只对render里的h1生效,不会污染外面的h1\r\n- 声明式事件绑定: onclick调用的就是组件内的handleClick,this可以拿到当前的DOM元素,还可以拿到当前的event\r\n\r\n点击这里→在线试试\r\n\r\n你可以使用Omi.makeHTML来生成组件标签用于嵌套。\r\n```js\r\n Omi.makeHTML('Hello', Hello);\r\n```\r\n那么你就在其他组件中使用,如\r\n```js\r\n ...\r\n render() {\r\n return `\r\n
\r\n
Test
\r\n \r\n
\r\n `;\r\n }\r\n ...\r\n```\r\n\r\n点击这里→在线试试\r\n\r\n### Hello World with ES5\r\n\r\n当然Omi没有抛弃ES5的用户。你可以使用ES5的方式编写Omi。如,在你的HTML中引用omi.js:\r\n\r\n```html\r\n\r\n```\r\n\r\n然后:\r\n\r\n```js\r\nvar Hello = Omi.create(\"Hello\", {\r\n style: function () {\r\n return \"h1{ cursor:pointer }\";\r\n },\r\n \r\n handleClick: function (dom) {\r\n alert(dom.innerHTML)\r\n },\r\n \r\n render: function () {\r\n return '
\\\r\n

\\\r\n Hello ,{{name}}!\\\r\n

\\\r\n
'\r\n }\r\n});\r\n\r\nvar Test = Omi.create(\"Test\", {\r\n render: function () {\r\n return '
\\\r\n
Test
\\\r\n \\\r\n
'\r\n }\r\n});\r\n\r\nOmi.render(new Test(),'#container');\r\n```\r\n当然除了在HTML引入脚本,你还可以使用AMD、CMD或者CommonJS的方式引入Omi,这里就不再一一列举。\r\n\r\n需要注意的是,Omi.create的第一个参数Hello是用来生成Tag Name的。你可以在其他地方嵌入你的组件。如:\r\n\r\n```js\r\n ...\r\n render:function() {\r\n return '
\\\r\n \\\r\n
Test XXXX
\\\r\n \\\r\n
';\r\n }\r\n ...\r\n```\r\n\r\n点击这里→在线试试\r\n" - -/***/ }, -/* 16 */ -/***/ function(module, exports) { - - module.exports = "## 继承\r\n\r\n通过继承机制,可以利用已有的数据类型来定义新的数据类型。所定义的新的数据类型不仅拥有新定义的成员,而且还同时拥有旧的成员。我们称已存在的用来派生新类的类为基类,又称为父类。由已存在的类派生出的新类称为派生类,又称为子类。\r\n\r\n### 举个例子\r\n\r\n```js\r\nclass Hello extends Omi.Component {\r\n constructor(data) {\r\n super(data);\r\n }\r\n \r\n style () {\r\n return `\r\n div{\r\n cursor:pointer;\r\n }\r\n `;\r\n }\r\n \r\n handleClick(target, evt){\r\n alert(target.innerHTML);\r\n }\r\n \r\n render() {\r\n return '
Hello {{name}}!
'\r\n }\r\n}\r\n\r\nclass SubHello extends Hello {\r\n constructor(data) {\r\n super(data);\r\n }\r\n}\r\n\r\nOmi.render(new SubHello({ name : 'Omi' }),'#container');\r\n```\r\n\r\n点击这里→在线试试\r\n\r\n### ES5下的继承\r\n\r\n```js\r\nvar Hello = Omi.create(\"Hello\",{\r\n render:function(){\r\n return '
Hello {{name}}!
'\r\n }\r\n})\r\n\r\nvar SubHello = Omi.create(\"SubHello\",Hello,{ });\r\n\r\n\r\nOmi.render(new SubHello({ name : 'Omi' }),'#container');\r\n```\r\n\r\n点击这里→在线试试" - -/***/ }, -/* 17 */ -/***/ function(module, exports) { - - module.exports = "## 安装\n\n[Omi](https://github.com/AlloyTeam/omi)(读音 / [ˈomɪ] /, 汉字类似于 欧米) 是一款用于创建用户界面的组件化框架,开放并且现代,故得名:Omi。\n\n### 安装 Omi\n\n我们推荐使用 [npm](https://www.npmjs.com/) 来管理你的前端依赖.\n\n通过npm安装Omi,你只需要执行下面的命令:\n\n``` js\n$ npm install omi\n```\n\n## omi-cli\n\n你也可以通过omi-cli去初始化你的项目:\n\n``` js\n$ npm install omi-cli -g //安装cli\n$ omi init your_project_name //初始化项目,你也可以在一个空的文件夹下执行 omi init\n$ cd your_project_name //如果你是在空文件夹下执行的 omi init。请无视这条命令\n$ npm run dev //开发\n$ npm run dist //部署发布\n```" - -/***/ }, -/* 18 */ -/***/ function(module, exports) { - - module.exports = "## 生命周期\r\n\r\n|name |avatars |company | \r\n|---|---|---|\r\n| constructor | 构造函数 | new的时候 |\r\n| install | 初始化安装,这可以拿到用户传进的data进行处理 | 实例化 |\r\n| installed | 安装完成,HTML已经插入页面之后执行 | 实例化 |\r\n| uninstall | 卸载组件。执行remove方法会触发该事件 | 销毁时 |\r\n| beforeUpdate | 更新前 | 存在期 |\r\n| afterUpdate | 更新后 | 存在期 |\r\n\r\n## 示意图\r\n\r\n![lc](http://images2015.cnblogs.com/blog/105416/201703/105416-20170322083548924-1871234168.jpg)\r\n \r\n### 举个例子\r\n\r\n```js\r\nclass Timer extends Omi.Component {\r\n constructor(data) {\r\n super(data);\r\n }\r\n\r\n install () {\r\n this.data = {secondsElapsed: 0};\r\n }\r\n\r\n tick() {\r\n this.data.secondsElapsed++;\r\n this.update();\r\n }\r\n\r\n installed(){\r\n this.interval = setInterval(() => this.tick(), 1000);\r\n }\r\n\r\n uninstall() {\r\n clearInterval(this.interval);\r\n }\r\n\r\n\r\n style () {\r\n return `\r\n .num { color:red; }\r\n `;\r\n }\r\n\r\n render () {\r\n return `
Seconds Elapsed: {{secondsElapsed}}
`;\r\n }\r\n}\r\n```\r\n\r\n点击这里→在线试试\r\n" - -/***/ }, -/* 19 */ -/***/ function(module, exports) { - - module.exports = "## 循环遍历\r\n\r\n下面介绍mustache.js的方式和javascript遍历的方式。\r\n\r\n### 方式一\r\n\r\n```js\r\nclass List extends Omi.Component {\r\n constructor(data) {\r\n super(data);\r\n }\r\n\r\n render () {\r\n return `
\r\n \r\n
`;\r\n }\r\n}\r\n\r\nOmi.render(new List({\r\n items: [\r\n {id: 1, text: 'Omi'},\r\n {id: 2, text: 'dntzhang'},\r\n {id: 3, text: 'AlloyTeam'}\r\n ]\r\n}),\"body\");\r\n```\r\n\r\nmustache.js更详细的循环遍历使用可看[https://github.com/janl/mustache.js#non-empty-lists](https://github.com/janl/mustache.js#non-empty-lists)。 比如还支持:\r\n\r\n* 如果items的每一项是字符串,可以直接**{{.}}**的方式来输出每一项\r\n* 循环的时候调用定义好的函数\r\n\r\n点击这里→在线试试\r\n\r\n### 方式二\r\n\r\n既然ES6+了,当然可以使用${ }以及Array的map方法: \r\n\r\n```js\r\nclass List extends Omi.Component {\r\n constructor(data) {\r\n super(data);\r\n }\r\n\r\n render() {\r\n return `
\r\n \r\n
`;\r\n }\r\n}\r\n\r\nOmi.render(new List({\r\n items: [\r\n {id: 1, text: 'Omi'},\r\n {id: 2, text: 'dntzhang'},\r\n {id: 3, text: 'AlloyTeam'}\r\n ]\r\n}),\"body\");\r\n```\r\n\r\n你将在页面看到如下效果:\r\n\r\n![pv](http://images2015.cnblogs.com/blog/105416/201701/105416-20170122095724129-2059595233.png)\r\n\r\n点击这里→在线试试\r\n\r\n如果想在循环里加些判断呢?比如需要把id为偶数的隐藏起来:\r\n\r\n```js\r\nrender() {\r\n return `
\r\n \r\n
`;\r\n}\r\n```\r\n\r\n所以模板字符串还是非常方便,随着ES继续发展下去,模板引擎估计会慢慢消失。所以omi提供了 omi.lite.js 版本不包含任何模板引擎。" - -/***/ }, -/* 20 */ -/***/ function(module, exports) { - - module.exports = "## 插件体系\r\n\r\n[Omi](https://github.com/AlloyTeam/omi)是Web组件化框架,怎么又来了个插件的概念?\r\n\r\n可以这么理解: Omi插件体系可以赋予dom元素一些能力,并且可以和组件的实例产生关联。\r\n\r\n### omi-drag\r\n\r\n且看这个例子:\r\n\r\n点击这里→在线试试\r\n\r\n```js\r\nimport OmiDrag from './omi-drag.js';\r\n\r\nOmiDrag.init();\r\n\r\nclass App extends Omi.Component {\r\n constructor(data) {\r\n super(data);\r\n }\r\n\r\n render() {\r\n return `\r\n
\r\n
Drag Me
\r\n
\r\n `;\r\n\r\n }\r\n\r\n style(){\r\n return `\r\n .test{\r\n width:100px;\r\n height:100px;\r\n color:white;\r\n line-height:90px;\r\n text-align:center;\r\n background-color:#00BFF3;\r\n }\r\n `\r\n }\r\n}\r\n\r\nOmi.render(new App(),\"#container\");\r\n```\r\n\r\n如上面的代码所示,通过在div上标记omi-drag,这个div就能够被用户使用鼠标拖拽。我们称omi-drag.js为omi插件。\r\n是不是非常方便?那么这个omi-drag是怎么实现的?\r\n\r\n## Omi.extendPlugin\r\n\r\n核心方法: Omi.extendPlugin( pluginName, handler )\r\n\r\n下面的代码就是展示了如何通过 Omi.extendPlugin 赋予dom拖拽的能力:\r\n\r\n```js\r\n;(function () {\r\n\r\n var OmiDrag = {};\r\n var Omi = typeof require === 'function'\r\n ? require('omi')\r\n : window.Omi;\r\n\r\n OmiDrag.init = function(){\r\n Omi.extendPlugin('omi-drag',function(dom, instance){\r\n dom.style.cursor='move';\r\n var isMouseDown = false,\r\n preX = null,\r\n preY = null,\r\n currentX = null,\r\n currentY = null,\r\n translateX = 0,\r\n translateY = 0;\r\n\r\n dom.addEventListener('mousedown',function(evt){\r\n isMouseDown = true;\r\n preX = evt.pageX;\r\n preY = evt.pageY;\r\n evt.stopPropagation();\r\n },false);\r\n\r\n window.addEventListener('mousemove',function(evt){\r\n if(isMouseDown){\r\n currentX = evt.pageX;\r\n currentY = evt.pageY;\r\n if(preX != null){\r\n translateX += currentX - preX;\r\n translateY += currentY - preY;\r\n dom.style.transform = 'translateX('+translateX+'px) translateY('+translateY+'px)';\r\n }\r\n preX = currentX;\r\n preY = currentY;\r\n evt.preventDefault();\r\n }\r\n },false);\r\n\r\n window.addEventListener('mouseup',function(){\r\n isMouseDown = false;\r\n preX = preY = currentX = currentY = null;\r\n },false);\r\n });\r\n }\r\n\r\n OmiDrag.destroy = function(){\r\n delete Omi.plugins['omi-drag'];\r\n };\r\n\r\n if (typeof exports == \"object\") {\r\n module.exports = OmiDrag;\r\n } else if (typeof define == \"function\" && define.amd) {\r\n define([], function(){ return OmiDrag });\r\n } else {\r\n window.OmiDrag = OmiDrag;\r\n }\r\n\r\n})();\r\n```\r\n\r\n方法: Omi.extendPlugin( pluginName, handler )\r\n\r\n其中pluginName为插件的名称\r\n其中handler为处理器。handler可以拿到标记了pluginName的dom以及dom所在的组件的实例,即 dom 和 instance。\r\n\r\n通过 Omi.extendPlugin,可以赋予dom元素一些能力,也可以和组件的实例(instance)产生关联。\r\n但是上面的例子没有和instance产生关联,我们接下来试试:\r\n\r\n## 关联instance\r\n\r\n我们想在组件里面能够监听到move并且执行回调。如下:\r\n\r\n```js\r\n...\r\n...\r\nmoveHandler(){\r\n console.log('moving');\r\n}\r\n\r\nrender() {\r\n return `\r\n
\r\n
Drag Me
\r\n
\r\n `;\r\n}\r\n...\r\n```\r\n\r\n主要被拖动过程中,moveHandler就不断地被执行。插件代码需要修改:\r\n\r\n```js\r\n...\r\nwindow.addEventListener('mousemove',function(evt){\r\n if(isMouseDown){\r\n currentX = evt.pageX;\r\n currentY = evt.pageY;\r\n if(preX != null){\r\n translateX += currentX - preX;\r\n translateY += currentY - preY;\r\n dom.style.transform = 'translateX('+translateX+'px) translateY('+translateY+'px)';\r\n }\r\n preX = currentX;\r\n preY = currentY;\r\n evt.preventDefault();\r\n instance.moveHandler(evt);\r\n }\r\n},false);\r\n```\r\n\r\n我们在里面增加了instance.moveHandler(evt);方法,用来执行组件实例上的moveHandler方法。\r\n这样的话:就是组件的实例(instance)产生关联。但是还是有问题?如果标记了多个omi-drag 就会有问题!如:\r\n\r\n```js\r\n...\r\nrender() {\r\n return `\r\n
\r\n
Drag Me
\r\n
Drag Me
\r\n
\r\n `;\r\n}\r\n...\r\n```\r\n\r\n通常我们系统每个omi-drag都能对应一个回调函数,如:\r\n\r\n```js\r\n...\r\n...\r\nmoveHandlerA(){\r\n console.log('moving');\r\n}\r\n\r\nmoveHandlerB(){\r\n console.log('moving');\r\n}\r\n\r\nrender() {\r\n return `\r\n
\r\n
Drag Me A
\r\n
Drag Me B
\r\n
\r\n `;\r\n}\r\n...\r\n```\r\n\r\n怎么办?怎么实现?有办法!通过dom传递数据给插件。\r\n\r\n## 传递数据\r\n\r\n先来看最后实现的效果:\r\n\r\n```js\r\n...\r\n...\r\nmoveHandlerA(){\r\n console.log('moving');\r\n}\r\n\r\nmoveHandlerB(){\r\n console.log('moving');\r\n}\r\n\r\nrender() {\r\n return `\r\n
\r\n
Drag Me A
\r\n
Drag Me B
\r\n
\r\n `;\r\n}\r\n...\r\n```\r\n\r\nomi-drag修改的地方:\r\n\r\n```js\r\n...\r\nvar handlerName = dom.getAttribute('dragMove');\r\n\r\nwindow.addEventListener('mousemove',function(evt){\r\n if(isMouseDown){\r\n currentX = evt.pageX;\r\n currentY = evt.pageY;\r\n if(preX != null){\r\n translateX += currentX - preX;\r\n translateY += currentY - preY;\r\n dom.style.transform = 'translateX('+translateX+'px) translateY('+translateY+'px)';\r\n }\r\n preX = currentX;\r\n preY = currentY;\r\n evt.preventDefault();\r\n instance[handlerName](evt);\r\n }\r\n},false);\r\n...\r\n```\r\n\r\n* 通过 var handlerName = dom.getAttribute('dragMove') 拿到dom上声明的dragMove\r\n* 通过 instance[handlerName](evt) 去执行对应的方法\r\n\r\n点击这里→在线试试\r\n\r\n## 更多插件\r\n\r\n* [omi-finger](https://github.com/AlloyTeam/omi/tree/master/plugins/omi-finger) Omi的[AlloyFinger](https://github.com/AlloyTeam/AlloyFinger)插件,支持各种触摸事件和手势\r\n* [omi-transform](https://github.com/AlloyTeam/omi/tree/master/plugins/omi-transform) Omi的[transformjs](http://alloyteam.github.io/AlloyTouch/transformjs/)插件,快速方便地设置DOM的CSS3 Transform属性\r\n* [omi-touch](https://github.com/AlloyTeam/omi/tree/master/plugins/omi-touch) Omi的[AlloyTouch](https://github.com/AlloyTeam/AlloyTouch)插件,Omi项目的触摸运动解决方案(支持触摸滚动、旋转、翻页、选择等等)\r\n* [omi-jquery-date-picker](https://github.com/AlloyTeam/omi/tree/master/plugins/omi-jquery-date-picker) Omi的时间选择插件,支持各种时间或者时间区域选择\r\n" - -/***/ }, -/* 21 */ -/***/ function(module, exports) { - - module.exports = "## Store 体系\r\n\r\n先说说Store系统是干什么的!\r\n\r\n当我们组件之间,拥有共享的数据的时候,经常需要进行组件通讯。在Omi框架里,组件通讯非常方便:\r\n\r\n* 通过在组件上声明 data-* 传递给子节点\r\n* 通过在组件上声明 data 传递给子节点 (支持复杂数据类型的映射)\r\n* 声明 group-data 把数组里的data传给一堆组件传递(支持复杂数据类型的映射)\r\n* 完全面向对象,可以非常容易地拿到对象的实例,之后可以设置实例属性和调用实例的方法。比如(标记name、标记omi-id)\r\n\r\n当然你也可以使用event emitter / pubsub库在组件之间通讯,比如这个只有 200b 的超小库[mitt](https://github.com/developit/mitt) 。但是需要注意mitt兼容到IE9+,Omi兼容IE8。\r\n\r\n虽然组件通讯非常方便,但是各种数据传递、组件实例互操作或者循环依赖,让代码非常难看且难以维护。所以:\r\n\r\nOmi.Store是为了让 组件通讯几乎绝迹 。虽然:\r\n\r\n\tRedux 的作者 Dan Abramov 说过:Flux 架构就像眼镜:您自会知道什么时候需要它。\r\n\t\r\n但是,我不会告诉你\r\n\r\n\tOmi Store 系统就像眼镜:您自会知道什么时候需要它。\r\n\t\r\n因为,Omi Store使用足够简便,对架构入侵性极极极小(3个极代表比极小还要小),让数据、数据逻辑和UI展现彻底分离,所以我的观点是:\r\n\r\n\t如果使用Omi,请使用Omi.Store架构。\r\n\t\r\n比如连这个[Todo例子](https://github.com/AlloyTeam/omi/tree/master/example/todo-store)都能使用Omi.Store架构。如果连复杂度都达不到Todo,那么Omi其实都没有必要使用,你可能只需要一个模板引擎便可。\r\n\r\n\r\n### 定义 Omi.Store\r\n\r\nOmi.Store是基类,我们可以继承Omi.Store来定义自己的Store,比如下面的TodoStore。\r\n\r\n```js\r\nimport Omi from 'omi'\r\n\r\nclass TodoStore extends Omi.Store {\r\n constructor(data , isReady) {\r\n super(isReady)\r\n\r\n this.data = Object.assign({\r\n items:[],\r\n text:'',\r\n length:0\r\n },data)\r\n\r\n this.data.length = this.data.items.length\r\n }\r\n\r\n add(){\r\n this.data.items.push(this.data.text)\r\n this.data.text = \"\"\r\n this.data.length = this.data.items.length\r\n this.update()\r\n }\r\n\r\n updateText(text){\r\n this.data.text = text\r\n }\r\n\r\n clear(){\r\n this.data.items.length = 0\r\n this.data.length = 0\r\n this.data.text = \"\"\r\n this.update()\r\n }\r\n}\r\n\r\nexport default TodoStore\r\n```\r\n\r\nTodoStore定义类数据的基本格式和数据模型的逻辑。\r\n比如 this.data 就是数据的基本格式, \r\n\r\n```js\r\n{\r\n items:[],\r\n text:'',\r\n length:0\r\n}\r\n```\r\n\r\nadd,updateText和clear就是数据模型的逻辑。\r\n\r\n### 使用 Omi.Store\r\n\r\n通过 new 关键字来使用TodoStore对象的实例。\r\n\r\n```js\r\nlet store = new TodoStore({ /* 初始化配置 */ })\r\n```\r\n\r\n上面可以传入一些初始化配置信息,store里面便包含了整个应用程序共享的状态数据以及相关数据逻辑方法(add,updateText,clear)。\r\n\r\n当然,这些初始化配置信息可能是异步拉取的。所以,有两种方法解决异步拉取store配置的问题:\r\n\r\n* 先let store = new TodoStore(),再Omi.render,组件内部监听store.ready,拉取数据更改store的data信息,然后执行store.beReady()\r\n* 拉取数据,然后new TodoStore(),再Omi.render\r\n\r\n### 根组件注入 store\r\n\r\n为了让组件树能够使用到 store,可以通过Omi.render的第三个参数给根组件注入 store:\r\n\r\n```js\r\nOmi.render(new Todo(),'body',{\r\n store: store\r\n});\r\n```\r\n\r\n当然ES2015已经允许你这样写了:\r\n\r\n```js\r\nOmi.render(new Todo(),'body',{\r\n store\r\n});\r\n```\r\n\r\n两份代码同样的效果。\r\n\r\n通过Omi.render注入之后,在组件树的所有组件都可以通过 this.$store 访问到 store。\r\n\r\n### 简便的 beforeRender\r\n\r\nbeforeRender这个函数,是生命周期的一部分。且看下面这张图:\r\n\r\n![beforeRender](http://images2015.cnblogs.com/blog/105416/201703/105416-20170322083548924-1871234168.jpg)\r\n\r\n在render之前,会去执行beforeRender方法。所以可以利用该方法写store的data到组件data的转换逻辑。比如:\r\n\r\n```js\r\nclass List extends Omi.Component {\r\n beforeRender(){\r\n this.data.items = this.$store.data.items\r\n }\r\n\r\n render () {\r\n return ` `\r\n }\r\n}\r\n```\r\n\r\n再比如todo使用length和text:\r\n\r\n```js\r\nimport Omi from '../../src/index.js';\r\nimport List from './list.js';\r\n\r\nOmi.makeHTML('List', List);\r\n\r\nclass Todo extends Omi.Component {\r\n\r\n install(){\r\n this.$store.ready(()=>this.update())\r\n }\r\n\r\n beforeRender(){\r\n this.data.length = this.$store.data.items.length\r\n this.data.text = this.$store.text\r\n }\r\n\r\n add (evt) {\r\n evt.preventDefault();\r\n this.$store.add();\r\n }\r\n\r\n handleChange(target){\r\n this.$store.updateText(target.value);\r\n }\r\n\r\n render () {\r\n return `
\r\n

TODO

\r\n \r\n
\r\n \r\n \r\n
\r\n
`;\r\n }\r\n}\r\n\r\nexport default Todo;\r\n```\r\n\r\n为什么要去写beforeRender方法?因为render只会使用this.data去渲染页面而不会去使用this.$store.data,所以需要把数据转移到组件的this.data下。这样组件既能使用自身的data,也能使用全局放this.$store.data了。\r\n\r\n更为详细的代码可以[点击这里](https://github.com/AlloyTeam/omi/tree/master/example/todo-store)。" - -/***/ }, -/* 22 */ -/***/ function(module, exports) { - - module.exports = "## 模板切换\r\n\r\nOmi有三个版本。其中的omi.js和omi.lite.js属于Web端使用的版本。\r\n\r\n* omi.js内置了[mustache.js](https://github.com/janl/mustache.js)作为模版引擎\r\n* omi.lite.js不包含任何模版引擎\r\n\r\nOmi不强制开发者使用mustache.js,你可以根据业务场景使用任意模板引擎或者不使用模板引擎。\r\n\r\n那么怎么使用别的模板引擎?下面拿[artTemplate](https://github.com/aui/artTemplate)作为例子。\r\n\r\n### 使用artTemplate\r\n\r\n```js\r\nOmi.template = function(tpl, data){\r\n return artTemplate.compile(tpl)(data);\r\n}\r\n```\r\n重写Omi.template方法,tpl为传入的模板,data为模板所需的数据,返回值为HTML。\r\n重写完毕后就能在render使用artTemplate的语法,如:\r\n\r\n```js\r\nclass List extends Omi.Component {\r\n constructor(data) {\r\n super(data);\r\n }\r\n\r\n style () {\r\n return `\r\n h1 { color:red; }\r\n li{ color:green;}\r\n `;\r\n }\r\n\r\n render () {\r\n return `

{{title}}

\r\n `;\r\n }\r\n}\r\n```\r\n\r\n### 相关地址\r\n\r\n* [演示地址](http://alloyteam.github.io/omi/example/artTemplate/)\r\n* [源码地址](https://github.com/AlloyTeam/omi/tree/master/example/artTemplate)" - -/***/ }, -/* 23 */ -/***/ function(module, exports) { - - module.exports = "## Omi的理念\n\nOmi的理念是基于面向对象编程体系,内建积木系统。\n 传统的单向数据流或者抛出event的组件通讯方式增加了系统的稳定性,但是丧失了灵活性。一定程度上也降低了组件的复用。所谓鱼和熊掌不可兼得。\n 面向对象体系需要多一个逻辑层,可以自由操作所有组件的instance,instance之间的逻辑关系构建出了整个程序。这样组件间的逻辑,通信,复用就全部迎刃而解。组件也更加单一职责,更松耦合。\n\n对比函数式编程、命令式编程与面向对象编程,可以归纳总结出下面几条:\n\n- 命令式编程干脆直接,利用循环条件等控制流程,强调执行过程\n- 命令式编程对硬件执行友好,运行更容易,却阻碍了复杂程序的设计\n- 函数式强调输入和输出,并非执行过程\n- 函数式倡导多个简单执行单元组合成复杂运算程序\n- 面向对象编程将对象作为程序的基本单元,更具有重用性、灵活性和扩展性\n\nJavascript是哪种类型的语言?现在ES6+已经有了class。那么他是面向对象语言?\n但是JS可以在任意地方定义函数并且当作把函数当作值来传递。那么他是函数式编程语言?\n所以,没有精准的定义,取决于你的用法和姿势。其次,Web组件化架构层面编程模型和语言层面编程模型是非常自由的关系。意思就是,你可以用Javascript构建函数式编程框架如React,也可以基于面向对象体系搭建Omi。\n\n### 函数式编程 VS 面向对象编程\n\n在UI组件框架层面,函数式编程的代表有React,Omi属于面向对象编程体系。那么他们各有什么优缺点?下面做了个对比(其实也是函数式编程与面向对象编程的对比):\n\n| | React | Omi |\n| ------------- |:-------------:|:-----:|\n| 组件通信 | ★★★★☆| ★★★★★ |\n| 稳定性 | ★★★★★ | ★★★★☆ |\n| 灵活性 | ★★★★☆| ★★★★★ |\n| 扩展性 | ★★★★☆ | ★★★★★ |\n| 测试性 | ★★★★★ | ★★★★☆ |\n| 文件大小 | ★★★☆☆ | ★★★★★ |\n| 功能特性 | ★★★☆☆ | ★★★★☆ |\n| DOM性能 | ★★★★★ | ★★★★☆ |\n| 动画性能 | ★★★★☆ | ★★★★★ |\n| 抽象复杂度 | ★★★★☆ | ★★★★★ |\n| 异步编程 | ★★★★★ | ★★★★☆ |\n\n可以看得出,鱼和熊掌不可兼得。面向对象编程更具有重用性、灵活性和扩展性,带来的问题就是更加难测试。\n具体来说,如函数式编程,其测试面积是state1 + state2 + ... + stateN;在面向对象编程中,其测试面积是state1×event1 + state2×event2 + ... + stateN×eventN。\n\n总结来说,更加推荐使用面向对象的方式去搭建UI组件化框架。\n\n
\n\n### 全文结束,感谢阅读。[开始Omi之旅吧!](https://github.com/AlloyTeam/omi) \n\n" - -/***/ }, -/* 24 */ -/***/ function(module, exports) { - - module.exports = "## Component Communication\r\n\r\nCommunication between [Omi](https://github.com/AlloyTeam/omi) components is very flexible, there are many options:\r\n\r\n- By declaring `data-*` on the component to pass data to child node\r\n- By declaring `data` on the component to pass data to child node (support complex data types mapping)\r\n- By declaring `group-data` (support complex data types mapping)\r\n- It's completely object-oriented, you can easily get the object instance, then you can set the instance of the property or call the instance of the method\r\n\r\nLet's see some examples.\r\n\r\n### Communicate by `data-*`\r\n\r\n```js\r\nclass Hello extends Omi.Component {\r\n constructor(data) {\r\n super(data);\r\n }\r\n \r\n style () {\r\n return `\r\n h1{\r\n \tcursor:pointer;\r\n }\r\n `;\r\n }\r\n \r\n handleClick(target, evt){\r\n alert(target.innerHTML);\r\n }\r\n \r\n render() {\r\n return `\r\n
\r\n \t

Hello ,{{name}}!

\r\n
\r\n \t\t`;\r\n }\r\n}\r\n\r\nOmi.makeHTML('Hello', Hello);\r\n\r\nclass App extends Omi.Component {\r\n constructor(data) {\r\n super(data);\r\n }\r\n \r\n render() {\r\n return `\r\n
\r\n \r\n
\r\n `;\r\n }\r\n}\r\n\r\nOmi.render(new App(),\"#container\");\r\n```\r\n\r\nGenerally `data-*` is used to pass value types such as string and number. It is worth noting that, through `data-*`, received data types are string. You need to manually transform it to the number type.\r\n\r\nNormally, communicate by `data-*` is enough, but sometimes we may need to use complex data types, then we can use `data` to communicate.\r\n\r\n### Communicate by `data`\r\n\r\nAs shown in the above code, name can be passed to the subcomponent by `data-name=\"Omi\"`. The following code can also achieve the same effect.\r\n\r\n```js\r\n...\r\nclass App extends Omi.Component {\r\n constructor(data) {\r\n super(data);\r\n this.helloData = { name : 'Omi' };\r\n }\r\n \r\n render() {\r\n return `\r\n
\r\n \r\n
\r\n `;\r\n }\r\n}\r\n\r\nOmi.render(new App(),\"#container\");\r\n```\r\n\r\nUse the `data` tag, it will find the property from the component instance (that is, this), this can be mounted with any complex objects. This also broke the limitations of `data-*`.\r\n\r\nThen how do we pass `data` that is in a deep depth of the instance to the Hello? No worries, `data` tag can be a complex statement:\r\n\r\n```js\r\n...\r\nclass App extends Omi.Component {\r\n constructor(data) {\r\n super(data);\r\n this.complexData ={\r\n a:{\r\n b:{\r\n c:[\r\n {\r\n e:[{\r\n name:'ComplexData Support1'\r\n },{\r\n name:'ComplexData Support2'\r\n }]\r\n },\r\n {\r\n name: 'ComplexData Support3'\r\n }\r\n ]\r\n }\r\n }\r\n };\r\n }\r\n \r\n render() {\r\n return `\r\n
\r\n \r\n
\r\n `;\r\n }\r\n}\r\n...\r\n```\r\n\r\nClick me for the complex data mapping\r\n\r\n### Communicate by `group-data`\r\n\r\n`group-data` can pass data to a group of components. \r\n\r\n```js\r\nimport Hello from './hello.js';\r\n\r\n\r\nOmi.makeHTML('Hello', Hello);\r\n\r\nclass App extends Omi.Component {\r\n constructor(data) {\r\n super(data);\r\n this.testData = [{name: 'Omi'}, {name: 'dntzhang'}, {name: 'AlloyTeam'}];\r\n }\r\n\r\n render() {\r\n return `\r\n
\r\n \r\n \r\n \r\n
\r\n `;\r\n\r\n }\r\n}\r\n\r\nOmi.render(new App(),\"#container\");\r\n```\r\n\r\nBy declaring a `group-data` tag in the sub-components, it will go to the current instance of the component (that is, `this`) to find the corresponding property. Then according to the current location, the data will pass to the positions one by one.\r\n\r\nThe results are as follows:\r\n\r\n![group-data results](http://images2015.cnblogs.com/blog/105416/201702/105416-20170216110701535-1698390390.png)\r\n\r\nClick me for the group-data example\r\n\r\nSimilarly, `group-data` supports the mapping of complex data types. It should be noted that the end of the group-data mapping must be an array:\r\n\r\n```js\r\nimport Hello from './hello.js';\r\n\r\n\r\nOmi.makeHTML('Hello', Hello);\r\n\r\nclass App extends Omi.Component {\r\n constructor(data) {\r\n super(data);\r\n this.complexData ={\r\n a:{\r\n b:{\r\n c:[\r\n {\r\n e:[{\r\n name:'ComplexData Support1'\r\n },{\r\n name:'ComplexData Support2'\r\n }]\r\n },\r\n {\r\n name: 'ComplexData Support3'\r\n }\r\n ]\r\n }\r\n }\r\n };\r\n }\r\n\r\n render() {\r\n return `\r\n
\r\n \r\n \r\n
\r\n `;\r\n\r\n }\r\n}\r\n\r\nOmi.render(new App(),\"#container\");\r\n```\r\n\r\nClick me for the complex group-data mapping\r\n\r\n### By object instance\r\n\r\n```js\r\n...\r\nclass App extends Omi.Component {\r\n constructor(data) {\r\n super(data);\r\n }\r\n \r\n installed(){\r\n this.hello.data.name = \"Omi\";\r\n this.update()\r\n }\r\n \r\n render() {\r\n return `\r\n
\r\n \r\n
\r\n `;\r\n }\r\n}\r\n\r\nOmi.render(new App(),\"#container\");\r\n```\r\n\r\n### By omi-id\r\n\r\n```js\r\n...\r\nclass App extends Omi.Component {\r\n constructor(data) {\r\n super(data);\r\n }\r\n \r\n installed(){\r\n Omi.get(\"hello\").data.name = \"Omi\";\r\n this.update()\r\n }\r\n \r\n render() {\r\n return `\r\n
\r\n \r\n
\r\n `;\r\n }\r\n}\r\n\r\nOmi.render(new App(),\"#container\");\r\n```\r\n\r\nBy declaring `omi-id` on the component, we can get the instance of the object anywhere in the program. This can be regarded as any component communication artifacts.\r\n\r\n" - -/***/ }, -/* 25 */ -/***/ function(module, exports) { - - module.exports = "## Components\r\n\r\n[Omi](https://github.com/AlloyTeam/omi) is based entirely on component architecture, which allows developers to build web applications like building blocks. Everything is components, components can be nested to create new components.\r\n\r\n![Omi Components System](http://images2015.cnblogs.com/blog/105416/201702/105416-20170210093427338-1536910080.png)\r\n\r\n### Simple Components\r\n\r\nLet's explore a simple Todo example to learn the components system in Omi.\r\n\r\n```js\r\nclass Todo extends Omi.Component {\r\n constructor(data) {\r\n super(data);\r\n }\r\n \r\n add (evt) {\r\n evt.preventDefault();\r\n this.data.items.push(this.data.text);\r\n this.data.text = '';\r\n this.update();\r\n }\r\n\r\n style () {\r\n return `\r\n h3 { color:red; }\r\n button{ color:green;}\r\n `;\r\n }\r\n\r\n handleChange(target){\r\n this.data.text = target.value;\r\n }\r\n\r\n render () {\r\n return `
\r\n

TODO

\r\n \r\n
\r\n \r\n \r\n
\r\n
`;\r\n }\r\n}\r\n\r\nOmi.render(new Todo({ items: [] ,text : '' }),\"body\");\r\n```\r\n\r\nThe HTML generated by the component will eventually be inserted into the body. The above example shows some of the features of Omi:\r\n\r\n- Data flow: `data` in `new Todo(data,..)` can be used directly in the template in render method.\r\n- Partial CSS: `h3` in `style()` only effect inside of render. It'll never pollute `h3` outside of this component. The same rule applies to `button`.\r\n- Declarative event binding: `onchange` will call `handleChange` that inside of the component. `this` refers to the current DOM element, `event` refers to the current DOM Event Object.\r\n- You need to manually call the `this.update()` method to update the component\r\n\r\nIt is important to note that, for more freedom and flexibility, Omi does not automatically update DOM while data changes. Developers need to call the `update` method manually.\r\n\r\nYou can also use [oba] (https://github.com/dntzhang/oba) or mobx to implement automatic updates.\r\n\r\nClick me for the live demo\r\n\r\n### Component Nesting\r\n\r\nIt's ok to not use nesting component if your page is super simple. However, for most of webpages and web applications, it is a necessary to define the nesting Components to implement complex features.\r\n\r\nFor instance, we can extract a `List` component form the Todo example. This brings maintainable, scalable and reuseable to our project:\r\n\r\n```js\r\nclass List extends Omi.Component {\r\n constructor(data) {\r\n super(data);\r\n }\r\n\r\n render () {\r\n return ``;\r\n }\r\n}\r\n```\r\n\r\nThen how to use this `List`? We need to use `Omi.makeHTML` to make the `List` to a tag which can be used in render method:\r\n\r\n```js\r\nimport List from './list.js';\r\n\r\nOmi.makeHTML('List', List);\r\n\r\nclass Todo extends Omi.Component {\r\n constructor(data) {\r\n super(data);\r\n this.data.length = this.data.items.length;\r\n this.listData = { items : this.data.items };\r\n }\r\n\r\n add (evt) {\r\n evt.preventDefault();\r\n this.list.data.items.push(this.data.text);\r\n this.data.length = this.list.data.items.length;\r\n this.data.text = '';\r\n this.update();\r\n }\r\n\r\n style () {\r\n return `\r\n h3 { color:red; }\r\n button{ color:green;}\r\n `;\r\n }\r\n\r\n handleChange(target){\r\n this.data.text = target.value;\r\n }\r\n\r\n render () {\r\n return `
\r\n

TODO

\r\n \r\n
\r\n \r\n \r\n
\r\n
`;\r\n }\r\n}\r\n```\r\n\r\n- In line 3, we use `makeHTML` to make the component to a tag which can be used in render method. Of course, `Omi.makeHTML('List', List);` can also be written in the end of List component.\r\n- In line 9, the parent component defines the 'listData' property\r\n- In line 34, we use List component in the render method. `name` attribute allows us easily find the instance of the component by using `this`.`data=\"listData\"` attribute allows us easily pass `this.listData` to the sub component from parent component.\r\n\r\nIt should be noted that the `data` passed from `data=\"listData\"` is cloned to the subcomponents by Object.assign(shallow copy) , which means if we want to change the DOM, we recommend that first update the `data` of the instance of subcomponent(not the parent component's `listData` ) and secondly call the `update` method.\r\n\r\nIn fact there are 4 way to communicate between components, it'll be explained later.\r\n\r\nClick me for the live demo\r\n" - -/***/ }, -/* 26 */ -/***/ function(module, exports) { - - module.exports = "## Conditional Rendering\r\n\r\nIn most case, we need to show different layouts according to different states. For example, some users are vip and we need to show vip logo for them. Omi has many ways to meet this kind of requirements.\r\n\r\n### First Option\r\n\r\n```js\r\nclass ConditionTest extends Omi.Component {\r\n constructor(data) {\r\n super(data);\r\n }\r\n\r\n render () {\r\n return `{{#isVip}}\r\n
you are VIP.
\r\n {{/isVip}}\r\n {{^isVip}}\r\n
you are not VIP.
\r\n {{/isVip}}`;\r\n }\r\n}\r\n```\r\n\r\nIn the above case, we use the condition in mustachejs for rendering. Of course Omi does not force you to use mustachejs. You can use omi.lite.js and then override the `Omi.template` method to use any of your favorite template engines.\r\n\r\n### Second Option\r\n\r\n```js\r\nclass ConditionTest extends Omi.Component {\r\n constructor(data) {\r\n super(data);\r\n }\r\n\r\n render () {\r\n if(this.data.isVip){\r\n return '
you are VIP.
';\r\n }else{\r\n return '
you are not VIP.
';\r\n }\r\n }\r\n}\r\n```\r\n\r\n`render` provides a very good programmability, which can write any js code inside. Oh, don't forget that `style` method can also have js code inside it.\r\n\r\n```js\r\nclass ConditionTest extends Omi.Component {\r\n constructor(data) {\r\n super(data);\r\n }\r\n\r\n style (){\r\n if(this.data.isVip){\r\n return 'div{ color : red; }';\r\n }else{\r\n return 'div{ color : green; }';\r\n }\r\n }\r\n\r\n render () {\r\n if(this.data.isVip){\r\n return '
you are VIP.
';\r\n }else{\r\n return '
you are not VIP.
';\r\n }\r\n }\r\n}\r\n```" - -/***/ }, -/* 27 */ -/***/ function(module, exports) { - - module.exports = "## Handling Events\r\n\r\nThere are two types of events in Omi, built-in events and custom events. Built-in events clever use of the browser's own pipeline mechanism, you can easily get events instance and the triggered event elements through `event` and `this`.\r\n\r\n### Built-in events\r\n\r\nWhat is the built-in event? As long as the it can match the following regular expression.\r\n\r\n```js\r\non(abort|blur|cancel|canplay|canplaythrough|change|click|close|contextmenu|cuechange|dblclick|drag|dragend|dragenter|dragleave|dragover|dragstart|drop|durationchange|emptied|ended|error|focus|input|invalid|keydown|keypress|keyup|load|loadeddata|loadedmetadata|loadstart|mousedown|mouseenter|mouseleave|mousemove|mouseout|mouseover|mouseup|mousewheel|pause|play|playing|progress|ratechange|reset|resize|scroll|seeked|seeking|select|show|stalled|submit|suspend|timeupdate|toggle|volumechange|waiting|autocomplete|autocompleteerror|beforecopy|beforecut|beforepaste|copy|cut|paste|search|selectstart|wheel|webkitfullscreenchange|webkitfullscreenerror|touchstart|touchmove|touchend|touchcancel|pointerdown|pointerup|pointercancel|pointermove|pointerover|pointerout|pointerenter|pointerleave)\r\n```\r\n\r\nHow to bind built-in events? As follows:\r\n\r\n```js\r\nclass EventTest extends Omi.Component {\r\n constructor(data) {\r\n super(data);\r\n }\r\n\r\n handleClick(dom, evt){\r\n alert(dom.innerHTML);\r\n }\r\n\r\n render () {\r\n return `
Hello, Omi!
`;\r\n }\r\n}\r\n```\r\n\r\n### Custom events\r\n\r\nEvents that defined by developers is the custom events. Here is the pagination example:\r\n\r\n```js\r\nimport Omi from '../../src/index.js';\r\nimport Pagination from './pagination.js';\r\nimport Content from './content.js';\r\n\r\nOmi.makeHTML('Pagination', Pagination);\r\nOmi.makeHTML('Content', Content);\r\n\r\nclass Main extends Omi.Component {\r\n constructor(data) {\r\n super(data);\r\n }\r\n\r\n installed(){\r\n this.content.goto(this.pagination.data.currentPage+1);\r\n }\r\n \r\n handlePageChange(index){\r\n this.content.goto(index+1);\r\n }\r\n\r\n render () {\r\n return `
\r\n

Pagination Example

\r\n \r\n \r\n
`;\r\n }\r\n}\r\n\r\nOmi.render( new Main(),'body');\r\n```\r\n\r\nAs we can see, the `onPageChange` is a custom event, `handlePageChange` will being executed when `onPageChange` is triggered. The `onPageChange` method is executed in `Pagination`:\r\n\r\n```js\r\nimport Omi from '../../src/index.js';\r\n\r\nclass Pagination extends Omi.Component {\r\n ...\r\n ...\r\n ...\r\n linkTo: \"#\",\r\n prevText: \"Prev\",\r\n nextText: \"Next\",\r\n ellipseText: \"...\",\r\n prevShow: true,\r\n nextShow: true,\r\n onPageChange: function () { return false; }\r\n }, this.data);\r\n\r\n this.pageNum = Math.ceil(this.data.total / this.data.pageSize);\r\n }\r\n \r\n goto (index,evt) {\r\n evt.preventDefault();\r\n this.data.currentPage=index;\r\n this.update();\r\n this.data.onPageChange(index);\r\n }\r\n ...\r\n ...\r\n ...\r\n}\r\n```\r\n\r\nThis is a part of `Pagination` code. Highlight is the place to execute `onPageChange`.\r\n\r\n### Links\r\n\r\n- [Demo](http://alloyteam.github.io/omi/example/pagination/)\r\n- [Source](https://github.com/AlloyTeam/omi/tree/master/example/pagination)" - -/***/ }, -/* 28 */ -/***/ function(module, exports) { - - module.exports = "## Forms\r\n\r\nIt's much more convenient to control forms in Omi, especially `\r\n \r\n \r\n \r\n \r\n\r\n```\r\n\r\nThe third option is selected because it is being set to `selected` attribute. The problem is that developers need to traversed each option. While using Omi, you can write code like this:\r\n\r\n```html\r\n\r\n```\r\n\r\nThis will achieve the same effect. For example, you want to choose the first item:\r\n\r\n```html\r\n\r\n```\r\n\r\nIsn't it very convenient?\r\n\r\n### For Example\r\n\r\n```js\r\nclass FormTest extends Omi.Component {\r\n constructor(data) {\r\n super(data);\r\n \r\n }\r\n\r\n handleChange(target){\r\n console.log(target.value)\r\n this.data.value = target.value;\r\n }\r\n\r\n handleSubmit(evt) {\r\n alert('Your favorite flavor is: ' + this.data.value);\r\n evt.preventDefault();\r\n }\r\n \r\n render () {\r\n return `\r\n
\r\n \r\n \r\n
`;\r\n }\r\n}\r\n\r\nOmi.render(new FormTest({ value: 'mango' }),'#container');\r\n```\r\n\r\nClick me for a live demo" - -/***/ }, -/* 29 */ -/***/ function(module, exports) { - - module.exports = "## Get DOM\r\n\r\nWhile most of the time, developers do not need to find the DOM, but sometimes is a need to get the DOM.\r\n\r\nOmi provides a way to get the DOM node.\r\n\r\n### ref and refs\r\n\r\n```js\r\nclass Hello extends Omi.Component {\r\n constructor(data) {\r\n super(data);\r\n }\r\n \r\n style () {\r\n return `\r\n h1{\r\n cursor:pointer;\r\n }\r\n `;\r\n }\r\n \r\n handleClick(){\r\n alert(this.refs.abc.innerHTML);\r\n }\r\n \r\n render() {\r\n return `\r\n
\r\n

Hello ,{{name}}!

\r\n
\r\n `;\r\n }\r\n}\r\n\r\nOmi.render(new Hello({ name : \"Omi\" }),\"#container\");\r\n```\r\n\r\nAs we can see, by referencing `ref` as `abc` in HTML, the DOM node can be accessed through `this.refs.abc`.\r\n\r\nClick me for the live demo\r\n" - -/***/ }, -/* 30 */ -/***/ function(module, exports) { - - module.exports = "## Hello World\r\n\r\n### Hello World with ES20XX \r\n\r\nWe recommend using a bundler like [webpack](https://webpack.github.io/) or [Browserify](http://browserify.org/) so you can write modular code and bundle it together into small packages to optimize load time.\r\n\r\nThe small Omi example looks like this:\r\n\r\n```js\r\nimport Omi from './omi.js';\r\n\r\nclass Hello extends Omi.Component {\r\n constructor(data) {\r\n super(data);\r\n }\r\n \r\n style () {\r\n return `\r\n h1{\r\n cursor:pointer;\r\n }\r\n `;\r\n }\r\n \r\n handleClick(target){\r\n alert(target.innerHTML);\r\n }\r\n \r\n render() {\r\n return `\r\n
\r\n

Hello ,{{name}}!

\r\n
\r\n `;\r\n }\r\n}\r\n\r\nOmi.render(new Hello({ name : \"Omi\" }),\"body\");\r\n```\r\n\r\nThis code renders into body element. \r\n\r\n### Hello World with ES5\r\n\r\n```html\r\n\r\n```\r\n\r\nthen:\r\n\r\n```js\r\nvar Hello = Omi.create(\"Hello\", {\r\n style: function () {\r\n return \"h1{ cursor:pointer }\";\r\n },\r\n \r\n handleClick: function (dom) {\r\n alert(dom.innerHTML)\r\n },\r\n \r\n render: function () {\r\n return '
\\\r\n

\\\r\n Hello ,{{name}}!\\\r\n

\\\r\n
'\r\n }\r\n});\r\n\r\nvar Test = Omi.create(\"Test\", {\r\n render: function () {\r\n return '
\\\r\n
Test
\\\r\n \\\r\n
'\r\n }\r\n});\r\n\r\nOmi.render(new Test(),'#container');\r\n```" - -/***/ }, -/* 31 */ -/***/ function(module, exports) { - - module.exports = "## Inheritance\r\n\r\nThrough the inheritance mechanism, we can define new classes base on old classes. The new classes not only have newly defined members, but also have old members at the same time.\r\n\r\nWe call the existing class the base class, also known as the parent class. And the new class derived from the existing class is called a derived class, also known as a subclass.\r\n\r\n### For Example\r\n\r\n```js\r\nclass Hello extends Omi.Component {\r\n constructor(data) {\r\n super(data);\r\n }\r\n \r\n style () {\r\n return `\r\n div{\r\n cursor:pointer;\r\n }\r\n `;\r\n }\r\n \r\n handleClick(target, evt){\r\n alert(target.innerHTML);\r\n }\r\n \r\n render() {\r\n return '
Hello {{name}}!
'\r\n }\r\n}\r\n\r\nclass SubHello extends Hello {\r\n constructor(data) {\r\n super(data);\r\n }\r\n}\r\n\r\nOmi.render(new SubHello({ name : 'Omi' }),'#container');\r\n```\r\n\r\nClick me for the live demo\r\n\r\n### inherit in ES5\r\n\r\n```js\r\nvar Hello = Omi.create(\"Hello\",{\r\n render:function(){\r\n return '
Hello {{name}}!
'\r\n }\r\n})\r\n\r\nvar SubHello = Omi.create(\"SubHello\",Hello,{ });\r\n\r\n\r\nOmi.render(new SubHello({ name : 'Omi' }),'#container');\r\n```\r\n\r\nClick me for the live demo" - -/***/ }, -/* 32 */ -/***/ function(module, exports) { - - module.exports = "## Installation\r\n\r\n[Omi](https://github.com/AlloyTeam/omi) is open and modern framework for building user interfaces.\r\n\r\n### Installing Omi\r\n\r\nWe recommend using [npm](https://www.npmjs.com/) for managing front-end dependencies. If you're new to package managers.\r\n\r\nTo install Omi with npm, run:\r\n\r\n``` js\r\n$ npm install omi\r\n```\r\n### omi-cli\r\n\r\n``` js\r\n$ npm install omi-cli -g \r\n$ omi init your_project_name \r\n$ cd your_project_name \r\n$ npm run dev \r\n$ npm run dist \r\n```" - -/***/ }, -/* 33 */ -/***/ function(module, exports) { - - module.exports = "## Lifecycle\r\n\r\n| Name | Meaning | Occasion |\r\n| :-------------: | :-------------: | :-----: |\r\n| constructor | The constructor | When new a constructor |\r\n| install | The installation. We can process the data that user pass | When instantiate |\r\n| installed | Complete the installation. It'll trigger after HTML being inserted to the page. Please note that it'll trigger when component being removed and restored | **Instantiation and existence** |\r\n| uninstall | Uninstall the component. It'll trigger when remove is executed | When destroy |\r\n| beforeUpdate | Before update | When existence |\r\n| afterUpdate | After update | When existence |\r\n\r\n## Illustration\r\n\r\n![lc](http://images2015.cnblogs.com/blog/105416/201703/105416-20170322084234049-1482108845.jpg)\r\n\r\nIt should be noted that the installed will be executed during the instantiation, which is not shown above. For example, it'll executed when a component is removed and restored, or when the new component is being added.\r\n\r\n### Examples\r\n\r\n```js\r\nclass Timer extends Omi.Component {\r\n constructor(data) {\r\n super(data);\r\n }\r\n\r\n install () {\r\n this.data = {secondsElapsed: 0};\r\n }\r\n\r\n tick() {\r\n this.data.secondsElapsed++;\r\n this.update();\r\n }\r\n\r\n installed(){\r\n this.interval = setInterval(() => this.tick(), 1000);\r\n }\r\n\r\n uninstall() {\r\n clearInterval(this.interval);\r\n }\r\n\r\n\r\n style () {\r\n return `\r\n .num { color:red; }\r\n `;\r\n }\r\n\r\n render () {\r\n return `
Seconds Elapsed: {{secondsElapsed}}
`;\r\n }\r\n}\r\n```\r\n\r\nClick me for the live demo" - -/***/ }, -/* 34 */ -/***/ function(module, exports) { - - module.exports = "## Loop\r\n\r\nThe following describes how to traverses in mustache.js and javascript.\r\n\r\n### First Option\r\n\r\n```js\r\nclass List extends Omi.Component {\r\n constructor(data) {\r\n super(data);\r\n }\r\n\r\n render () {\r\n return `
\r\n \r\n
`;\r\n }\r\n}\r\n\r\nOmi.render(new List({\r\n items: [\r\n {id: 1, text: 'Omi'},\r\n {id: 2, text: 'dntzhang'},\r\n {id: 3, text: 'AlloyTeam'}\r\n ]\r\n}),\"body\");\r\n```\r\n\r\nMustache.js more detailed loop traversal use can see \r\n\r\nFor more details for traversal in mustache.js please view [https://github.com/janl/mustache.js#non-empty-lists](https://github.com/janl/mustache.js#non-empty-lists).\r\n\r\nFor example, it also support:\r\n\r\n- If each item of items is a string, you can directly use **{{.}}** to output each item\r\n- Call the defined function when looping\r\n\r\nClick me for the live demo\r\n\r\n### Second Option\r\n\r\nOf course, you can also use template string inside the `map`:\r\n\r\n```js\r\nclass List extends Omi.Component {\r\n constructor(data) {\r\n super(data);\r\n }\r\n\r\n render() {\r\n return `
\r\n \r\n
`;\r\n }\r\n}\r\n\r\nOmi.render(new List({\r\n items: [\r\n {id: 1, text: 'Omi'},\r\n {id: 2, text: 'dntzhang'},\r\n {id: 3, text: 'AlloyTeam'}\r\n ]\r\n}),\"body\");\r\n```\r\n\r\nYou will see the following page:\r\n\r\n![pv](http://images2015.cnblogs.com/blog/105416/201701/105416-20170122095724129-2059595233.png)\r\n\r\nClick me for the live demo" - -/***/ }, -/* 35 */ -/***/ function(module, exports) { - - module.exports = "## Plugin\r\n\r\n[Omi](https://github.com/AlloyTeam/omi) is a componentized web framework. Then what is plugin?\r\n\r\nIt can be understood that the Omi plugin system can give the dom element some ability and can be associated with the instance of the components.\r\n\r\n### omi-drag\r\n\r\nLet's see this example:\r\n\r\nClick me for the live deme\r\n\r\n```js\r\nimport OmiDrag from './omi-drag.js';\r\n\r\nOmiDrag.init();\r\n\r\nclass App extends Omi.Component {\r\n constructor(data) {\r\n super(data);\r\n }\r\n\r\n render() {\r\n return `\r\n
\r\n
Drag Me
\r\n
\r\n `;\r\n\r\n }\r\n\r\n style(){\r\n return `\r\n .test{\r\n width:100px;\r\n height:100px;\r\n color:white;\r\n line-height:90px;\r\n text-align:center;\r\n background-color:#00BFF3;\r\n }\r\n `\r\n }\r\n}\r\n\r\nOmi.render(new App(),\"#container\");\r\n```\r\n\r\nAs shown above, by adding `omi-drag` attribute to the div, it can be dragged by the user using the mouse. We call omi-drag.js an omi plugin.\r\n\r\nIsn't it very convenient? So how did this omi-drag implement?\r\n\r\n如上面的代码所示,通过在div上标记omi-drag,这个div就能够被用户使用鼠标拖拽。我们称omi-drag.js为omi插件。\r\n是不是非常方便?那么这个omi-drag是怎么实现的?\r\n\r\n## Omi.extendPlugin\r\n\r\nCore method: Omi.extendPlugin( pluginName, handler )\r\n\r\nThe following code shows how to use `Omi.extendPlugin` to give dom the drap and drop ability:\r\n\r\n```js\r\n;(function () {\r\n\r\n var OmiDrag = {};\r\n var Omi = typeof require === 'function'\r\n ? require('omi')\r\n : window.Omi;\r\n\r\n OmiDrag.init = function(){\r\n Omi.extendPlugin('omi-drag',function(dom, instance){\r\n dom.style.cursor='move';\r\n var isMouseDown = false,\r\n preX = null,\r\n preY = null,\r\n currentX = null,\r\n currentY = null,\r\n translateX = 0,\r\n translateY = 0;\r\n\r\n dom.addEventListener('mousedown',function(evt){\r\n isMouseDown = true;\r\n preX = evt.pageX;\r\n preY = evt.pageY;\r\n evt.stopPropagation();\r\n },false);\r\n\r\n window.addEventListener('mousemove',function(evt){\r\n if(isMouseDown){\r\n currentX = evt.pageX;\r\n currentY = evt.pageY;\r\n if(preX != null){\r\n translateX += currentX - preX;\r\n translateY += currentY - preY;\r\n dom.style.transform = 'translateX('+translateX+'px) translateY('+translateY+'px)';\r\n }\r\n preX = currentX;\r\n preY = currentY;\r\n evt.preventDefault();\r\n }\r\n },false);\r\n\r\n window.addEventListener('mouseup',function(){\r\n isMouseDown = false;\r\n preX = preY = currentX = currentY = null;\r\n },false);\r\n });\r\n }\r\n\r\n OmiDrag.destroy = function(){\r\n delete Omi.plugins['omi-drag'];\r\n };\r\n\r\n if (typeof exports == \"object\") {\r\n module.exports = OmiDrag;\r\n } else if (typeof define == \"function\" && define.amd) {\r\n define([], function(){ return OmiDrag });\r\n } else {\r\n window.OmiDrag = OmiDrag;\r\n }\r\n\r\n})();\r\n```\r\n\r\nMethod: Omi.extendPlugin( pluginName, handler )\r\n\r\n`pluginName` is the name of the plugin.\r\n\r\n`handler` is the processor. The handler can get the dom which marked as the `pluginName` and the instance of the component.\r\n\r\nWith `Omi.extendPlugin`, we can give the dom some ability, and can also be associated with the component instance.\r\n\r\nThe above example is not associated with the instance, let's try it:\r\n\r\n## Associated with instance\r\n\r\nWe want to be able to listen to the `move` inside the component and perform a callback. As follows:\r\n\r\n```js\r\n...\r\n...\r\nmoveHandler(){\r\n console.log('moving');\r\n}\r\n\r\nrender() {\r\n return `\r\n
\r\n
Drag Me
\r\n
\r\n `;\r\n}\r\n...\r\n```\r\n\r\nIn this case, the `moveHandler` will be continually executed while dragging. We can modify some code to solve this issue:\r\n\r\n```js\r\n...\r\nwindow.addEventListener('mousemove',function(evt){\r\n if(isMouseDown){\r\n currentX = evt.pageX;\r\n currentY = evt.pageY;\r\n if(preX != null){\r\n translateX += currentX - preX;\r\n translateY += currentY - preY;\r\n dom.style.transform = 'translateX('+translateX+'px) translateY('+translateY+'px)';\r\n }\r\n preX = currentX;\r\n preY = currentY;\r\n evt.preventDefault();\r\n instance.moveHandler(evt);\r\n }\r\n},false);\r\n```\r\n\r\nWe add `instance.moveHandler(evt)` method to execute the `moveHandler` method of component instance.\r\n\r\nThis is how associated with instance works.\r\n\r\nHowever, this may still have an issue if we add `omi-drag` to a list of `div`:\r\n\r\n```js\r\n...\r\nrender() {\r\n return `\r\n
\r\n
Drag Me
\r\n
Drag Me
\r\n
\r\n `;\r\n}\r\n...\r\n```\r\n\r\nUsually each of our `omi-drag` can correspond to a callback function, such as:\r\n\r\n```js\r\n...\r\n...\r\nmoveHandlerA(){\r\n console.log('moving');\r\n}\r\n\r\nmoveHandlerB(){\r\n console.log('moving');\r\n}\r\n\r\nrender() {\r\n return `\r\n
\r\n
Drag Me A
\r\n
Drag Me B
\r\n
\r\n `;\r\n}\r\n...\r\n```\r\n\r\nHow to achieve this? We can pass the data to the plugin via dom.\r\n\r\n## Passing data\r\n\r\nLet's see the final code:\r\n\r\n```js\r\n...\r\n...\r\nmoveHandlerA(){\r\n console.log('moving');\r\n}\r\n\r\nmoveHandlerB(){\r\n console.log('moving');\r\n}\r\n\r\nrender() {\r\n return `\r\n
\r\n
Drag Me A
\r\n
Drag Me B
\r\n
\r\n `;\r\n}\r\n...\r\n```\r\n\r\nWhere `omi-drag` modified:\r\n\r\n```js\r\n...\r\nvar handlerName = dom.getAttribute('dragMove');\r\n\r\nwindow.addEventListener('mousemove',function(evt){\r\n if(isMouseDown){\r\n currentX = evt.pageX;\r\n currentY = evt.pageY;\r\n if(preX != null){\r\n translateX += currentX - preX;\r\n translateY += currentY - preY;\r\n dom.style.transform = 'translateX('+translateX+'px) translateY('+translateY+'px)';\r\n }\r\n preX = currentX;\r\n preY = currentY;\r\n evt.preventDefault();\r\n instance[handlerName](evt);\r\n }\r\n},false);\r\n...\r\n```\r\n\r\n- We use `var handlerName = dom.getAttribute('dragMove')` to get the `dragMove` of dom\r\n- We use `instance[handlerName](evt)` to execute the method\r\n\r\nClick me for the live demo\r\n\r\n## More plugins\r\n\r\n* [omi-finger](https://github.com/AlloyTeam/omi/tree/master/plugins/omi-finger) The [AlloyFinger](https://github.com/AlloyTeam/AlloyFinger) plugin for Omi, which support touch events and gustures\r\n* [omi-transform](https://github.com/AlloyTeam/omi/tree/master/plugins/omi-transform) The [transformjs](http://alloyteam.github.io/AlloyTouch/transformjs/) plugin for Omi, which can easily set CSS3 Transform to DOM\r\n* [omi-touch](https://github.com/AlloyTeam/omi/tree/master/plugins/omi-touch) The [AlloyTouch](https://github.com/AlloyTeam/AlloyTouch) plugin for Omi. The touch movement solution for Omi (support touch scroll, rotate, flip, select, etc.)\r\n* [omi-jquery-date-picker](https://github.com/AlloyTeam/omi/tree/master/plugins/omi-jquery-date-picker) The date picker plugin for Omi, which support choose any time zone\r\n" - -/***/ }, -/* 36 */ -/***/ function(module, exports) { - - module.exports = "## Templates\r\n\r\nThere are three types of Omi. omi.js and omi.lite.js is for web side.\r\n\r\n- omi.js has a built-in [mustache.js](https://github.com/janl/mustache.js) as the template engine\r\n- omi.lite.js doesn't have any template engines\r\n\r\nOmi does not force developers to use mustache.js, you can use any template engine based on business scenarios or do not use any template engines.\r\n\r\nHow to use other template engines? Let's see the [artTemplate](https://github.com/aui/artTemplate) example.\r\n\r\n### Use artTemplate\r\n\r\n```js\r\nOmi.template = function(tpl, data){\r\n return artTemplate.compile(tpl)(data);\r\n}\r\n```\r\n\r\nWe need to rewrite the `Omi.template` method, the `tpl` is the incoming template, the `data` is the required data for the template, and the return value is HTML.\r\n\r\nAfter rewriting, you can use the artTemplate syntax in `render`, such as:\r\n\r\n```js\r\nclass List extends Omi.Component {\r\n constructor(data) {\r\n super(data);\r\n }\r\n\r\n style () {\r\n return `\r\n h1 { color:red; }\r\n li{ color:green;}\r\n `;\r\n }\r\n\r\n render () {\r\n return `

{{title}}

\r\n `;\r\n }\r\n}\r\n```\r\n\r\n### Links\r\n\r\n* [Demo Link](http://alloyteam.github.io/omi/example/artTemplate/)\r\n* [Source Code](https://github.com/AlloyTeam/omi/tree/master/example/artTemplate)" - -/***/ }, -/* 37 */ -/***/ function(module, exports) { - - module.exports = "## Thinking in Omi\r\n\r\nOmi is based on object-oriented programming, with plugin system.\r\n\r\nThe traditional one-way data flow or the event-throwing component communicating can increase the stability of the system, but it loses it's flexibility. To a certain extent also reduced the component reusing.\r\n\r\nObject-oriented system has an other logical layer, which let you control the instance of components. The logic between instances build the entire program.\r\n\r\nThen the issues like communication, reusing and logics between components are all solved.\r\n\r\n\r\nPlus, the component is also more single duty, more loosely coupled.\r\n\r\nFor functional programming, imperative programming and object-oriented programming, we can sum up the following list:\r\n\r\n- Imperative programming is well understood, we use loop and if-else condition to control processes, it emphasize the process of execution\r\n- Imperative programming is hardware friendly, easy to run, but hard to design complex program\r\n- Functional programming is all about input and output, not the process of execution\r\n- Functional programming advocates multiple simple execution units into complex operations\r\n- Object-oriented programming uses objects as the basic unit of the program, with more reusability, flexibility, and extensibility\r\n\r\nWhat kind of language is JavaScript? We have `class` in ES6+, so is JavaScript object-oriented language?\r\n\r\nJavaScript can pass a function as a argumant, so is JavaScript a functional language?\r\n\r\nThere are no right answer, it depands on how you use JavaScript.\r\n\r\nIt's free to chooce, you can use functional programming framework like React, or object-oriented framework like Omi. \r\n\r\n### Functional Programming VS Object-Oriented Programming\r\n\r\nIn the UI component framework scope, functional programming is represented by React, while Omi belongs to object-oriented programming.\r\n\r\nSo what are their strengths and weaknesses? The following is a comparison (in fact, functional programming and object-oriented programming comparison):\r\n\r\n| | React | Omi |\r\n| ------------- |:-------------:|:-----:|\r\n| Component communication | ★★★★☆| ★★★★★ |\r\n| Stability | ★★★★★ | ★★★★☆ |\r\n| Flexibility | ★★★★☆| ★★★★★ |\r\n| Scalability | ★★★★☆ | ★★★★★ |\r\n| Testability | ★★★★★ | ★★★★☆ |\r\n| File size | ★★★☆☆ | ★★★★★ |\r\n| Features | ★★★☆☆ | ★★★★☆ |\r\n| DOM performance | ★★★★★ | ★★★★☆ |\r\n| Animation performance | ★★★★☆ | ★★★★★ |\r\n| Abstract complexity | ★★★★☆ | ★★★★★ |\r\n| Asynchronous programming | ★★★★★ | ★★★★☆ |\r\n\r\nAs we can see, we can not have it both ways. Object-oriented programming is more reusable, flexible and scalable, the problem is more difficult to test.\r\n\r\nSpecifically, if the functional programming, the test area is state1 + state2 + ... + stateN; in object-oriented programming, the test area is state1 × event1 + state2 × event2 + ... + stateN × eventN.\r\n\r\nIn summary, it is more recommended to use the object-oriented programming to build UI component framework.\r\n\r\n
\r\n\r\n### The end. Thanks for reading. [Let's start the Omi journey](https://github.com/AlloyTeam/omi)!\r\n" - -/***/ }, -/* 38 */ -/***/ function(module, exports, __webpack_require__) { - - 'use strict'; - - Object.defineProperty(exports, "__esModule", { - value: true - }); - - var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); - - var _omi = __webpack_require__(2); - - var _omi2 = _interopRequireDefault(_omi); - - var _index = __webpack_require__(39); - - var _index2 = _interopRequireDefault(_index); - - var _config = __webpack_require__(4); - - var _config2 = _interopRequireDefault(_config); - - function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - - function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } - - function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; } - - function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } - - _omi2.default.makeHTML('List', _index2.default); - - var Sidebar = function (_Omi$Component) { - _inherits(Sidebar, _Omi$Component); - - function Sidebar(data) { - _classCallCheck(this, Sidebar); - - return _possibleConstructorReturn(this, (Sidebar.__proto__ || Object.getPrototypeOf(Sidebar)).call(this, data)); - } - - _createClass(Sidebar, [{ - key: 'install', - value: function install() { - this.data.items = _config2.default['menus'][this.data.lan]; - this.data.height = window.innerHeight - 45; - } - }, { - key: 'style', - value: function style() { - return __webpack_require__(42); - } - }, { - key: 'render', - value: function render() { - return __webpack_require__(43); - } - }]); - - return Sidebar; - }(_omi2.default.Component); - - exports.default = Sidebar; - -/***/ }, -/* 39 */ -/***/ function(module, exports, __webpack_require__) { - - 'use strict'; - - Object.defineProperty(exports, "__esModule", { - value: true - }); - - var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); - - var _omi = __webpack_require__(2); - - var _omi2 = _interopRequireDefault(_omi); - - function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - - function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } - - function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; } - - function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } - - var tpl = __webpack_require__(40); - var css = __webpack_require__(41); - - var List = function (_Omi$Component) { - _inherits(List, _Omi$Component); - - function List(data) { - _classCallCheck(this, List); - - var _this = _possibleConstructorReturn(this, (List.__proto__ || Object.getPrototypeOf(List)).call(this, data)); - - _omi2.default.mixIndexToArray(_this.data.list); - _this.data.currentIndex = 0; - var self = _this; - _this.data.isCurrent = function () { - return this.index === self.data.currentIndex && self.data.active; - }; - return _this; - } - - _createClass(List, [{ - key: 'goto', - value: function goto(name, index) { - var _this2 = this; - - _omi2.default.get('content').data.name = name; - _omi2.default.get('content').update(); - this.data.currentIndex = index; - this.parent.children.forEach(function (child, index) { - child.data.active = false; - if (child.id === _this2.id) { - _omi2.default.get('pager').activeIndex = index; - child.data.active = true; - } - child.update(); - }); - _omi2.default.get('pager').currentIndex = index; - _omi2.default.get('pager').update(); - document.body.scrollTop = 0; - } - }, { - key: 'render', - value: function render() { - return tpl; - } - }, { - key: 'style', - value: function style() { - return css; - } - }]); - - return List; - }(_omi2.default.Component); - - exports.default = List; - -/***/ }, -/* 40 */ -/***/ function(module, exports) { - - module.exports = "" - -/***/ }, -/* 41 */ -/***/ function(module, exports) { - - module.exports = "li.title{ font-size: 16px; font-weight: bold; margin-bottom:10px; margin-top:10px; text-indent: 23px;}li{ margin-bottom:3px; text-indent: 33px;}li a{ display:block; font-size:14px; height:20px; line-height:20px; color: #666;}li a.current{ background-color:#c3d4fc; color:white;}li a:hover{ background-color:#b3d4fc; color:white;}" - -/***/ }, -/* 42 */ -/***/ function(module, exports) { - - module.exports = "@media only screen and (max-width: 768px) { .list{ transform: translateX(-100%); background-color:white; -moz-transition: all .6s ease; -o-transition: all .6s ease; -webkit-transition: all .6s ease; transition: all .6s ease; } .list.show { -moz-transform: translateX(0%) translateZ(0); -ms-transform: translateX(0%) translateZ(0); -o-transform: translateX(0%) translateZ(0); -webkit-transform: translateX(0%) translateZ(0); transform: translateX(0%) translateZ(0); }}.list{ width:200px; text-indent: 20px; border-right: 1px solid #eee; overflow-x: hidden; overflow-y: auto; position:fixed; top:45px;}.version{ height:20px;}" - -/***/ }, -/* 43 */ -/***/ function(module, exports) { - - module.exports = "
{{#items}} {{/items}}
" - -/***/ }, -/* 44 */ -/***/ function(module, exports, __webpack_require__) { - - 'use strict'; - - Object.defineProperty(exports, "__esModule", { - value: true - }); - - var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); - - var _omi = __webpack_require__(2); - - var _omi2 = _interopRequireDefault(_omi); - - var _omiFinger = __webpack_require__(45); - - var _omiFinger2 = _interopRequireDefault(_omiFinger); - - function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - - function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } - - function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; } - - function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } - - var tpl = __webpack_require__(47); - var css = __webpack_require__(48); - - _omiFinger2.default.init(); - - var Head = function (_Omi$Component) { - _inherits(Head, _Omi$Component); - - function Head(data) { - _classCallCheck(this, Head); - - return _possibleConstructorReturn(this, (Head.__proto__ || Object.getPrototypeOf(Head)).call(this, data)); - } - - _createClass(Head, [{ - key: 'install', - value: function install() { - var _this2 = this; - - this.data.isEnLan = this.data.lan === 'en'; - document.body.addEventListener('touchend', function () { - setTimeout(function () { - _this2.removeClass(_omi2.default.get('sidebar').node, 'show'); - }, 300); - }, false); - } - }, { - key: 'toggleMenus', - value: function toggleMenus(evt) { - this.toggleClass(_omi2.default.get('sidebar').node, 'show'); - evt.stopPropagation(); - } - }, { - key: 'handleTouchEnd', - value: function handleTouchEnd(evt) { - evt.stopPropagation(); - } - }, { - key: 'toggleClass', - value: function toggleClass(element, className) { - if (!element || !className) { - return; - } - - var classString = element.className, - nameIndex = classString.indexOf(className); - if (nameIndex == -1) { - classString += ' ' + className; - } else { - classString = classString.substr(0, nameIndex) + classString.substr(nameIndex + className.length); - } - element.className = classString; - } - }, { - key: 'removeClass', - value: function removeClass(element, className) { - var classString = element.className, - nameIndex = classString.indexOf(className); - if (nameIndex !== -1) { - classString = classString.substr(0, nameIndex) + classString.substr(nameIndex + className.length); - } - element.className = classString; - } - }, { - key: 'style', - value: function style() { - return css; - } - }, { - key: 'render', - value: function render() { - return tpl; - } - }]); - - return Head; - }(_omi2.default.Component); - - exports.default = Head; - -/***/ }, -/* 45 */ -/***/ function(module, exports, __webpack_require__) { - - /*! - * omi-finger v0.1.3 by dntzhang - * Omi / AlloyFinger integration. Support touch and gesture events in your Omi project. - * Github: https://github.com/AlloyTeam/omi - * MIT Licensed. - */ - - ;(function () { - - var OmiFinger = {}; - var AlloyFinger = true - ? __webpack_require__(46) - : window.AlloyFinger; - var Omi = true - ? __webpack_require__(2) - : window.Omi; - - var noop = function(){ - - }; - - var getHandler = function(name, dom, instance) { - var value = dom.getAttribute(name); - if (value === null) { - return noop; - }else{ - return instance[value].bind(instance); - } - }; - - - OmiFinger.init = function(){ - Omi.extendPlugin('omi-finger',function(dom, instance){ - if(!instance.alloyFingerInstances)instance.alloyFingerInstances = []; - var len = instance.alloyFingerInstances.length; - var i = 0 ; - for(;i 1) r = 1; - return Math.acos(r); - } - - function cross(v1, v2) { - return v1.x * v2.y - v2.x * v1.y; - } - - function getRotateAngle(v1, v2) { - var angle = getAngle(v1, v2); - if (cross(v1, v2) > 0) { - angle *= -1; - } - - return angle * 180 / Math.PI; - } - - var HandlerAdmin = function(el) { - this.handlers = []; - this.el = el; - }; - - HandlerAdmin.prototype.add = function(handler) { - this.handlers.push(handler); - } - - HandlerAdmin.prototype.del = function(handler) { - if(!handler) this.handlers = []; - - for(var i=this.handlers.length; i>=0; i--) { - if(this.handlers[i] === handler) { - this.handlers.splice(i, 1); - } - } - } - - HandlerAdmin.prototype.dispatch = function() { - for(var i=0,len=this.handlers.length; i 0 && this.delta <= 250 && Math.abs(this.preTapPosition.x - this.x1) < 30 && Math.abs(this.preTapPosition.y - this.y1) < 30); - } - this.preTapPosition.x = this.x1; - this.preTapPosition.y = this.y1; - this.last = this.now; - var preV = this.preV, - len = evt.touches.length; - if (len > 1) { - this._cancelLongTap(); - this._cancelSingleTap(); - var v = { x: evt.touches[1].pageX - this.x1, y: evt.touches[1].pageY - this.y1 }; - preV.x = v.x; - preV.y = v.y; - this.pinchStartLen = getLen(preV); - this.multipointStart.dispatch(evt); - } - this.longTapTimeout = setTimeout(function () { - this.longTap.dispatch(evt); - }.bind(this), 750); - }, - move: function (evt) { - if (!evt.touches) return; - var preV = this.preV, - len = evt.touches.length, - currentX = evt.touches[0].pageX, - currentY = evt.touches[0].pageY; - this.isDoubleTap = false; - if (len > 1) { - var v = { x: evt.touches[1].pageX - currentX, y: evt.touches[1].pageY - currentY }; - - if (preV.x !== null) { - if (this.pinchStartLen > 0) { - evt.scale = getLen(v) / this.pinchStartLen; - this.pinch.dispatch(evt); - } - - evt.angle = getRotateAngle(v, preV); - this.rotate.dispatch(evt); - } - preV.x = v.x; - preV.y = v.y; - } else { - if (this.x2 !== null) { - evt.deltaX = currentX - this.x2; - evt.deltaY = currentY - this.y2; - - } else { - evt.deltaX = 0; - evt.deltaY = 0; - } - this.pressMove.dispatch(evt); - } - - this.touchMove.dispatch(evt); - - this._cancelLongTap(); - this.x2 = currentX; - this.y2 = currentY; - if (len > 1) { - evt.preventDefault(); - } - }, - end: function (evt) { - if (!evt.changedTouches) return; - this._cancelLongTap(); - var self = this; - if (evt.touches.length < 2) { - this.multipointEnd.dispatch(evt); - } - this.touchEnd.dispatch(evt); - //swipe - if ((this.x2 && Math.abs(this.x1 - this.x2) > 30) || - (this.y2 && Math.abs(this.y1 - this.y2) > 30)) { - evt.direction = this._swipeDirection(this.x1, this.x2, this.y1, this.y2); - this.swipeTimeout = setTimeout(function () { - self.swipe.dispatch(evt); - - }, 0) - } else { - this.tapTimeout = setTimeout(function () { - self.tap.dispatch(evt); - // trigger double tap immediately - if (self.isDoubleTap) { - self.doubleTap.dispatch(evt); - clearTimeout(self.singleTapTimeout); - self.isDoubleTap = false; - } - }, 0) - - if (!self.isDoubleTap) { - self.singleTapTimeout = setTimeout(function () { - self.singleTap.dispatch(evt); - }, 250); - } - } - - this.preV.x = 0; - this.preV.y = 0; - this.scale = 1; - this.pinchStartLen = null; - this.x1 = this.x2 = this.y1 = this.y2 = null; - }, - cancel: function (evt) { - clearTimeout(this.singleTapTimeout); - clearTimeout(this.tapTimeout); - clearTimeout(this.longTapTimeout); - clearTimeout(this.swipeTimeout); - this.touchCancel.dispatch(evt); - }, - _cancelLongTap: function () { - clearTimeout(this.longTapTimeout); - }, - _cancelSingleTap: function () { - clearTimeout(this.singleTapTimeout); - }, - _swipeDirection: function (x1, x2, y1, y2) { - return Math.abs(x1 - x2) >= Math.abs(y1 - y2) ? (x1 - x2 > 0 ? 'Left' : 'Right') : (y1 - y2 > 0 ? 'Up' : 'Down') - }, - - on: function(evt, handler) { - if(this[evt]) { - this[evt].add(handler); - } - }, - - off: function(evt, handler) { - if(this[evt]) { - this[evt].del(handler); - } - }, - - destroy: function() { - if(this.singleTapTimeout) clearTimeout(this.singleTapTimeout); - if(this.tapTimeout) clearTimeout(this.tapTimeout); - if(this.longTapTimeout) clearTimeout(this.longTapTimeout); - if(this.swipeTimeout) clearTimeout(this.swipeTimeout); - - this.element.removeEventListener("touchstart", this.start); - this.element.removeEventListener("touchmove", this.move); - this.element.removeEventListener("touchend", this.end); - this.element.removeEventListener("touchcancel", this.cancel); - - this.rotate.del(); - this.touchStart.del(); - this.multipointStart.del(); - this.multipointEnd.del(); - this.pinch.del(); - this.swipe.del(); - this.tap.del(); - this.doubleTap.del(); - this.longTap.del(); - this.singleTap.del(); - this.pressMove.del(); - this.touchMove.del(); - this.touchEnd.del(); - this.touchCancel.del(); - - this.preV = this.pinchStartLen = this.scale = this.isDoubleTap = this.delta = this.last = this.now = this.tapTimeout = this.singleTapTimeout = this.longTapTimeout = this.swipeTimeout = this.x1 = this.x2 = this.y1 = this.y2 = this.preTapPosition = this.rotate = this.touchStart = this.multipointStart = this.multipointEnd = this.pinch = this.swipe = this.tap = this.doubleTap = this.longTap = this.singleTap = this.pressMove = this.touchMove = this.touchEnd = this.touchCancel = null; - - return null; - } - }; - - if (true) { - module.exports = AlloyFinger; - } else { - window.AlloyFinger = AlloyFinger; - } - })(); - - -/***/ }, -/* 47 */ -/***/ function(module, exports) { - - module.exports = "
\"\"
Omi
" - -/***/ }, -/* 48 */ -/***/ function(module, exports) { - - module.exports = ".head{ position:fixed; height:45px; line-height: 45px; border-bottom: 1px solid #eee; width:100%; background-color:#303030; z-index:100;}ul,li{ display: inline-block;}.logo_box{ width:100px; display: inline-block; text-align:center; line-height: 60px;}.menu a,.logo_box a{ display: inline-block; height:45px; color:#ddd;}.menu{ position: absolute; right:20px;}.menu li{ margin-left:15px;}.logo_box a{ font-size: 34px; font-weight: bold; color: #00bff3; padding: 0px 15px; line-height: 45px; cursor: pointer;}.menu a:hover{ color: white;}.m_menu{ position:fixed; display:none;}@media only screen and (max-width: 768px) { .menu li{ display:none; } .menu .m_show{ display:block; } .logo_box{ display:inline-block; } .head{ text-align:center; } .m_menu{ top:0; left:0; display:block; width:50px; height:50px; padding-top: 6px; } .m_menu img{ width:30px; }}" - -/***/ }, -/* 49 */ -/***/ function(module, exports, __webpack_require__) { - - 'use strict'; - - Object.defineProperty(exports, "__esModule", { - value: true - }); - - var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); - - var _omi = __webpack_require__(2); - - var _omi2 = _interopRequireDefault(_omi); - - var _config = __webpack_require__(4); - - var _config2 = _interopRequireDefault(_config); - - var _omiFinger = __webpack_require__(45); - - var _omiFinger2 = _interopRequireDefault(_omiFinger); - - function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - - function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } - - function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; } - - function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } - - _omiFinger2.default.init(); - - var Pager = function (_Omi$Component) { - _inherits(Pager, _Omi$Component); - - function Pager(data) { - _classCallCheck(this, Pager); - - var _this = _possibleConstructorReturn(this, (Pager.__proto__ || Object.getPrototypeOf(Pager)).call(this, data)); - - _this.activeIndex = 0; - _this.currentIndex = 0; - return _this; - } - - _createClass(Pager, [{ - key: 'updatePager', - value: function updatePager() { - this.data.preMd = null; - this.data.preName = null; - this.data.nextMd = null; - this.data.nextName = null; - var item = _config2.default.menus[this.data.lan][this.activeIndex]; - - var pre = item.list[this.currentIndex - 1]; - if (pre) { - this.data.preMd = pre.md; - this.data.preName = pre.name; - } - var next = item.list[this.currentIndex + 1]; - if (next) { - this.data.nextMd = next.md; - this.data.nextName = next.name; - } - } - }, { - key: 'goto', - value: function goto(name, dir) { - var sidebar = _omi2.default.get('sidebar'); - if (dir === 'next') { - sidebar.children[this.activeIndex].goto(name, ++this.currentIndex); - } else { - sidebar.children[this.activeIndex].goto(name, --this.currentIndex); - } - this.update(); - } - }, { - key: 'handleTap', - value: function handleTap(evt) { - var dir = evt.target.getAttribute('data-dir'); - var name = evt.target.getAttribute('data-name'); - this.goto(name, dir); - } - }, { - key: 'isMobile', - value: function isMobile() { - var browser = { - versions: function () { - var u = navigator.userAgent, - app = navigator.appVersion; - return { //移动终端浏览器版本信息 - trident: u.indexOf('Trident') > -1, //IE内核 - presto: u.indexOf('Presto') > -1, //opera内核 - webKit: u.indexOf('AppleWebKit') > -1, //苹果、谷歌内核 - gecko: u.indexOf('Gecko') > -1 && u.indexOf('KHTML') == -1, //火狐内核 - mobile: !!u.match(/AppleWebKit.*Mobile.*/), //是否为移动终端 - ios: !!u.match(/\(i[^;]+;( U;)? CPU.+Mac OS X/), //ios终端 - android: u.indexOf('Android') > -1 || u.indexOf('Linux') > -1, //android终端或者uc浏览器 - iPhone: u.indexOf('iPhone') > -1, //是否为iPhone或者QQHD浏览器 - iPad: u.indexOf('iPad') > -1, //是否iPad - webApp: u.indexOf('Safari') == -1 //是否web应该程序,没有头部与底部 - }; - }(), - language: (navigator.browserLanguage || navigator.language).toLowerCase() - }; - - if (browser.versions.mobile || browser.versions.ios || browser.versions.android || browser.versions.iPhone || browser.versions.iPad) { - return true; - } - return false; - } - }, { - key: 'render', - value: function render() { - this.updatePager(); - if (this.isMobile()) { - return '\n
\n {{#preName}} \u2190{{preName}}{{/preName}}\n {{#nextName}} {{/nextName}}\n
'; - } else { - return '\n
\n {{#preName}} \u2190{{preName}}{{/preName}}\n {{#nextName}} {{/nextName}}\n
'; - } - } - }, { - key: 'style', - value: function style() { - return __webpack_require__(50); - } - }]); - - return Pager; - }(_omi2.default.Component); - - exports.default = Pager; - -/***/ }, -/* 50 */ -/***/ function(module, exports) { - - module.exports = ".pager { width:85%; height:80px; line-height:80px; position: relative; font-size:16px;}@media only screen and (max-width: 768px) { .pager { width:100%; }}.pre{ position: absolute; left:10px; top:10px;}.next{ position: absolute; right:10px; top:10px;}" - -/***/ } -]); \ No newline at end of file diff --git a/website/js/docs-cn.aef27307.js b/website/js/docs-cn.aef27307.js deleted file mode 100644 index 31edcfffc..000000000 --- a/website/js/docs-cn.aef27307.js +++ /dev/null @@ -1,1401 +0,0 @@ -window.Root ={}; Root.isDev = false;webpackJsonp([0],[ -/* 0 */ -/***/ function(module, exports, __webpack_require__) { - - 'use strict'; - - var _frame = __webpack_require__(1); - - var _frame2 = _interopRequireDefault(_frame); - - function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - - Omi.render(new _frame2.default({ lan: 'cn' }), 'body', true); - -/***/ }, -/* 1 */ -/***/ function(module, exports, __webpack_require__) { - - 'use strict'; - - Object.defineProperty(exports, "__esModule", { - value: true - }); - - var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); - - var _omi = __webpack_require__(2); - - var _omi2 = _interopRequireDefault(_omi); - - var _index = __webpack_require__(3); - - var _index2 = _interopRequireDefault(_index); - - var _index3 = __webpack_require__(38); - - var _index4 = _interopRequireDefault(_index3); - - var _index5 = __webpack_require__(44); - - var _index6 = _interopRequireDefault(_index5); - - var _config = __webpack_require__(4); - - var _config2 = _interopRequireDefault(_config); - - var _index7 = __webpack_require__(49); - - var _index8 = _interopRequireDefault(_index7); - - function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - - function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } - - function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; } - - function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } - - _omi2.default.makeHTML('Content', _index2.default); - _omi2.default.makeHTML('Sidebar', _index4.default); - _omi2.default.makeHTML('Head', _index6.default); - _omi2.default.makeHTML('Pager', _index8.default); - - var Frame = function (_Omi$Component) { - _inherits(Frame, _Omi$Component); - - function Frame(data) { - _classCallCheck(this, Frame); - - return _possibleConstructorReturn(this, (Frame.__proto__ || Object.getPrototypeOf(Frame)).call(this, data)); - } - - _createClass(Frame, [{ - key: 'install', - value: function install() { - var _this2 = this; - - this.setViewport(); - window.onresize = function () { - if (window.innerWidth < 768) { - _this2.refs.main.style.width = '100%'; - } else { - _this2.refs.main.style.width = window.innerWidth - 220 + 'px'; - } - }; - } - }, { - key: 'setViewport', - value: function setViewport() { - if (window.innerWidth < 768) { - this.data.width = '100%'; - } else { - this.data.width = window.innerWidth - 220 + 'px'; - } - } - }, { - key: 'style', - value: function style() { - return '\n \n '; - } - }, { - key: 'render', - value: function render() { - return '
\n \n
\n \n \n
\n \n
'; - } - }]); - - return Frame; - }(_omi2.default.Component); - - exports.default = Frame; - -/***/ }, -/* 2 */, -/* 3 */ -/***/ function(module, exports, __webpack_require__) { - - 'use strict'; - - Object.defineProperty(exports, "__esModule", { - value: true - }); - - var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); - - var _omi = __webpack_require__(2); - - var _omi2 = _interopRequireDefault(_omi); - - var _config = __webpack_require__(4); - - var _config2 = _interopRequireDefault(_config); - - var _highlightLines = __webpack_require__(5); - - var _highlightLines2 = _interopRequireDefault(_highlightLines); - - function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - - function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } - - function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; } - - function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } - - var tpl = __webpack_require__(6); - var css = __webpack_require__(7); - - var Content = function (_Omi$Component) { - _inherits(Content, _Omi$Component); - - function Content(data) { - _classCallCheck(this, Content); - - data = Object.assign({ - lan: 'cn', - name: 'installation' - }, data); - - var _this = _possibleConstructorReturn(this, (Content.__proto__ || Object.getPrototypeOf(Content)).call(this, data)); - - _this.md = new Remarkable({ html: true }); - return _this; - } - - _createClass(Content, [{ - key: 'getMarkDown', - value: function getMarkDown(name, lan) { - return __webpack_require__(8)("./" + lan + "/" + name + ".md"); - } - }, { - key: 'installed', - value: function installed() { - this.initCodeStyle(); - } - }, { - key: 'afterUpdate', - value: function afterUpdate() { - this.initCodeStyle(); - } - }, { - key: 'initCodeStyle', - value: function initCodeStyle() { - var _this2 = this; - - var codes = _omi2.default.$$("code"); - var codeHlNumArr = []; - codes.forEach(function (code) { - hljs.highlightBlock(code); - var arr = code.className.match(/{\S*}/); - var hllNums = null; - if (arr) { - var numArr = arr[0].replace(/[{|}]/g, '').split(','); - hllNums = _this2._arrToNumber(numArr); - } - codeHlNumArr.push(hllNums); - }); - - (0, _highlightLines2.default)(); - - codes.forEach(function (code, index) { - _this2._hll(code, codeHlNumArr[index]); - }); - } - }, { - key: '_arrToNumber', - value: function _arrToNumber(numArr) { - var arr = []; - numArr.forEach(function (item) { - if (item.indexOf('-') !== -1) { - var tempArr = item.split('-'); - var begin = Number(tempArr[0]); - var end = Number(tempArr[1]); - for (var i = begin; i < end + 1; i++) { - arr.push(i); - } - } else { - arr.push(Number(item)); - } - }); - return arr; - } - }, { - key: '_hll', - value: function _hll(code, hllNums) { - var spans = _omi2.default.$$('.line', code); - hllNums && hllNums.forEach(function (num) { - spans[num] && spans[num].classList.add('highlight'); - }); - } - }, { - key: 'render', - value: function render() { - this.data.html = this.md.render(this.getMarkDown(this.data.name, this.data.lan)); - return tpl; - } - }, { - key: 'style', - value: function style() { - return css; - } - }]); - - return Content; - }(_omi2.default.Component); - - exports.default = Content; - -/***/ }, -/* 4 */ -/***/ function(module, exports) { - - 'use strict'; - - Object.defineProperty(exports, "__esModule", { - value: true - }); - var config = { - menus: { - cn: [{ - active: true, - title: '快速开始', - currentIndex: 0, - list: [{ 'name': '安装', md: 'installation' }, { 'name': 'Hello World', md: 'hello_world' }, { 'name': '组件', md: 'components' }, { 'name': '组件通讯', md: 'communication' }, { 'name': '生命周期', md: 'lifecycle' }, { 'name': '事件处理', md: 'events' }, { 'name': '条件判断', md: 'condition' }, { 'name': '循环遍历', md: 'loop' }, { 'name': 'Store体系', md: 'store' }, { 'name': '表单', md: 'form' }, { 'name': '继承', md: 'inherit' }, { 'name': '模板切换', md: 'template' }, { 'name': '获取DOM节点', md: 'get_dom' }, { 'name': '插件体系', md: 'plugin' }, { 'name': 'Omi的理念', md: 'thinking_in_omi' }] - }], - en: [{ - title: 'QUICK START', - active: true, - currentIndex: 0, - list: [{ 'name': 'Installation', md: 'installation' }, { 'name': 'Hello World', md: 'hello_world' }, { 'name': 'Components', md: 'components' }, { 'name': 'Communication', md: 'communication' }, { 'name': 'Lifecycle', md: 'lifecycle' }, { 'name': 'Handling Events', md: 'events' }, { 'name': 'Conditional Rendering', md: 'condition' }, { 'name': 'Loop', md: 'loop' }, { 'name': 'Forms', md: 'form' }, { 'name': 'Inheritance', md: 'inherit' }, { 'name': 'Templates', md: 'template' }, { 'name': 'Get DOM', md: 'get_dom' }, { 'name': 'Plugin', md: 'plugin' }, { 'name': 'Thinking in Omi', md: 'thinking_in_omi' }] - }] - } - }; - - exports.default = config; - -/***/ }, -/* 5 */ -/***/ function(module, exports) { - - 'use strict'; - - Object.defineProperty(exports, "__esModule", { - value: true - }); - - // Iterates through `array`, running `callback` for each `array` element. - function forEach(array, callback) { - var i = -1, - length = array ? array.length : 0; - while (++i < length) { - callback(array[i]); - } - } - - function indexOf(array, elem) { - var i = -1, - length = array ? array.length : 0; - while (++i < length) { - if (array[i] === elem) { - return i; - } - } - } - function highlightLines() { - // TODO: mark as parsed. - forEach(document.querySelectorAll('pre code'), function (element) { - // Trim whitespace if the `data-trim` attribute is present. - if (element.hasAttribute('data-trim') && typeof element.innerHTML.trim == 'function') { - element.innerHTML = element.innerHTML.trim(); - } - - // Highlight code using highlight.js. - hljs.highlightBlock(element); - - // Split highlighted code into lines. - var openTags = [], - reHtmlTag = /<(\/?)span(?:\s+(?:class=(['"])hljs-.*?\2)?\s*|\s*)>/g; - element.innerHTML = element.innerHTML.replace(/(.*?)\r?\n/g, function (_, string) { - if (!string) { - return ' '; - } - var openTag, stringPrepend; - // Re-open all tags that were previously closed. - if (openTags.length) { - stringPrepend = openTags.join(''); - } - // Match all HTML `` tags. - reHtmlTag.lastIndex = 0; - while (openTag = reHtmlTag.exec(string)) { - // If it is a closing tag, remove the opening tag from the list. - if (openTag[1]) { - openTags.pop(); - } - // Otherwise if it is an opening tag, push it to the list. - else { - openTags.push(openTag[0]); - } - } - // Close all opened tags, so that strings can be wrapped with `span.line`. - if (openTags.length) { - string += Array(openTags.length + 1).join(''); - } - if (stringPrepend) { - string = stringPrepend + string; - } - return '' + string + ''; - }); - }); - } - - exports.default = highlightLines; - -/***/ }, -/* 6 */ -/***/ function(module, exports) { - - module.exports = "
{{{html}}}
" - -/***/ }, -/* 7 */ -/***/ function(module, exports) { - - module.exports = ".content{ width: 80%;}h3{ color:#444444;}pre{ border: 1px solid #eee; width: 100%;}li{ text-indent: 20px; list-style:disc inside ;}@media only screen and (max-width: 768px) { .content{ width: 100%; }}" - -/***/ }, -/* 8 */ -/***/ function(module, exports, __webpack_require__) { - - var map = { - "./cn/communication.md": 9, - "./cn/components.md": 10, - "./cn/condition.md": 11, - "./cn/events.md": 12, - "./cn/form.md": 13, - "./cn/get_dom.md": 14, - "./cn/hello_world.md": 15, - "./cn/inherit.md": 16, - "./cn/installation.md": 17, - "./cn/lifecycle.md": 18, - "./cn/loop.md": 19, - "./cn/plugin.md": 20, - "./cn/store.md": 21, - "./cn/template.md": 22, - "./cn/thinking_in_omi.md": 23, - "./en/communication.md": 24, - "./en/components.md": 25, - "./en/condition.md": 26, - "./en/events.md": 27, - "./en/form.md": 28, - "./en/get_dom.md": 29, - "./en/hello_world.md": 30, - "./en/inherit.md": 31, - "./en/installation.md": 32, - "./en/lifecycle.md": 33, - "./en/loop.md": 34, - "./en/plugin.md": 35, - "./en/template.md": 36, - "./en/thinking_in_omi.md": 37 - }; - function webpackContext(req) { - return __webpack_require__(webpackContextResolve(req)); - }; - function webpackContextResolve(req) { - return map[req] || (function() { throw new Error("Cannot find module '" + req + "'.") }()); - }; - webpackContext.keys = function webpackContextKeys() { - return Object.keys(map); - }; - webpackContext.resolve = webpackContextResolve; - module.exports = webpackContext; - webpackContext.id = 8; - - -/***/ }, -/* 9 */ -/***/ function(module, exports) { - - module.exports = "## 组件通讯\r\n\r\n[Omi框架](https://github.com/AlloyTeam/omi)组建间的通讯非常遍历灵活,因为有许多可选方案进行通讯:\r\n\r\n* 通过在组件上声明 data-* 传递给子节点 \r\n* 通过在组件上声明 data 传递给子节点 (支持复杂数据类型的映射)\r\n* 父容器设置 childrenData 自动传递给子节点\r\n* 声明 group-data 传递(支持复杂数据类型的映射)\r\n* 完全面向对象,可以非常容易地拿到对象的实例,之后可以设置实例属性和调用实例的方法\r\n\r\n所以通讯变得畅通无阻,下面一一来举例说明。\r\n\r\n### data-*通讯 \r\n\r\n```js {36}\r\nclass Hello extends Omi.Component {\r\n constructor(data) {\r\n super(data);\r\n }\r\n \r\n style () {\r\n return `\r\n h1{\r\n \tcursor:pointer;\r\n }\r\n `;\r\n }\r\n \r\n handleClick(target, evt){\r\n alert(target.innerHTML);\r\n }\r\n \r\n render() {\r\n return `\r\n
\r\n \t

Hello ,{{name}}!

\r\n
\r\n \t\t`;\r\n }\r\n}\r\n\r\nOmi.makeHTML('Hello', Hello);\r\n\r\nclass App extends Omi.Component {\r\n constructor(data) {\r\n super(data);\r\n }\r\n \r\n render() {\r\n return `\r\n
\r\n \r\n
\r\n `;\r\n }\r\n}\r\n\r\nOmi.render(new App(),\"#container\");\r\n```\r\n\r\n一般data-*用来传递值类型,如string、number。值得注意的是,通过data-*接收到的数据类型都是string,需要自行转成number类型。\r\n通常情况下,data-*能满足我们的要求,但是遇到复杂的数据类型是没有办法通过大量data-*去表达,所以可以通过data通讯,请往下看。\r\n\r\n### data通讯 \r\n\r\n如上面代码所示,通过 data-name=\"Omi\"可以把name传递给子组件。下面的代码也可以达到同样的效果。\r\n\r\n```js {4,10}\r\n...\r\nclass App extends Omi.Component {\r\n constructor(data) {\r\n super(data);\r\n this.helloData = { name : 'Omi' };\r\n }\r\n \r\n render() {\r\n return `\r\n
\r\n \r\n
\r\n `;\r\n }\r\n}\r\n\r\nOmi.render(new App(),\"#container\");\r\n```\r\n\r\n使用data声明,会去组件的instance(也就是this)下找对应的属性,this下可以挂载任意复杂的对象。所以这也就突破了data-*的局限性。\r\n\r\n如果instance下面的某个属性下面的某个属性下面的某个数组的第一个元素的某个属性要作为data传递Hello怎么办?\r\n没关系,data声明是支持复杂类型的,使用方式如下:\r\n\r\n```js\r\n...\r\nclass App extends Omi.Component {\r\n constructor(data) {\r\n super(data);\r\n this.complexData ={\r\n a:{\r\n b:{\r\n c:[\r\n {\r\n e:[{\r\n name:'ComplexData Support1'\r\n },{\r\n name:'ComplexData Support2'\r\n }]\r\n },\r\n {\r\n name: 'ComplexData Support3'\r\n }\r\n ]\r\n }\r\n }\r\n };\r\n }\r\n \r\n render() {\r\n return `\r\n
\r\n \r\n
\r\n `;\r\n }\r\n}\r\n...\r\n```\r\n\r\n点击这里→data映射复杂数据\r\n\r\n### childrenData通讯\r\n\r\n```js\r\n...\r\nclass App extends Omi.Component {\r\n constructor(data) {\r\n super(data);\r\n this.childrenData = [{ name : 'Omi' } , { name : 'dntzhang' }];\r\n }\r\n \r\n render() {\r\n return `\r\n
\r\n \r\n \r\n
\r\n `;\r\n }\r\n}\r\n\r\nOmi.render(new App(),\"#container\");\r\n```\r\n\r\n使用this.childrenData传递data给子组件,childrenData是一个数组类型,所以支持同时给多个组件传递data,与render里面的组件会一一对应上。\r\n\r\n### group-data通讯\r\n\r\nchildrenData的方式可以批量传递数据给组件,但是有很多场景下data的来源不一定非要都从childrenData来,childrenData是个数组,会和组件的顺序一一对应,这就给不同传递方式的data必须全部集中的childrenData中,非常不方便。group-data专门为解决上面的痛点而生,专门是为了给一组组件批量传递data。\r\n\r\n```js\r\nimport Hello from './hello.js';\r\n\r\n\r\nOmi.makeHTML('Hello', Hello);\r\n\r\nclass App extends Omi.Component {\r\n constructor(data) {\r\n super(data);\r\n this.testData = [{name: 'Omi'}, {name: 'dntzhang'}, {name: 'AlloyTeam'}];\r\n }\r\n\r\n render() {\r\n return `\r\n
\r\n \r\n \r\n \r\n
\r\n `;\r\n\r\n }\r\n}\r\n\r\nOmi.render(new App(),\"#container\");\r\n```\r\n\r\n只需要在声明的子组件上标记group-data,就会去当前组件的instance(也就是this)下面找对应的属性,然后根据当前的位置,和对应数组的位置会一一对应起来。\r\n\r\n运行结果如下:\r\n![](http://images2015.cnblogs.com/blog/105416/201702/105416-20170216110701535-1698390390.png)\r\n\r\n点击这里→group-data\r\n\r\n同样group-data支持复杂数据类型的映射,需要注意的是,group-data映射的终点必须是一个数组:\r\n\r\n```js\r\nimport Hello from './hello.js';\r\n\r\n\r\nOmi.makeHTML('Hello', Hello);\r\n\r\nclass App extends Omi.Component {\r\n constructor(data) {\r\n super(data);\r\n this.complexData ={\r\n a:{\r\n b:{\r\n c:[\r\n {\r\n e:[{\r\n name:'ComplexData Support1'\r\n },{\r\n name:'ComplexData Support2'\r\n }]\r\n },\r\n {\r\n name: 'ComplexData Support3'\r\n }\r\n ]\r\n }\r\n }\r\n };\r\n }\r\n\r\n render() {\r\n return `\r\n
\r\n \r\n \r\n
\r\n `;\r\n\r\n }\r\n}\r\n\r\nOmi.render(new App(),\"#container\");\r\n```\r\n\r\n点击这里→group-data映射复杂数据\r\n\r\n### 通过对象实例\r\n\r\n```js {7}\r\n...\r\nclass App extends Omi.Component {\r\n constructor(data) {\r\n super(data);\r\n }\r\n \r\n installed(){\r\n this.hello.data.name = \"Omi\";\r\n this.update()\r\n }\r\n \r\n render() {\r\n return `\r\n
\r\n \r\n
\r\n `;\r\n }\r\n}\r\n\r\nOmi.render(new App(),\"#container\");\r\n```\r\n\r\n### 通过omi-id\r\n\r\n```js {7,14}\r\n...\r\nclass App extends Omi.Component {\r\n constructor(data) {\r\n super(data);\r\n }\r\n \r\n installed(){\r\n Omi.get(\"hello\").data.name = \"Omi\";\r\n this.update()\r\n }\r\n \r\n render() {\r\n return `\r\n
\r\n \r\n
\r\n `;\r\n }\r\n}\r\n\r\nOmi.render(new App(),\"#container\");\r\n```\r\n\r\n通过在组件上声明omi-id,在程序任何地方拿到该对象的实例。这个可以算是跨任意组件通讯神器。\r\n\r\n### 特别强调\r\n\r\n* 通过childrenData或者data方式通讯都是一锤子买卖。后续变更只能通过组件实例下的data属性去更新组件\r\n* 通过data-✼通讯也是一锤子买卖。后续变更只能通过组件实例下的data属性去更新组件。\r\n* 关于data-✼通讯也可以不是一锤子买卖,但是要设置组件实例的dataFirst为false,这样的话data-✼就会覆盖组件实例的data对应的属性\r\n\r\n关于上面的第三条也就是这样的逻辑伪代码:\r\n```js\r\nif(this.dataFirst){\r\n this.data = Object.assign({},data-✼ ,this.data);\r\n}else{\r\n this.data = Object.assign({},this.data, data-✼);\r\n}\r\n```" - -/***/ }, -/* 10 */ -/***/ function(module, exports) { - - module.exports = "## 组件\r\n\r\n[Omi框架](https://github.com/AlloyTeam/omi)完全基于组件体系设计,我们希望开发者可以像搭积木一样制作Web程序,一切皆是组件,组件也可以嵌套子组件形成新的组件,新的组件又可以当作子组件嵌套至任意组件形成新的组件...\r\n\r\n![](http://images2015.cnblogs.com/blog/105416/201702/105416-20170210093427338-1536910080.png)\r\n\r\n## 简单组件\r\n\r\n这里使用Todo的例子来讲解Omi组件体系的使用。\r\n\r\n```js\r\nclass Todo extends Omi.Component {\r\n constructor(data) {\r\n super(data);\r\n }\r\n \r\n add (evt) {\r\n evt.preventDefault();\r\n this.data.items.push(this.data.text);\r\n this.data.text = '';\r\n this.update();\r\n }\r\n\r\n style () {\r\n return `\r\n h3 { color:red; }\r\n button{ color:green;}\r\n `;\r\n }\r\n\r\n handleChange(target){\r\n this.data.text = target.value;\r\n }\r\n\r\n render () {\r\n return `
\r\n

TODO

\r\n
    {{#items}}
  • {{.}}
  • {{/items}}
\r\n
\r\n \r\n \r\n
\r\n
`;\r\n }\r\n}\r\n\r\nOmi.render(new Todo({ items: [] ,text : '' }),\"body\");\r\n```\r\n\r\n组件生成的HTML最终会插入到body中。上面的例子展示了Omi的部分特性:\r\n\r\n- data传递: new Todo(data,..)的data可以直接提供给render方法里的模板\r\n- 局部CSS: h3只对render里的h3生效,不会污染外面的h3;button也是同样的\r\n- 声明式事件绑定: onchange调用的就是组件内的handleChange,this可以拿到当然的DOM元素,还可以拿到当前的event\r\n- 需要手动调用update方法才能更新组件\r\n\r\n这里需要特别强调的是,为了更加的自由和灵活度。Omi没有内置数据变更的自动更新,需要开发者自己调用update方法。\r\n\r\n点击这里→在线试试\r\n\r\n## 组件嵌套\r\n\r\n如果页面超级简单的话,可以没有组件嵌套。但是绝大部分Web网页或者Web应用,需要嵌套定义的组件来完成所有的功能和展示。比如上面的Todo,我们也是可以抽取出List。\r\n这样让程序易维护、可扩展、方便复用。如,我们抽取出List:\r\n\r\n```js\r\nclass List extends Omi.Component {\r\n constructor(data) {\r\n super(data);\r\n }\r\n\r\n render () {\r\n return ``;\r\n }\r\n}\r\n```\r\n\r\n怎么使用这个List?我们需要使用Omi.makeHTML把List制作成可以声明式的标签,在render方法中就能直接使用该标签。如下所示:\r\n\r\n```js\r\nimport List from './list.js';\r\n\r\nOmi.makeHTML('List', List);\r\n\r\nclass Todo extends Omi.Component {\r\n constructor(data) {\r\n super(data);\r\n this.data.length = this.data.items.length;\r\n this.listData = { items : this.data.items };\r\n }\r\n\r\n add (evt) {\r\n evt.preventDefault();\r\n this.list.data.items.push(this.data.text);\r\n this.data.length = this.list.data.items.length;\r\n this.data.text = '';\r\n this.update();\r\n }\r\n\r\n style () {\r\n return `\r\n h3 { color:red; }\r\n button{ color:green;}\r\n `;\r\n }\r\n\r\n handleChange(target){\r\n this.data.text = target.value;\r\n }\r\n\r\n render () {\r\n return `
\r\n

TODO

\r\n \r\n
\r\n \r\n \r\n
\r\n
`;\r\n }\r\n}\r\n```\r\n\r\n* 第3行,通过makeHTML方法把组件制作成可以在render中使用的标签。当然Omi.makeHTML('List', List);也可以写在List组件的代码下面。\r\n* 第9行,在父组件上定义listData属性用来传递给子组件。\r\n* 第34行,在render方法中使用List组件。其中name方法可以让你在代码里通过this快速方法到该组件的实例。data=\"listData\"可以让你把this.listData传递给子组件。\r\n\r\n需要注意的是,父组件的this.listData会被通过Object.assign浅拷贝到子组件。\r\n这样做的目的主要是希望以后DOM的变更都尽量修改子组件自身的data,然后再调用其update方法,而不是去更改父组件的listData。\r\n\r\n关于Omi组件通讯其实有4种方案,这个后续教程会专门来讲。\r\n\r\n点击这里→在线试试\r\n" - -/***/ }, -/* 11 */ -/***/ function(module, exports) { - - module.exports = "## 条件判断\r\n\r\n我们经常需要根据不同的状态呈现不同的界面,比如有的用户是vip要显示vip的Logo。Omi有许多种方式满足你的要求。\r\n\r\n### 方式一\r\n\r\n```js\r\nclass ConditionTest extends Omi.Component {\r\n constructor(data) {\r\n super(data);\r\n }\r\n\r\n render () {\r\n return `{{#isVip}}\r\n
you are VIP.
\r\n {{/isVip}}\r\n {{^isVip}}\r\n
you are not VIP.
\r\n {{/isVip}}`;\r\n }\r\n}\r\n```\r\n\r\n上面完全使用mustachejs的条件判断的语法。当然Omi不强制你使用mustachejs。你可以是omi.lite.js,然后重写Omi.template方法去使用任意你喜爱的模板引擎。\r\n\r\n### 方式二\r\n\r\n```js\r\nclass ConditionTest extends Omi.Component {\r\n constructor(data) {\r\n super(data);\r\n }\r\n\r\n render () {\r\n if(this.data.isVip){\r\n return '
you are VIP.
';\r\n }else{\r\n return '
you are not VIP.
';\r\n }\r\n }\r\n}\r\n```\r\n\r\nrender就是提供了很好的可编程性,里面可以写任意js逻辑代码。对了,差点忘了,style方法里面也可以写js逻辑的。\r\n\r\n```js\r\nclass ConditionTest extends Omi.Component {\r\n constructor(data) {\r\n super(data);\r\n }\r\n\r\n style (){\r\n if(this.data.isVip){\r\n return 'div{ color : red; }';\r\n }else{\r\n return 'div{ color : green; }';\r\n }\r\n }\r\n\r\n render () {\r\n if(this.data.isVip){\r\n return '
you are VIP.
';\r\n }else{\r\n return '
you are not VIP.
';\r\n }\r\n }\r\n}\r\n```\r\n\r\n### 方式三\r\n\r\n```js\r\nclass ConditionTest extends Omi.Component {\r\n constructor(data) {\r\n super(data);\r\n }\r\n\r\n render() {\r\n return `\r\n ${this.data.isVip\r\n ?\"
you are VIP.
\"\r\n :\"
you are not VIP.
\"\r\n \t\t}\r\n `;\r\n }\r\n}\r\n```\r\n\r\n当然可以使用${ }里面写javascript代码进行输出。" - -/***/ }, -/* 12 */ -/***/ function(module, exports) { - - module.exports = "## 事件处理\r\n\r\nOmi的事件分内置事件和自定义事件。在内置事件处理方面巧妙地利用了浏览器自身的管线机制,可以通过event和this轻松拿到事件实例和触发该事件的元素。\r\n\r\n### 内置事件\r\n\r\n什么算内置事件?只要下面正则能匹配到就算内置事件。\r\n\r\n```js\r\non(abort|blur|cancel|canplay|canplaythrough|change|click|close|contextmenu|cuechange|dblclick|drag|dragend|dragenter|dragleave|dragover|dragstart|drop|durationchange|emptied|ended|error|focus|input|invalid|keydown|keypress|keyup|load|loadeddata|loadedmetadata|loadstart|mousedown|mouseenter|mouseleave|mousemove|mouseout|mouseover|mouseup|mousewheel|pause|play|playing|progress|ratechange|reset|resize|scroll|seeked|seeking|select|show|stalled|submit|suspend|timeupdate|toggle|volumechange|waiting|autocomplete|autocompleteerror|beforecopy|beforecut|beforepaste|copy|cut|paste|search|selectstart|wheel|webkitfullscreenchange|webkitfullscreenerror|touchstart|touchmove|touchend|touchcancel|pointerdown|pointerup|pointercancel|pointermove|pointerover|pointerout|pointerenter|pointerleave)\r\n```\r\n\r\n内置事件怎么绑定?如下所示:\r\n\r\n```js\r\nclass EventTest extends Omi.Component {\r\n constructor(data) {\r\n super(data);\r\n }\r\n\r\n handleClick(dom, evt){\r\n alert(dom.innerHTML);\r\n }\r\n\r\n render () {\r\n return `
Hello, Omi!
`;\r\n }\r\n}\r\n```\r\n\r\n### 自定义事件\r\n\r\n开发者自己定义的组件的事件,称为自定义事件,自定义事件必须以on开头,即onXXXX的格式,不然Omi识别不到。这里拿分页作为例子:\r\n\r\n```js\r\nimport Omi from '../../src/index.js';\r\nimport Pagination from './pagination.js';\r\nimport Content from './content.js';\r\n\r\nOmi.makeHTML('Pagination', Pagination);\r\nOmi.makeHTML('Content', Content);\r\n\r\nclass Main extends Omi.Component {\r\n constructor(data) {\r\n super(data);\r\n }\r\n\r\n installed(){\r\n this.content.goto(this.pagination.data.currentPage+1);\r\n }\r\n \r\n handlePageChange(index){\r\n this.content.goto(index+1);\r\n }\r\n\r\n render () {\r\n return `
\r\n

Pagination Example

\r\n \r\n \r\n
`;\r\n }\r\n}\r\n\r\nOmi.render( new Main(),'body');\r\n```\r\n\r\n如上面的onPageChange就是自定义事件,触发会执行handlePageChange。onPageChange方法是在Pagination中执行:\r\n\r\n```js\r\nimport Omi from '../../src/index.js';\r\n\r\nclass Pagination extends Omi.Component {\r\n ...\r\n ...\r\n ...\r\n linkTo: \"#\",\r\n prevText: \"Prev\",\r\n nextText: \"Next\",\r\n ellipseText: \"...\",\r\n prevShow: true,\r\n nextShow: true,\r\n onPageChange: function () { return false; }\r\n }, this.data);\r\n\r\n this.pageNum = Math.ceil(this.data.total / this.data.pageSize);\r\n }\r\n \r\n goto (index,evt) {\r\n evt.preventDefault();\r\n this.data.currentPage=index;\r\n this.update();\r\n this.data.onPageChange(index);\r\n }\r\n ...\r\n ...\r\n ...\r\n}\r\n```\r\n\r\n这里取了Pagination组件的部分代码。高亮的就是执行onPageChange的地方。\r\n\r\n### 相关地址\r\n\r\n* [演示地址](http://alloyteam.github.io/omi/example/pagination/)\r\n* [源码地址](https://github.com/AlloyTeam/omi/tree/master/example/pagination)\r\n" - -/***/ }, -/* 13 */ -/***/ function(module, exports) { - - module.exports = "## 表单\r\n\r\nOmi让一些表单操控起来更加方便,特别是select!\r\n\r\n### select标签\r\n\r\n以前,我们需要像如下的方式选中一个选项:\r\n\r\n```html\r\n\r\n```\r\n\r\n第三个option由于加上了selected,所有会被选中。这样带来的问题就是,开发者写的程序可能要操遍历每个option。而使用Omi,你只需要这样子:\r\n\r\n```html\r\n\r\n```\r\n\r\n这样就能达到同样的效果。比如你想选择第一项:\r\n\r\n```html\r\n\r\n```\r\n\r\n是不是非常方便?\r\n\r\n### 举个例子\r\n\r\n```js\r\nclass FormTest extends Omi.Component {\r\n constructor(data) {\r\n super(data);\r\n \r\n }\r\n\r\n handleChange(target){\r\n console.log(target.value)\r\n this.data.value = target.value;\r\n }\r\n\r\n handleSubmit(evt) {\r\n alert('Your favorite flavor is: ' + this.data.value);\r\n evt.preventDefault();\r\n }\r\n \r\n render () {\r\n return `\r\n
\r\n \r\n \r\n
`;\r\n }\r\n}\r\n\r\nOmi.render(new FormTest({ value: 'mango' }),'#container');\r\n```\r\n\r\n点击这里→在线试试" - -/***/ }, -/* 14 */ -/***/ function(module, exports) { - - module.exports = "## 获取DOM节点\r\n\r\n虽然绝大部分情况下,开发者不需要去查找获取DOM,但是还是有需要获取DOM的场景,所以Omi提供了方便获取DOM节点的方式。\r\n\r\n### ref和refs\r\n\r\n```js\r\nclass Hello extends Omi.Component {\r\n constructor(data) {\r\n super(data);\r\n }\r\n \r\n style () {\r\n return `\r\n h1{\r\n cursor:pointer;\r\n }\r\n `;\r\n }\r\n \r\n handleClick(){\r\n alert(this.refs.abc.innerHTML);\r\n }\r\n \r\n render() {\r\n return `\r\n
\r\n

Hello ,{{name}}!

\r\n
\r\n `;\r\n }\r\n}\r\n\r\nOmi.render(new Hello({ name : \"Omi\" }),\"#container\");\r\n```\r\n\r\n可以看到通过在HTML中标记ref为abc,那么就通过this.refs.abc访问到该DOM节点。\r\n\r\n点击这里→在线试试" - -/***/ }, -/* 15 */ -/***/ function(module, exports) { - - module.exports = "## Hello World\r\n\r\n你可以使用ES6+或者ES5的方式编写Omi程序来搭建你的Web程序。\r\n\r\n### Hello World with ES6+\r\n\r\n你可以使用 [webpack](https://webpack.github.io/) 打包工具,webpack会把你的模块代码打成一个很小的包,优化加载时间。使用[babel](http://babeljs.io/),让你立刻马上使用ES6+来编写你的web程序。你只需要在webpack配置的module设置好[babel-loader](https://github.com/babel/babel-loader)便可。\r\n\r\n一个Omi的简短的例子如下所示:\r\n\r\n```js\r\nimport Omi from './omi.js';\r\n\r\nclass Hello extends Omi.Component {\r\n constructor(data) {\r\n super(data);\r\n }\r\n \r\n style () {\r\n //注意,return中的包裹是可选的。主要是为了识别为JSX文件可以有CSS高亮。\r\n return `\r\n \r\n `;\r\n }\r\n \r\n handleClick(target, evt){\r\n alert(target.innerHTML);\r\n }\r\n \r\n render() {\r\n return `\r\n
\r\n

Hello ,{{name}}!

\r\n
\r\n `;\r\n }\r\n}\r\n\r\nOmi.render(new Hello({ name : \"Omi\" }),\"#container\");\r\n```\r\n\r\n组件生成的HTML最终会插入到#container中。上面的例子展示了Omi的部分特性:\r\n\r\n- data传递: new Hello(data,..)的data可以直接提供给render方法里的模板\r\n- 局部CSS: h1只对render里的h1生效,不会污染外面的h1\r\n- 声明式事件绑定: onclick调用的就是组件内的handleClick,this可以拿到当前的DOM元素,还可以拿到当前的event\r\n\r\n点击这里→在线试试\r\n\r\n你可以使用Omi.makeHTML来生成组件标签用于嵌套。\r\n```js\r\n Omi.makeHTML('Hello', Hello);\r\n```\r\n那么你就在其他组件中使用,如\r\n```js\r\n ...\r\n render() {\r\n return `\r\n
\r\n
Test
\r\n \r\n
\r\n `;\r\n }\r\n ...\r\n```\r\n\r\n点击这里→在线试试\r\n\r\n### Hello World with ES5\r\n\r\n当然Omi没有抛弃ES5的用户。你可以使用ES5的方式编写Omi。如,在你的HTML中引用omi.js:\r\n\r\n```html\r\n\r\n```\r\n\r\n然后:\r\n\r\n```js\r\nvar Hello = Omi.create(\"Hello\", {\r\n style: function () {\r\n return \"h1{ cursor:pointer }\";\r\n },\r\n \r\n handleClick: function (dom) {\r\n alert(dom.innerHTML)\r\n },\r\n \r\n render: function () {\r\n return '
\\\r\n

\\\r\n Hello ,{{name}}!\\\r\n

\\\r\n
'\r\n }\r\n});\r\n\r\nvar Test = Omi.create(\"Test\", {\r\n render: function () {\r\n return '
\\\r\n
Test
\\\r\n \\\r\n
'\r\n }\r\n});\r\n\r\nOmi.render(new Test(),'#container');\r\n```\r\n当然除了在HTML引入脚本,你还可以使用AMD、CMD或者CommonJS的方式引入Omi,这里就不再一一列举。\r\n\r\n需要注意的是,Omi.create的第一个参数Hello是用来生成Tag Name的。你可以在其他地方嵌入你的组件。如:\r\n\r\n```js\r\n ...\r\n render:function() {\r\n return '
\\\r\n \\\r\n
Test XXXX
\\\r\n \\\r\n
';\r\n }\r\n ...\r\n```\r\n\r\n点击这里→在线试试\r\n" - -/***/ }, -/* 16 */ -/***/ function(module, exports) { - - module.exports = "## 继承\r\n\r\n通过继承机制,可以利用已有的数据类型来定义新的数据类型。所定义的新的数据类型不仅拥有新定义的成员,而且还同时拥有旧的成员。我们称已存在的用来派生新类的类为基类,又称为父类。由已存在的类派生出的新类称为派生类,又称为子类。\r\n\r\n### 举个例子\r\n\r\n```js\r\nclass Hello extends Omi.Component {\r\n constructor(data) {\r\n super(data);\r\n }\r\n \r\n style () {\r\n return `\r\n div{\r\n cursor:pointer;\r\n }\r\n `;\r\n }\r\n \r\n handleClick(target, evt){\r\n alert(target.innerHTML);\r\n }\r\n \r\n render() {\r\n return '
Hello {{name}}!
'\r\n }\r\n}\r\n\r\nclass SubHello extends Hello {\r\n constructor(data) {\r\n super(data);\r\n }\r\n}\r\n\r\nOmi.render(new SubHello({ name : 'Omi' }),'#container');\r\n```\r\n\r\n点击这里→在线试试\r\n\r\n### ES5下的继承\r\n\r\n```js\r\nvar Hello = Omi.create(\"Hello\",{\r\n render:function(){\r\n return '
Hello {{name}}!
'\r\n }\r\n})\r\n\r\nvar SubHello = Omi.create(\"SubHello\",Hello,{ });\r\n\r\n\r\nOmi.render(new SubHello({ name : 'Omi' }),'#container');\r\n```\r\n\r\n点击这里→在线试试" - -/***/ }, -/* 17 */ -/***/ function(module, exports) { - - module.exports = "## 安装\n\n[Omi](https://github.com/AlloyTeam/omi)(读音 / [ˈomɪ] /, 汉字类似于 欧米) 是一款用于创建用户界面的组件化框架,开放并且现代,故得名:Omi。\n\n### 安装 Omi\n\n我们推荐使用 [npm](https://www.npmjs.com/) 来管理你的前端依赖.\n\n通过npm安装Omi,你只需要执行下面的命令:\n\n``` js\n$ npm install omi\n```\n\n## omi-cli\n\n你也可以通过omi-cli去初始化你的项目:\n\n``` js\n$ npm install omi-cli -g //安装cli\n$ omi init your_project_name //初始化项目,你也可以在一个空的文件夹下执行 omi init\n$ cd your_project_name //如果你是在空文件夹下执行的 omi init。请无视这条命令\n$ npm run dev //开发\n$ npm run dist //部署发布\n```" - -/***/ }, -/* 18 */ -/***/ function(module, exports) { - - module.exports = "## 生命周期\r\n\r\n|name |avatars |company | \r\n|---|---|---|\r\n| constructor | 构造函数 | new的时候 |\r\n| install | 初始化安装,这可以拿到用户传进的data进行处理 | 实例化 |\r\n| installed | 安装完成,HTML已经插入页面之后执行 | 实例化 |\r\n| uninstall | 卸载组件。执行remove方法会触发该事件 | 销毁时 |\r\n| beforeUpdate | 更新前 | 存在期 |\r\n| afterUpdate | 更新后 | 存在期 |\r\n\r\n## 示意图\r\n\r\n![lc](http://images2015.cnblogs.com/blog/105416/201703/105416-20170322083548924-1871234168.jpg)\r\n \r\n### 举个例子\r\n\r\n```js\r\nclass Timer extends Omi.Component {\r\n constructor(data) {\r\n super(data);\r\n }\r\n\r\n install () {\r\n this.data = {secondsElapsed: 0};\r\n }\r\n\r\n tick() {\r\n this.data.secondsElapsed++;\r\n this.update();\r\n }\r\n\r\n installed(){\r\n this.interval = setInterval(() => this.tick(), 1000);\r\n }\r\n\r\n uninstall() {\r\n clearInterval(this.interval);\r\n }\r\n\r\n\r\n style () {\r\n return `\r\n .num { color:red; }\r\n `;\r\n }\r\n\r\n render () {\r\n return `
Seconds Elapsed: {{secondsElapsed}}
`;\r\n }\r\n}\r\n```\r\n\r\n点击这里→在线试试\r\n" - -/***/ }, -/* 19 */ -/***/ function(module, exports) { - - module.exports = "## 循环遍历\r\n\r\n下面介绍mustache.js的方式和javascript遍历的方式。\r\n\r\n### 方式一\r\n\r\n```js\r\nclass List extends Omi.Component {\r\n constructor(data) {\r\n super(data);\r\n }\r\n\r\n render () {\r\n return `
\r\n
    \r\n {{#items}} \r\n
  • {{text}}
  • \r\n {{/items}}\r\n
\r\n
`;\r\n }\r\n}\r\n\r\nOmi.render(new List({\r\n items: [\r\n {id: 1, text: 'Omi'},\r\n {id: 2, text: 'dntzhang'},\r\n {id: 3, text: 'AlloyTeam'}\r\n ]\r\n}),\"body\");\r\n```\r\n\r\nmustache.js更详细的循环遍历使用可看[https://github.com/janl/mustache.js#non-empty-lists](https://github.com/janl/mustache.js#non-empty-lists)。 比如还支持:\r\n\r\n* 如果items的每一项是字符串,可以直接**{{.}}**的方式来输出每一项\r\n* 循环的时候调用定义好的函数\r\n\r\n点击这里→在线试试\r\n\r\n### 方式二\r\n\r\n既然ES6+了,当然可以使用${ }以及Array的map方法: \r\n\r\n```js\r\nclass List extends Omi.Component {\r\n constructor(data) {\r\n super(data);\r\n }\r\n\r\n render() {\r\n return `
\r\n
    \r\n ${this.data.items.map(item =>\r\n `
  • ${item.text}
  • `\r\n ).join('')}\r\n
\r\n
`;\r\n }\r\n}\r\n\r\nOmi.render(new List({\r\n items: [\r\n {id: 1, text: 'Omi'},\r\n {id: 2, text: 'dntzhang'},\r\n {id: 3, text: 'AlloyTeam'}\r\n ]\r\n}),\"body\");\r\n```\r\n\r\n你将在页面看到如下效果:\r\n\r\n![pv](http://images2015.cnblogs.com/blog/105416/201701/105416-20170122095724129-2059595233.png)\r\n\r\n点击这里→在线试试\r\n\r\n如果想在循环里加些判断呢?比如需要把id为偶数的隐藏起来:\r\n\r\n```js\r\nrender() {\r\n return `
\r\n
    \r\n ${this.data.items.map(item =>\r\n `
  • ${item.text}
  • `\r\n ).join('')}\r\n
\r\n
`;\r\n}\r\n```\r\n\r\n所以模板字符串还是非常方便,随着ES继续发展下去,模板引擎估计会慢慢消失。所以omi提供了 omi.lite.js 版本不包含任何模板引擎。" - -/***/ }, -/* 20 */ -/***/ function(module, exports) { - - module.exports = "## 插件体系\r\n\r\n[Omi](https://github.com/AlloyTeam/omi)是Web组件化框架,怎么又来了个插件的概念?\r\n\r\n可以这么理解: Omi插件体系可以赋予dom元素一些能力,并且可以和组件的实例产生关联。\r\n\r\n### omi-drag\r\n\r\n且看这个例子:\r\n\r\n点击这里→在线试试\r\n\r\n```js\r\nimport OmiDrag from './omi-drag.js';\r\n\r\nOmiDrag.init();\r\n\r\nclass App extends Omi.Component {\r\n constructor(data) {\r\n super(data);\r\n }\r\n\r\n render() {\r\n return `\r\n
\r\n
Drag Me
\r\n
\r\n `;\r\n\r\n }\r\n\r\n style(){\r\n return `\r\n .test{\r\n width:100px;\r\n height:100px;\r\n color:white;\r\n line-height:90px;\r\n text-align:center;\r\n background-color:#00BFF3;\r\n }\r\n `\r\n }\r\n}\r\n\r\nOmi.render(new App(),\"#container\");\r\n```\r\n\r\n如上面的代码所示,通过在div上标记omi-drag,这个div就能够被用户使用鼠标拖拽。我们称omi-drag.js为omi插件。\r\n是不是非常方便?那么这个omi-drag是怎么实现的?\r\n\r\n## Omi.extendPlugin\r\n\r\n核心方法: Omi.extendPlugin( pluginName, handler )\r\n\r\n下面的代码就是展示了如何通过 Omi.extendPlugin 赋予dom拖拽的能力:\r\n\r\n```js\r\n;(function () {\r\n\r\n var OmiDrag = {};\r\n var Omi = typeof require === 'function'\r\n ? require('omi')\r\n : window.Omi;\r\n\r\n OmiDrag.init = function(){\r\n Omi.extendPlugin('omi-drag',function(dom, instance){\r\n dom.style.cursor='move';\r\n var isMouseDown = false,\r\n preX = null,\r\n preY = null,\r\n currentX = null,\r\n currentY = null,\r\n translateX = 0,\r\n translateY = 0;\r\n\r\n dom.addEventListener('mousedown',function(evt){\r\n isMouseDown = true;\r\n preX = evt.pageX;\r\n preY = evt.pageY;\r\n evt.stopPropagation();\r\n },false);\r\n\r\n window.addEventListener('mousemove',function(evt){\r\n if(isMouseDown){\r\n currentX = evt.pageX;\r\n currentY = evt.pageY;\r\n if(preX != null){\r\n translateX += currentX - preX;\r\n translateY += currentY - preY;\r\n dom.style.transform = 'translateX('+translateX+'px) translateY('+translateY+'px)';\r\n }\r\n preX = currentX;\r\n preY = currentY;\r\n evt.preventDefault();\r\n }\r\n },false);\r\n\r\n window.addEventListener('mouseup',function(){\r\n isMouseDown = false;\r\n preX = preY = currentX = currentY = null;\r\n },false);\r\n });\r\n }\r\n\r\n OmiDrag.destroy = function(){\r\n delete Omi.plugins['omi-drag'];\r\n };\r\n\r\n if (typeof exports == \"object\") {\r\n module.exports = OmiDrag;\r\n } else if (typeof define == \"function\" && define.amd) {\r\n define([], function(){ return OmiDrag });\r\n } else {\r\n window.OmiDrag = OmiDrag;\r\n }\r\n\r\n})();\r\n```\r\n\r\n方法: Omi.extendPlugin( pluginName, handler )\r\n\r\n其中pluginName为插件的名称\r\n其中handler为处理器。handler可以拿到标记了pluginName的dom以及dom所在的组件的实例,即 dom 和 instance。\r\n\r\n通过 Omi.extendPlugin,可以赋予dom元素一些能力,也可以和组件的实例(instance)产生关联。\r\n但是上面的例子没有和instance产生关联,我们接下来试试:\r\n\r\n## 关联instance\r\n\r\n我们想在组件里面能够监听到move并且执行回调。如下:\r\n\r\n```js\r\n...\r\n...\r\nmoveHandler(){\r\n console.log('moving');\r\n}\r\n\r\nrender() {\r\n return `\r\n
\r\n
Drag Me
\r\n
\r\n `;\r\n}\r\n...\r\n```\r\n\r\n主要被拖动过程中,moveHandler就不断地被执行。插件代码需要修改:\r\n\r\n```js\r\n...\r\nwindow.addEventListener('mousemove',function(evt){\r\n if(isMouseDown){\r\n currentX = evt.pageX;\r\n currentY = evt.pageY;\r\n if(preX != null){\r\n translateX += currentX - preX;\r\n translateY += currentY - preY;\r\n dom.style.transform = 'translateX('+translateX+'px) translateY('+translateY+'px)';\r\n }\r\n preX = currentX;\r\n preY = currentY;\r\n evt.preventDefault();\r\n instance.moveHandler(evt);\r\n }\r\n},false);\r\n```\r\n\r\n我们在里面增加了instance.moveHandler(evt);方法,用来执行组件实例上的moveHandler方法。\r\n这样的话:就是组件的实例(instance)产生关联。但是还是有问题?如果标记了多个omi-drag 就会有问题!如:\r\n\r\n```js\r\n...\r\nrender() {\r\n return `\r\n
\r\n
Drag Me
\r\n
Drag Me
\r\n
\r\n `;\r\n}\r\n...\r\n```\r\n\r\n通常我们系统每个omi-drag都能对应一个回调函数,如:\r\n\r\n```js\r\n...\r\n...\r\nmoveHandlerA(){\r\n console.log('moving');\r\n}\r\n\r\nmoveHandlerB(){\r\n console.log('moving');\r\n}\r\n\r\nrender() {\r\n return `\r\n
\r\n
Drag Me A
\r\n
Drag Me B
\r\n
\r\n `;\r\n}\r\n...\r\n```\r\n\r\n怎么办?怎么实现?有办法!通过dom传递数据给插件。\r\n\r\n## 传递数据\r\n\r\n先来看最后实现的效果:\r\n\r\n```js\r\n...\r\n...\r\nmoveHandlerA(){\r\n console.log('moving');\r\n}\r\n\r\nmoveHandlerB(){\r\n console.log('moving');\r\n}\r\n\r\nrender() {\r\n return `\r\n
\r\n
Drag Me A
\r\n
Drag Me B
\r\n
\r\n `;\r\n}\r\n...\r\n```\r\n\r\nomi-drag修改的地方:\r\n\r\n```js\r\n...\r\nvar handlerName = dom.getAttribute('dragMove');\r\n\r\nwindow.addEventListener('mousemove',function(evt){\r\n if(isMouseDown){\r\n currentX = evt.pageX;\r\n currentY = evt.pageY;\r\n if(preX != null){\r\n translateX += currentX - preX;\r\n translateY += currentY - preY;\r\n dom.style.transform = 'translateX('+translateX+'px) translateY('+translateY+'px)';\r\n }\r\n preX = currentX;\r\n preY = currentY;\r\n evt.preventDefault();\r\n instance[handlerName](evt);\r\n }\r\n},false);\r\n...\r\n```\r\n\r\n* 通过 var handlerName = dom.getAttribute('dragMove') 拿到dom上声明的dragMove\r\n* 通过 instance[handlerName](evt) 去执行对应的方法\r\n\r\n点击这里→在线试试\r\n\r\n## 更多插件\r\n\r\n* [omi-finger](https://github.com/AlloyTeam/omi/tree/master/plugins/omi-finger) Omi的[AlloyFinger](https://github.com/AlloyTeam/AlloyFinger)插件,支持各种触摸事件和手势\r\n* [omi-transform](https://github.com/AlloyTeam/omi/tree/master/plugins/omi-transform) Omi的[transformjs](http://alloyteam.github.io/AlloyTouch/transformjs/)插件,快速方便地设置DOM的CSS3 Transform属性\r\n* [omi-touch](https://github.com/AlloyTeam/omi/tree/master/plugins/omi-touch) Omi的[AlloyTouch](https://github.com/AlloyTeam/AlloyTouch)插件,Omi项目的触摸运动解决方案(支持触摸滚动、旋转、翻页、选择等等)\r\n* [omi-jquery-date-picker](https://github.com/AlloyTeam/omi/tree/master/plugins/omi-jquery-date-picker) Omi的时间选择插件,支持各种时间或者时间区域选择\r\n" - -/***/ }, -/* 21 */ -/***/ function(module, exports) { - - module.exports = "## Store 体系\r\n\r\n先说说Store系统是干什么的!\r\n\r\n当我们组件之间,拥有共享的数据的时候,经常需要进行组件通讯。在Omi框架里,组件通讯非常方便:\r\n\r\n* 通过在组件上声明 data-* 传递给子节点\r\n* 通过在组件上声明 data 传递给子节点 (支持复杂数据类型的映射)\r\n* 声明 group-data 把数组里的data传给一堆组件传递(支持复杂数据类型的映射)\r\n* 完全面向对象,可以非常容易地拿到对象的实例,之后可以设置实例属性和调用实例的方法。比如(标记name、标记omi-id)\r\n\r\n当然你也可以使用event emitter / pubsub库在组件之间通讯,比如这个只有 200b 的超小库[mitt](https://github.com/developit/mitt) 。但是需要注意mitt兼容到IE9+,Omi兼容IE8。\r\n\r\n虽然组件通讯非常方便,但是各种数据传递、组件实例互操作或者循环依赖,让代码非常难看且难以维护。所以:\r\n\r\nOmi.Store是为了让 组件通讯几乎绝迹 。虽然:\r\n\r\n\tRedux 的作者 Dan Abramov 说过:Flux 架构就像眼镜:您自会知道什么时候需要它。\r\n\t\r\n但是,我不会告诉你\r\n\r\n\tOmi Store 系统就像眼镜:您自会知道什么时候需要它。\r\n\t\r\n因为,Omi Store使用足够简便,对架构入侵性极极极小(3个极代表比极小还要小),让数据、数据逻辑和UI展现彻底分离,所以我的观点是:\r\n\r\n\t如果使用Omi,请使用Omi.Store架构。\r\n\t\r\n比如连这个[Todo例子](https://github.com/AlloyTeam/omi/tree/master/example/todo-store)都能使用Omi.Store架构。如果连复杂度都达不到Todo,那么Omi其实都没有必要使用,你可能只需要一个模板引擎便可。\r\n\r\n\r\n### 定义 Omi.Store\r\n\r\nOmi.Store是基类,我们可以继承Omi.Store来定义自己的Store,比如下面的TodoStore。\r\n\r\n```js\r\nimport Omi from 'omi'\r\n\r\nclass TodoStore extends Omi.Store {\r\n constructor(data , isReady) {\r\n super(isReady)\r\n\r\n this.data = Object.assign({\r\n items:[],\r\n text:'',\r\n length:0\r\n },data)\r\n\r\n this.data.length = this.data.items.length\r\n }\r\n\r\n add(){\r\n this.data.items.push(this.data.text)\r\n this.data.text = \"\"\r\n this.data.length = this.data.items.length\r\n this.update()\r\n }\r\n\r\n updateText(text){\r\n this.data.text = text\r\n }\r\n\r\n clear(){\r\n this.data.items.length = 0\r\n this.data.length = 0\r\n this.data.text = \"\"\r\n this.update()\r\n }\r\n}\r\n\r\nexport default TodoStore\r\n```\r\n\r\nTodoStore定义类数据的基本格式和数据模型的逻辑。\r\n比如 this.data 就是数据的基本格式, \r\n\r\n```js\r\n{\r\n items:[],\r\n text:'',\r\n length:0\r\n}\r\n```\r\n\r\nadd,updateText和clear就是数据模型的逻辑。\r\n\r\n### 使用 Omi.Store\r\n\r\n通过 new 关键字来使用TodoStore对象的实例。\r\n\r\n```js\r\nlet store = new TodoStore({ /* 初始化配置 */ })\r\n```\r\n\r\n上面可以传入一些初始化配置信息,store里面便包含了整个应用程序共享的状态数据以及相关数据逻辑方法(add,updateText,clear)。\r\n\r\n当然,这些初始化配置信息可能是异步拉取的。所以,有两种方法解决异步拉取store配置的问题:\r\n\r\n* 先let store = new TodoStore(),再Omi.render,组件内部监听store.ready,拉取数据更改store的data信息,然后执行store.beReady()\r\n* 拉取数据,然后new TodoStore(),再Omi.render\r\n\r\n### 根组件注入 store\r\n\r\n为了让组件树能够使用到 store,可以通过Omi.render的第三个参数给根组件注入 store:\r\n\r\n```js\r\nOmi.render(new Todo(),'body',{\r\n store: store\r\n});\r\n```\r\n\r\n当然ES2015已经允许你这样写了:\r\n\r\n```js\r\nOmi.render(new Todo(),'body',{\r\n store\r\n});\r\n```\r\n\r\n两份代码同样的效果。\r\n\r\n通过Omi.render注入之后,在组件树的所有组件都可以通过 this.$store 访问到 store。\r\n\r\n### 简便的 beforeRender\r\n\r\nbeforeRender这个函数,是生命周期的一部分。且看下面这张图:\r\n\r\n![beforeRender](http://images2015.cnblogs.com/blog/105416/201703/105416-20170322083548924-1871234168.jpg)\r\n\r\n在render之前,会去执行beforeRender方法。所以可以利用该方法写store的data到组件data的转换逻辑。比如:\r\n\r\n```js\r\nclass List extends Omi.Component {\r\n beforeRender(){\r\n this.data.items = this.$store.data.items\r\n }\r\n\r\n render () {\r\n return ` `\r\n }\r\n}\r\n```\r\n\r\n再比如todo使用length和text:\r\n\r\n```js\r\nimport Omi from '../../src/index.js';\r\nimport List from './list.js';\r\n\r\nOmi.makeHTML('List', List);\r\n\r\nclass Todo extends Omi.Component {\r\n\r\n install(){\r\n this.$store.ready(()=>this.update())\r\n }\r\n\r\n beforeRender(){\r\n this.data.length = this.$store.data.items.length\r\n this.data.text = this.$store.text\r\n }\r\n\r\n add (evt) {\r\n evt.preventDefault();\r\n this.$store.add();\r\n }\r\n\r\n handleChange(target){\r\n this.$store.updateText(target.value);\r\n }\r\n\r\n render () {\r\n return `
\r\n

TODO

\r\n \r\n
\r\n \r\n \r\n
\r\n
`;\r\n }\r\n}\r\n\r\nexport default Todo;\r\n```\r\n\r\n为什么要去写beforeRender方法?因为render只会使用this.data去渲染页面而不会去使用this.$store.data,所以需要把数据转移到组件的this.data下。这样组件既能使用自身的data,也能使用全局放this.$store.data了。\r\n\r\n更为详细的代码可以[点击这里](https://github.com/AlloyTeam/omi/tree/master/example/todo-store)。" - -/***/ }, -/* 22 */ -/***/ function(module, exports) { - - module.exports = "## 模板切换\r\n\r\nOmi有三个版本。其中的omi.js和omi.lite.js属于Web端使用的版本。\r\n\r\n* omi.js内置了[mustache.js](https://github.com/janl/mustache.js)作为模版引擎\r\n* omi.lite.js不包含任何模版引擎\r\n\r\nOmi不强制开发者使用mustache.js,你可以根据业务场景使用任意模板引擎或者不使用模板引擎。\r\n\r\n那么怎么使用别的模板引擎?下面拿[artTemplate](https://github.com/aui/artTemplate)作为例子。\r\n\r\n### 使用artTemplate\r\n\r\n```js\r\nOmi.template = function(tpl, data){\r\n return artTemplate.compile(tpl)(data);\r\n}\r\n```\r\n重写Omi.template方法,tpl为传入的模板,data为模板所需的数据,返回值为HTML。\r\n重写完毕后就能在render使用artTemplate的语法,如:\r\n\r\n```js\r\nclass List extends Omi.Component {\r\n constructor(data) {\r\n super(data);\r\n }\r\n\r\n style () {\r\n return `\r\n h1 { color:red; }\r\n li{ color:green;}\r\n `;\r\n }\r\n\r\n render () {\r\n return `

{{title}}

\r\n `;\r\n }\r\n}\r\n```\r\n\r\n### 相关地址\r\n\r\n* [演示地址](http://alloyteam.github.io/omi/example/artTemplate/)\r\n* [源码地址](https://github.com/AlloyTeam/omi/tree/master/example/artTemplate)" - -/***/ }, -/* 23 */ -/***/ function(module, exports) { - - module.exports = "## Omi的理念\n\nOmi的理念是基于面向对象编程体系,内建积木系统。\n 传统的单向数据流或者抛出event的组件通讯方式增加了系统的稳定性,但是丧失了灵活性。一定程度上也降低了组件的复用。所谓鱼和熊掌不可兼得。\n 面向对象体系需要多一个逻辑层,可以自由操作所有组件的instance,instance之间的逻辑关系构建出了整个程序。这样组件间的逻辑,通信,复用就全部迎刃而解。组件也更加单一职责,更松耦合。\n\n对比函数式编程、命令式编程与面向对象编程,可以归纳总结出下面几条:\n\n- 命令式编程干脆直接,利用循环条件等控制流程,强调执行过程\n- 命令式编程对硬件执行友好,运行更容易,却阻碍了复杂程序的设计\n- 函数式强调输入和输出,并非执行过程\n- 函数式倡导多个简单执行单元组合成复杂运算程序\n- 面向对象编程将对象作为程序的基本单元,更具有重用性、灵活性和扩展性\n\nJavascript是哪种类型的语言?现在ES6+已经有了class。那么他是面向对象语言?\n但是JS可以在任意地方定义函数并且当作把函数当作值来传递。那么他是函数式编程语言?\n所以,没有精准的定义,取决于你的用法和姿势。其次,Web组件化架构层面编程模型和语言层面编程模型是非常自由的关系。意思就是,你可以用Javascript构建函数式编程框架如React,也可以基于面向对象体系搭建Omi。\n\n### 函数式编程 VS 面向对象编程\n\n在UI组件框架层面,函数式编程的代表有React,Omi属于面向对象编程体系。那么他们各有什么优缺点?下面做了个对比(其实也是函数式编程与面向对象编程的对比):\n\n| | React | Omi |\n| ------------- |:-------------:|:-----:|\n| 组件通信 | ★★★★☆| ★★★★★ |\n| 稳定性 | ★★★★★ | ★★★★☆ |\n| 灵活性 | ★★★★☆| ★★★★★ |\n| 扩展性 | ★★★★☆ | ★★★★★ |\n| 测试性 | ★★★★★ | ★★★★☆ |\n| 文件大小 | ★★★☆☆ | ★★★★★ |\n| 功能特性 | ★★★☆☆ | ★★★★☆ |\n| DOM性能 | ★★★★★ | ★★★★☆ |\n| 动画性能 | ★★★★☆ | ★★★★★ |\n| 抽象复杂度 | ★★★★☆ | ★★★★★ |\n| 异步编程 | ★★★★★ | ★★★★☆ |\n\n可以看得出,鱼和熊掌不可兼得。面向对象编程更具有重用性、灵活性和扩展性,带来的问题就是更加难测试。\n具体来说,如函数式编程,其测试面积是state1 + state2 + ... + stateN;在面向对象编程中,其测试面积是state1×event1 + state2×event2 + ... + stateN×eventN。\n\n总结来说,更加推荐使用面向对象的方式去搭建UI组件化框架。\n\n
\n\n### 全文结束,感谢阅读。[开始Omi之旅吧!](https://github.com/AlloyTeam/omi) \n\n" - -/***/ }, -/* 24 */ -/***/ function(module, exports) { - - module.exports = "## Component Communication\r\n\r\nCommunication between [Omi](https://github.com/AlloyTeam/omi) components is very flexible, there are many options:\r\n\r\n- By declaring `data-*` on the component to pass data to child node\r\n- By declaring `data` on the component to pass data to child node (support complex data types mapping)\r\n- By declaring `childrenData` on parent component to automatically pass data to child node\r\n- By declaring `group-data` (support complex data types mapping)\r\n- It's completely object-oriented, you can easily get the object instance, then you can set the instance of the property or call the instance of the method\r\n\r\nLet's see some examples.\r\n\r\n### Communicate by `data-*`\r\n\r\n```js\r\nclass Hello extends Omi.Component {\r\n constructor(data) {\r\n super(data);\r\n }\r\n \r\n style () {\r\n return `\r\n h1{\r\n \tcursor:pointer;\r\n }\r\n `;\r\n }\r\n \r\n handleClick(target, evt){\r\n alert(target.innerHTML);\r\n }\r\n \r\n render() {\r\n return `\r\n
\r\n \t

Hello ,{{name}}!

\r\n
\r\n \t\t`;\r\n }\r\n}\r\n\r\nOmi.makeHTML('Hello', Hello);\r\n\r\nclass App extends Omi.Component {\r\n constructor(data) {\r\n super(data);\r\n }\r\n \r\n render() {\r\n return `\r\n
\r\n \r\n
\r\n `;\r\n }\r\n}\r\n\r\nOmi.render(new App(),\"#container\");\r\n```\r\n\r\nGenerally `data-*` is used to pass value types such as string and number. It is worth noting that, through `data-*`, received data types are string. You need to manually transform it to the number type.\r\n\r\nNormally, communicate by `data-*` is enough, but sometimes we may need to use complex data types, then we can use `data` to communicate.\r\n\r\n### Communicate by `data`\r\n\r\nAs shown in the above code, name can be passed to the subcomponent by `data-name=\"Omi\"`. The following code can also achieve the same effect.\r\n\r\n```js\r\n...\r\nclass App extends Omi.Component {\r\n constructor(data) {\r\n super(data);\r\n this.helloData = { name : 'Omi' };\r\n }\r\n \r\n render() {\r\n return `\r\n
\r\n \r\n
\r\n `;\r\n }\r\n}\r\n\r\nOmi.render(new App(),\"#container\");\r\n```\r\n\r\nUse the `data` tag, it will find the property from the component instance (that is, this), this can be mounted with any complex objects. This also broke the limitations of `data-*`.\r\n\r\nThen how do we pass `data` that is in a deep depth of the instance to the Hello? No worries, `data` tag can be a complex statement:\r\n\r\n```js\r\n...\r\nclass App extends Omi.Component {\r\n constructor(data) {\r\n super(data);\r\n this.complexData ={\r\n a:{\r\n b:{\r\n c:[\r\n {\r\n e:[{\r\n name:'ComplexData Support1'\r\n },{\r\n name:'ComplexData Support2'\r\n }]\r\n },\r\n {\r\n name: 'ComplexData Support3'\r\n }\r\n ]\r\n }\r\n }\r\n };\r\n }\r\n \r\n render() {\r\n return `\r\n
\r\n \r\n
\r\n `;\r\n }\r\n}\r\n...\r\n```\r\n\r\nClick me for the complex data mapping\r\n\r\n### Communicate by `childrenData`\r\n\r\n```js\r\n...\r\nclass App extends Omi.Component {\r\n constructor(data) {\r\n super(data);\r\n this.childrenData = [{ name : 'Omi' } , { name : 'dntzhang' }];\r\n }\r\n \r\n render() {\r\n return `\r\n
\r\n \r\n \r\n
\r\n `;\r\n }\r\n}\r\n\r\nOmi.render(new App(),\"#container\");\r\n```\r\n\r\nWe can use `this.childrenData` to transfer data to the sub-component. In this case, `childrenData` is an array, so it can pass data to multiple components in the same time. In the meanwhile, the data will be passed to components one by one.\r\n\r\n### Communicate by `group-data`\r\n\r\n`childrenData` can pass data to multiple components. However, there are many scenes where the source of data does not have to be from `childrenData`. `childrenData` is an array, and it should be the same order with the components, so that the data must all concentrated in `childrenData`, it's very inconvenient. `group-data` dedicated to solve the above pain points, specifically to pass data to a group of components.\r\n\r\n```js\r\nimport Hello from './hello.js';\r\n\r\n\r\nOmi.makeHTML('Hello', Hello);\r\n\r\nclass App extends Omi.Component {\r\n constructor(data) {\r\n super(data);\r\n this.testData = [{name: 'Omi'}, {name: 'dntzhang'}, {name: 'AlloyTeam'}];\r\n }\r\n\r\n render() {\r\n return `\r\n
\r\n \r\n \r\n \r\n
\r\n `;\r\n\r\n }\r\n}\r\n\r\nOmi.render(new App(),\"#container\");\r\n```\r\n\r\nBy declaring a `group-data` tag in the sub-components, it will go to the current instance of the component (that is, `this`) to find the corresponding property. Then according to the current location, the data will pass to the positions one by one.\r\n\r\nThe results are as follows:\r\n\r\n![group-data results](http://images2015.cnblogs.com/blog/105416/201702/105416-20170216110701535-1698390390.png)\r\n\r\nClick me for the group-data example\r\n\r\nSimilarly, `group-data` supports the mapping of complex data types. It should be noted that the end of the group-data mapping must be an array:\r\n\r\n```js\r\nimport Hello from './hello.js';\r\n\r\n\r\nOmi.makeHTML('Hello', Hello);\r\n\r\nclass App extends Omi.Component {\r\n constructor(data) {\r\n super(data);\r\n this.complexData ={\r\n a:{\r\n b:{\r\n c:[\r\n {\r\n e:[{\r\n name:'ComplexData Support1'\r\n },{\r\n name:'ComplexData Support2'\r\n }]\r\n },\r\n {\r\n name: 'ComplexData Support3'\r\n }\r\n ]\r\n }\r\n }\r\n };\r\n }\r\n\r\n render() {\r\n return `\r\n
\r\n \r\n \r\n
\r\n `;\r\n\r\n }\r\n}\r\n\r\nOmi.render(new App(),\"#container\");\r\n```\r\n\r\nClick me for the complex group-data mapping\r\n\r\n### By object instance\r\n\r\n```js\r\n...\r\nclass App extends Omi.Component {\r\n constructor(data) {\r\n super(data);\r\n }\r\n \r\n installed(){\r\n this.hello.data.name = \"Omi\";\r\n this.update()\r\n }\r\n \r\n render() {\r\n return `\r\n
\r\n \r\n
\r\n `;\r\n }\r\n}\r\n\r\nOmi.render(new App(),\"#container\");\r\n```\r\n\r\n### By omi-id\r\n\r\n```js\r\n...\r\nclass App extends Omi.Component {\r\n constructor(data) {\r\n super(data);\r\n }\r\n \r\n installed(){\r\n Omi.get(\"hello\").data.name = \"Omi\";\r\n this.update()\r\n }\r\n \r\n render() {\r\n return `\r\n
\r\n \r\n
\r\n `;\r\n }\r\n}\r\n\r\nOmi.render(new App(),\"#container\");\r\n```\r\n\r\nBy declaring `omi-id` on the component, we can get the instance of the object anywhere in the program. This can be regarded as any component communication artifacts.\r\n\r\n### Warm Tips\r\n\r\n- The data that passed by `childrenData` or `data` is shadow copied to sub-components. In order to update it, we need to update the `data` attribute of the component instance.\r\n- The data that passed by `data-*` is also shadow copied to sub-components. In order to update it, we need to update the `data` attribute of the component instance.\r\n- If we set the `dataFirst` property of the component instance to `false`, then `data-*` will override the `data` of component instance.\r\n\r\nFor the third tip, please checkout the pseudo-code:\r\n\r\n```js\r\nif(this.dataFirst){\r\n this.data = Object.assign({},data-✼ ,this.data);\r\n}else{\r\n this.data = Object.assign({},this.data, data-✼);\r\n}\r\n```" - -/***/ }, -/* 25 */ -/***/ function(module, exports) { - - module.exports = "## Components\r\n\r\n[Omi](https://github.com/AlloyTeam/omi) is based entirely on component architecture, which allows developers to build web applications like building blocks. Everything is components, components can be nested to create new components.\r\n\r\n![Omi Components System](http://images2015.cnblogs.com/blog/105416/201702/105416-20170210093427338-1536910080.png)\r\n\r\n### Simple Components\r\n\r\nLet's explore a simple Todo example to learn the components system in Omi.\r\n\r\n```js\r\nclass Todo extends Omi.Component {\r\n constructor(data) {\r\n super(data);\r\n }\r\n \r\n add (evt) {\r\n evt.preventDefault();\r\n this.data.items.push(this.data.text);\r\n this.data.text = '';\r\n this.update();\r\n }\r\n\r\n style () {\r\n return `\r\n h3 { color:red; }\r\n button{ color:green;}\r\n `;\r\n }\r\n\r\n handleChange(target){\r\n this.data.text = target.value;\r\n }\r\n\r\n render () {\r\n return `
\r\n

TODO

\r\n
    {{#items}}
  • {{.}}
  • {{/items}}
\r\n
\r\n \r\n \r\n
\r\n
`;\r\n }\r\n}\r\n\r\nOmi.render(new Todo({ items: [] ,text : '' }),\"body\");\r\n```\r\n\r\nThe HTML generated by the component will eventually be inserted into the body. The above example shows some of the features of Omi:\r\n\r\n- Data flow: `data` in `new Todo(data,..)` can be used directly in the template in render method.\r\n- Partial CSS: `h3` in `style()` only effect inside of render. It'll never pollute `h3` outside of this component. The same rule applies to `button`.\r\n- Declarative event binding: `onchange` will call `handleChange` that inside of the component. `this` refers to the current DOM element, `event` refers to the current DOM Event Object.\r\n- You need to manually call the `this.update()` method to update the component\r\n\r\nIt is important to note that, for more freedom and flexibility, Omi does not automatically update DOM while data changes. Developers need to call the `update` method manually.\r\n\r\nYou can also use [oba] (https://github.com/dntzhang/oba) or mobx to implement automatic updates.\r\n\r\nClick me for the live demo\r\n\r\n### Component Nesting\r\n\r\nIt's ok to not use nesting component if your page is super simple. However, for most of webpages and web applications, it is a necessary to define the nesting Components to implement complex features.\r\n\r\nFor instance, we can extract a `List` component form the Todo example. This brings maintainable, scalable and reuseable to our project:\r\n\r\n```js\r\nclass List extends Omi.Component {\r\n constructor(data) {\r\n super(data);\r\n }\r\n\r\n render () {\r\n return ``;\r\n }\r\n}\r\n```\r\n\r\nThen how to use this `List`? We need to use `Omi.makeHTML` to make the `List` to a tag which can be used in render method:\r\n\r\n```js\r\nimport List from './list.js';\r\n\r\nOmi.makeHTML('List', List);\r\n\r\nclass Todo extends Omi.Component {\r\n constructor(data) {\r\n super(data);\r\n this.data.length = this.data.items.length;\r\n this.listData = { items : this.data.items };\r\n }\r\n\r\n add (evt) {\r\n evt.preventDefault();\r\n this.list.data.items.push(this.data.text);\r\n this.data.length = this.list.data.items.length;\r\n this.data.text = '';\r\n this.update();\r\n }\r\n\r\n style () {\r\n return `\r\n h3 { color:red; }\r\n button{ color:green;}\r\n `;\r\n }\r\n\r\n handleChange(target){\r\n this.data.text = target.value;\r\n }\r\n\r\n render () {\r\n return `
\r\n

TODO

\r\n \r\n
\r\n \r\n \r\n
\r\n
`;\r\n }\r\n}\r\n```\r\n\r\n- In line 3, we use `makeHTML` to make the component to a tag which can be used in render method. Of course, `Omi.makeHTML('List', List);` can also be written in the end of List component.\r\n- In line 9, the parent component defines the 'listData' property\r\n- In line 34, we use List component in the render method. `name` attribute allows us easily find the instance of the component by using `this`.`data=\"listData\"` attribute allows us easily pass `this.listData` to the sub component from parent component.\r\n\r\nIt should be noted that the `data` passed from `data=\"listData\"` is cloned to the subcomponents by Object.assign(shallow copy) , which means if we want to change the DOM, we recommend that first update the `data` of the instance of subcomponent(not the parent component's `listData` ) and secondly call the `update` method.\r\n\r\nIn fact there are 4 way to communicate between components, it'll be explained later.\r\n\r\nClick me for the live demo\r\n" - -/***/ }, -/* 26 */ -/***/ function(module, exports) { - - module.exports = "## Conditional Rendering\r\n\r\nIn most case, we need to show different layouts according to different states. For example, some users are vip and we need to show vip logo for them. Omi has many ways to meet this kind of requirements.\r\n\r\n### First Option\r\n\r\n```js\r\nclass ConditionTest extends Omi.Component {\r\n constructor(data) {\r\n super(data);\r\n }\r\n\r\n render () {\r\n return `{{#isVip}}\r\n
you are VIP.
\r\n {{/isVip}}\r\n {{^isVip}}\r\n
you are not VIP.
\r\n {{/isVip}}`;\r\n }\r\n}\r\n```\r\n\r\nIn the above case, we use the condition in mustachejs for rendering. Of course Omi does not force you to use mustachejs. You can use omi.lite.js and then override the `Omi.template` method to use any of your favorite template engines.\r\n\r\n### Second Option\r\n\r\n```js\r\nclass ConditionTest extends Omi.Component {\r\n constructor(data) {\r\n super(data);\r\n }\r\n\r\n render () {\r\n if(this.data.isVip){\r\n return '
you are VIP.
';\r\n }else{\r\n return '
you are not VIP.
';\r\n }\r\n }\r\n}\r\n```\r\n\r\n`render` provides a very good programmability, which can write any js code inside. Oh, don't forget that `style` method can also have js code inside it.\r\n\r\n```js\r\nclass ConditionTest extends Omi.Component {\r\n constructor(data) {\r\n super(data);\r\n }\r\n\r\n style (){\r\n if(this.data.isVip){\r\n return 'div{ color : red; }';\r\n }else{\r\n return 'div{ color : green; }';\r\n }\r\n }\r\n\r\n render () {\r\n if(this.data.isVip){\r\n return '
you are VIP.
';\r\n }else{\r\n return '
you are not VIP.
';\r\n }\r\n }\r\n}\r\n```" - -/***/ }, -/* 27 */ -/***/ function(module, exports) { - - module.exports = "## Handling Events\r\n\r\nThere are two types of events in Omi, built-in events and custom events. Built-in events clever use of the browser's own pipeline mechanism, you can easily get events instance and the triggered event elements through `event` and `this`.\r\n\r\n### Built-in events\r\n\r\nWhat is the built-in event? As long as the it can match the following regular expression.\r\n\r\n```js\r\non(abort|blur|cancel|canplay|canplaythrough|change|click|close|contextmenu|cuechange|dblclick|drag|dragend|dragenter|dragleave|dragover|dragstart|drop|durationchange|emptied|ended|error|focus|input|invalid|keydown|keypress|keyup|load|loadeddata|loadedmetadata|loadstart|mousedown|mouseenter|mouseleave|mousemove|mouseout|mouseover|mouseup|mousewheel|pause|play|playing|progress|ratechange|reset|resize|scroll|seeked|seeking|select|show|stalled|submit|suspend|timeupdate|toggle|volumechange|waiting|autocomplete|autocompleteerror|beforecopy|beforecut|beforepaste|copy|cut|paste|search|selectstart|wheel|webkitfullscreenchange|webkitfullscreenerror|touchstart|touchmove|touchend|touchcancel|pointerdown|pointerup|pointercancel|pointermove|pointerover|pointerout|pointerenter|pointerleave)\r\n```\r\n\r\nHow to bind built-in events? As follows:\r\n\r\n```js\r\nclass EventTest extends Omi.Component {\r\n constructor(data) {\r\n super(data);\r\n }\r\n\r\n handleClick(dom, evt){\r\n alert(dom.innerHTML);\r\n }\r\n\r\n render () {\r\n return `
Hello, Omi!
`;\r\n }\r\n}\r\n```\r\n\r\n### Custom events\r\n\r\nEvents that defined by developers is the custom events. Here is the pagination example:\r\n\r\n```js\r\nimport Omi from '../../src/index.js';\r\nimport Pagination from './pagination.js';\r\nimport Content from './content.js';\r\n\r\nOmi.makeHTML('Pagination', Pagination);\r\nOmi.makeHTML('Content', Content);\r\n\r\nclass Main extends Omi.Component {\r\n constructor(data) {\r\n super(data);\r\n }\r\n\r\n installed(){\r\n this.content.goto(this.pagination.data.currentPage+1);\r\n }\r\n \r\n handlePageChange(index){\r\n this.content.goto(index+1);\r\n }\r\n\r\n render () {\r\n return `
\r\n

Pagination Example

\r\n \r\n \r\n
`;\r\n }\r\n}\r\n\r\nOmi.render( new Main(),'body');\r\n```\r\n\r\nAs we can see, the `onPageChange` is a custom event, `handlePageChange` will being executed when `onPageChange` is triggered. The `onPageChange` method is executed in `Pagination`:\r\n\r\n```js\r\nimport Omi from '../../src/index.js';\r\n\r\nclass Pagination extends Omi.Component {\r\n ...\r\n ...\r\n ...\r\n linkTo: \"#\",\r\n prevText: \"Prev\",\r\n nextText: \"Next\",\r\n ellipseText: \"...\",\r\n prevShow: true,\r\n nextShow: true,\r\n onPageChange: function () { return false; }\r\n }, this.data);\r\n\r\n this.pageNum = Math.ceil(this.data.total / this.data.pageSize);\r\n }\r\n \r\n goto (index,evt) {\r\n evt.preventDefault();\r\n this.data.currentPage=index;\r\n this.update();\r\n this.data.onPageChange(index);\r\n }\r\n ...\r\n ...\r\n ...\r\n}\r\n```\r\n\r\nThis is a part of `Pagination` code. Highlight is the place to execute `onPageChange`.\r\n\r\n### Links\r\n\r\n- [Demo](http://alloyteam.github.io/omi/example/pagination/)\r\n- [Source](https://github.com/AlloyTeam/omi/tree/master/example/pagination)" - -/***/ }, -/* 28 */ -/***/ function(module, exports) { - - module.exports = "## Forms\r\n\r\nIt's much more convenient to control forms in Omi, especially `\r\n \r\n \r\n \r\n \r\n\r\n```\r\n\r\nThe third option is selected because it is being set to `selected` attribute. The problem is that developers need to traversed each option. While using Omi, you can write code like this:\r\n\r\n```html\r\n\r\n```\r\n\r\nThis will achieve the same effect. For example, you want to choose the first item:\r\n\r\n```html\r\n\r\n```\r\n\r\nIsn't it very convenient?\r\n\r\n### For Example\r\n\r\n```js\r\nclass FormTest extends Omi.Component {\r\n constructor(data) {\r\n super(data);\r\n \r\n }\r\n\r\n handleChange(target){\r\n console.log(target.value)\r\n this.data.value = target.value;\r\n }\r\n\r\n handleSubmit(evt) {\r\n alert('Your favorite flavor is: ' + this.data.value);\r\n evt.preventDefault();\r\n }\r\n \r\n render () {\r\n return `\r\n
\r\n \r\n \r\n
`;\r\n }\r\n}\r\n\r\nOmi.render(new FormTest({ value: 'mango' }),'#container');\r\n```\r\n\r\nClick me for a live demo" - -/***/ }, -/* 29 */ -/***/ function(module, exports) { - - module.exports = "## Get DOM\r\n\r\nWhile most of the time, developers do not need to find the DOM, but sometimes is a need to get the DOM.\r\n\r\nOmi provides a way to get the DOM node.\r\n\r\n### ref and refs\r\n\r\n```js\r\nclass Hello extends Omi.Component {\r\n constructor(data) {\r\n super(data);\r\n }\r\n \r\n style () {\r\n return `\r\n h1{\r\n cursor:pointer;\r\n }\r\n `;\r\n }\r\n \r\n handleClick(){\r\n alert(this.refs.abc.innerHTML);\r\n }\r\n \r\n render() {\r\n return `\r\n
\r\n

Hello ,{{name}}!

\r\n
\r\n `;\r\n }\r\n}\r\n\r\nOmi.render(new Hello({ name : \"Omi\" }),\"#container\");\r\n```\r\n\r\nAs we can see, by referencing `ref` as `abc` in HTML, the DOM node can be accessed through `this.refs.abc`.\r\n\r\nClick me for the live demo\r\n" - -/***/ }, -/* 30 */ -/***/ function(module, exports) { - - module.exports = "## Hello World\r\n\r\n### Hello World with ES20XX \r\n\r\nWe recommend using a bundler like [webpack](https://webpack.github.io/) or [Browserify](http://browserify.org/) so you can write modular code and bundle it together into small packages to optimize load time.\r\n\r\nThe small Omi example looks like this:\r\n\r\n```js\r\nimport Omi from './omi.js';\r\n\r\nclass Hello extends Omi.Component {\r\n constructor(data) {\r\n super(data);\r\n }\r\n \r\n style () {\r\n return `\r\n h1{\r\n cursor:pointer;\r\n }\r\n `;\r\n }\r\n \r\n handleClick(target){\r\n alert(target.innerHTML);\r\n }\r\n \r\n render() {\r\n return `\r\n
\r\n

Hello ,{{name}}!

\r\n
\r\n `;\r\n }\r\n}\r\n\r\nOmi.render(new Hello({ name : \"Omi\" }),\"body\");\r\n```\r\n\r\nThis code renders into body element. \r\n\r\n### Hello World with ES5\r\n\r\n```html\r\n\r\n```\r\n\r\nthen:\r\n\r\n```js\r\nvar Hello = Omi.create(\"Hello\", {\r\n style: function () {\r\n return \"h1{ cursor:pointer }\";\r\n },\r\n \r\n handleClick: function (dom) {\r\n alert(dom.innerHTML)\r\n },\r\n \r\n render: function () {\r\n return '
\\\r\n

\\\r\n Hello ,{{name}}!\\\r\n

\\\r\n
'\r\n }\r\n});\r\n\r\nvar Test = Omi.create(\"Test\", {\r\n render: function () {\r\n return '
\\\r\n
Test
\\\r\n \\\r\n
'\r\n }\r\n});\r\n\r\nOmi.render(new Test(),'#container');\r\n```" - -/***/ }, -/* 31 */ -/***/ function(module, exports) { - - module.exports = "## Inheritance\r\n\r\nThrough the inheritance mechanism, we can define new classes base on old classes. The new classes not only have newly defined members, but also have old members at the same time.\r\n\r\nWe call the existing class the base class, also known as the parent class. And the new class derived from the existing class is called a derived class, also known as a subclass.\r\n\r\n### For Example\r\n\r\n```js\r\nclass Hello extends Omi.Component {\r\n constructor(data) {\r\n super(data);\r\n }\r\n \r\n style () {\r\n return `\r\n div{\r\n cursor:pointer;\r\n }\r\n `;\r\n }\r\n \r\n handleClick(target, evt){\r\n alert(target.innerHTML);\r\n }\r\n \r\n render() {\r\n return '
Hello {{name}}!
'\r\n }\r\n}\r\n\r\nclass SubHello extends Hello {\r\n constructor(data) {\r\n super(data);\r\n }\r\n}\r\n\r\nOmi.render(new SubHello({ name : 'Omi' }),'#container');\r\n```\r\n\r\nClick me for the live demo\r\n\r\n### inherit in ES5\r\n\r\n```js\r\nvar Hello = Omi.create(\"Hello\",{\r\n render:function(){\r\n return '
Hello {{name}}!
'\r\n }\r\n})\r\n\r\nvar SubHello = Omi.create(\"SubHello\",Hello,{ });\r\n\r\n\r\nOmi.render(new SubHello({ name : 'Omi' }),'#container');\r\n```\r\n\r\nClick me for the live demo" - -/***/ }, -/* 32 */ -/***/ function(module, exports) { - - module.exports = "## Installation\r\n\r\n[Omi](https://github.com/AlloyTeam/omi) is open and modern framework for building user interfaces.\r\n\r\n### Installing Omi\r\n\r\nWe recommend using [npm](https://www.npmjs.com/) for managing front-end dependencies. If you're new to package managers.\r\n\r\nTo install Omi with npm, run:\r\n\r\n``` js\r\n$ npm install omi\r\n```\r\n### omi-cli\r\n\r\n``` js\r\n$ npm install omi-cli -g \r\n$ omi init your_project_name \r\n$ cd your_project_name \r\n$ npm run dev \r\n$ npm run dist \r\n```" - -/***/ }, -/* 33 */ -/***/ function(module, exports) { - - module.exports = "## Lifecycle\r\n\r\n| Name | Meaning | Occasion |\r\n| :-------------: | :-------------: | :-----: |\r\n| constructor | The constructor | When new a constructor |\r\n| install | The installation. We can process the data that user pass | When instantiate |\r\n| installed | Complete the installation. It'll trigger after HTML being inserted to the page. Please note that it'll trigger when component being removed and restored | **Instantiation and existence** |\r\n| uninstall | Uninstall the component. It'll trigger when remove is executed | When destroy |\r\n| beforeUpdate | Before update | When existence |\r\n| afterUpdate | After update | When existence |\r\n\r\n## Illustration\r\n\r\n![lc](http://images2015.cnblogs.com/blog/105416/201703/105416-20170322084234049-1482108845.jpg)\r\n\r\nIt should be noted that the installed will be executed during the instantiation, which is not shown above. For example, it'll executed when a component is removed and restored, or when the new component is being added.\r\n\r\n### Examples\r\n\r\n```js\r\nclass Timer extends Omi.Component {\r\n constructor(data) {\r\n super(data);\r\n }\r\n\r\n install () {\r\n this.data = {secondsElapsed: 0};\r\n }\r\n\r\n tick() {\r\n this.data.secondsElapsed++;\r\n this.update();\r\n }\r\n\r\n installed(){\r\n this.interval = setInterval(() => this.tick(), 1000);\r\n }\r\n\r\n uninstall() {\r\n clearInterval(this.interval);\r\n }\r\n\r\n\r\n style () {\r\n return `\r\n .num { color:red; }\r\n `;\r\n }\r\n\r\n render () {\r\n return `
Seconds Elapsed: {{secondsElapsed}}
`;\r\n }\r\n}\r\n```\r\n\r\nClick me for the live demo" - -/***/ }, -/* 34 */ -/***/ function(module, exports) { - - module.exports = "## Loop\r\n\r\nThe following describes how to traverses in mustache.js and javascript.\r\n\r\n### First Option\r\n\r\n```js\r\nclass List extends Omi.Component {\r\n constructor(data) {\r\n super(data);\r\n }\r\n\r\n render () {\r\n return `
\r\n
    \r\n {{#items}} \r\n
  • {{text}}
  • \r\n {{/items}}\r\n
\r\n
`;\r\n }\r\n}\r\n\r\nOmi.render(new List({\r\n items: [\r\n {id: 1, text: 'Omi'},\r\n {id: 2, text: 'dntzhang'},\r\n {id: 3, text: 'AlloyTeam'}\r\n ]\r\n}),\"body\");\r\n```\r\n\r\nMustache.js more detailed loop traversal use can see \r\n\r\nFor more details for traversal in mustache.js please view [https://github.com/janl/mustache.js#non-empty-lists](https://github.com/janl/mustache.js#non-empty-lists).\r\n\r\nFor example, it also support:\r\n\r\n- If each item of items is a string, you can directly use **{{.}}** to output each item\r\n- Call the defined function when looping\r\n\r\nClick me for the live demo\r\n\r\n### Second Option\r\n\r\nOf course, you can also use template string inside the `map`:\r\n\r\n```js\r\nclass List extends Omi.Component {\r\n constructor(data) {\r\n super(data);\r\n }\r\n\r\n render() {\r\n return `
\r\n
    \r\n ${this.data.items.map(item =>\r\n `
  • ${item.text}
  • `\r\n ).join('')}\r\n
\r\n
`;\r\n }\r\n}\r\n\r\nOmi.render(new List({\r\n items: [\r\n {id: 1, text: 'Omi'},\r\n {id: 2, text: 'dntzhang'},\r\n {id: 3, text: 'AlloyTeam'}\r\n ]\r\n}),\"body\");\r\n```\r\n\r\nYou will see the following page:\r\n\r\n![pv](http://images2015.cnblogs.com/blog/105416/201701/105416-20170122095724129-2059595233.png)\r\n\r\nClick me for the live demo" - -/***/ }, -/* 35 */ -/***/ function(module, exports) { - - module.exports = "## Plugin\r\n\r\n[Omi](https://github.com/AlloyTeam/omi) is a componentized web framework. Then what is plugin?\r\n\r\nIt can be understood that the Omi plugin system can give the dom element some ability and can be associated with the instance of the components.\r\n\r\n### omi-drag\r\n\r\nLet's see this example:\r\n\r\nClick me for the live deme\r\n\r\n```js\r\nimport OmiDrag from './omi-drag.js';\r\n\r\nOmiDrag.init();\r\n\r\nclass App extends Omi.Component {\r\n constructor(data) {\r\n super(data);\r\n }\r\n\r\n render() {\r\n return `\r\n
\r\n
Drag Me
\r\n
\r\n `;\r\n\r\n }\r\n\r\n style(){\r\n return `\r\n .test{\r\n width:100px;\r\n height:100px;\r\n color:white;\r\n line-height:90px;\r\n text-align:center;\r\n background-color:#00BFF3;\r\n }\r\n `\r\n }\r\n}\r\n\r\nOmi.render(new App(),\"#container\");\r\n```\r\n\r\nAs shown above, by adding `omi-drag` attribute to the div, it can be dragged by the user using the mouse. We call omi-drag.js an omi plugin.\r\n\r\nIsn't it very convenient? So how did this omi-drag implement?\r\n\r\n如上面的代码所示,通过在div上标记omi-drag,这个div就能够被用户使用鼠标拖拽。我们称omi-drag.js为omi插件。\r\n是不是非常方便?那么这个omi-drag是怎么实现的?\r\n\r\n## Omi.extendPlugin\r\n\r\nCore method: Omi.extendPlugin( pluginName, handler )\r\n\r\nThe following code shows how to use `Omi.extendPlugin` to give dom the drap and drop ability:\r\n\r\n```js\r\n;(function () {\r\n\r\n var OmiDrag = {};\r\n var Omi = typeof require === 'function'\r\n ? require('omi')\r\n : window.Omi;\r\n\r\n OmiDrag.init = function(){\r\n Omi.extendPlugin('omi-drag',function(dom, instance){\r\n dom.style.cursor='move';\r\n var isMouseDown = false,\r\n preX = null,\r\n preY = null,\r\n currentX = null,\r\n currentY = null,\r\n translateX = 0,\r\n translateY = 0;\r\n\r\n dom.addEventListener('mousedown',function(evt){\r\n isMouseDown = true;\r\n preX = evt.pageX;\r\n preY = evt.pageY;\r\n evt.stopPropagation();\r\n },false);\r\n\r\n window.addEventListener('mousemove',function(evt){\r\n if(isMouseDown){\r\n currentX = evt.pageX;\r\n currentY = evt.pageY;\r\n if(preX != null){\r\n translateX += currentX - preX;\r\n translateY += currentY - preY;\r\n dom.style.transform = 'translateX('+translateX+'px) translateY('+translateY+'px)';\r\n }\r\n preX = currentX;\r\n preY = currentY;\r\n evt.preventDefault();\r\n }\r\n },false);\r\n\r\n window.addEventListener('mouseup',function(){\r\n isMouseDown = false;\r\n preX = preY = currentX = currentY = null;\r\n },false);\r\n });\r\n }\r\n\r\n OmiDrag.destroy = function(){\r\n delete Omi.plugins['omi-drag'];\r\n };\r\n\r\n if (typeof exports == \"object\") {\r\n module.exports = OmiDrag;\r\n } else if (typeof define == \"function\" && define.amd) {\r\n define([], function(){ return OmiDrag });\r\n } else {\r\n window.OmiDrag = OmiDrag;\r\n }\r\n\r\n})();\r\n```\r\n\r\nMethod: Omi.extendPlugin( pluginName, handler )\r\n\r\n`pluginName` is the name of the plugin.\r\n\r\n`handler` is the processor. The handler can get the dom which marked as the `pluginName` and the instance of the component.\r\n\r\nWith `Omi.extendPlugin`, we can give the dom some ability, and can also be associated with the component instance.\r\n\r\nThe above example is not associated with the instance, let's try it:\r\n\r\n## Associated with instance\r\n\r\nWe want to be able to listen to the `move` inside the component and perform a callback. As follows:\r\n\r\n```js\r\n...\r\n...\r\nmoveHandler(){\r\n console.log('moving');\r\n}\r\n\r\nrender() {\r\n return `\r\n
\r\n
Drag Me
\r\n
\r\n `;\r\n}\r\n...\r\n```\r\n\r\nIn this case, the `moveHandler` will be continually executed while dragging. We can modify some code to solve this issue:\r\n\r\n```js\r\n...\r\nwindow.addEventListener('mousemove',function(evt){\r\n if(isMouseDown){\r\n currentX = evt.pageX;\r\n currentY = evt.pageY;\r\n if(preX != null){\r\n translateX += currentX - preX;\r\n translateY += currentY - preY;\r\n dom.style.transform = 'translateX('+translateX+'px) translateY('+translateY+'px)';\r\n }\r\n preX = currentX;\r\n preY = currentY;\r\n evt.preventDefault();\r\n instance.moveHandler(evt);\r\n }\r\n},false);\r\n```\r\n\r\nWe add `instance.moveHandler(evt)` method to execute the `moveHandler` method of component instance.\r\n\r\nThis is how associated with instance works.\r\n\r\nHowever, this may still have an issue if we add `omi-drag` to a list of `div`:\r\n\r\n```js\r\n...\r\nrender() {\r\n return `\r\n
\r\n
Drag Me
\r\n
Drag Me
\r\n
\r\n `;\r\n}\r\n...\r\n```\r\n\r\nUsually each of our `omi-drag` can correspond to a callback function, such as:\r\n\r\n```js\r\n...\r\n...\r\nmoveHandlerA(){\r\n console.log('moving');\r\n}\r\n\r\nmoveHandlerB(){\r\n console.log('moving');\r\n}\r\n\r\nrender() {\r\n return `\r\n
\r\n
Drag Me A
\r\n
Drag Me B
\r\n
\r\n `;\r\n}\r\n...\r\n```\r\n\r\nHow to achieve this? We can pass the data to the plugin via dom.\r\n\r\n## Passing data\r\n\r\nLet's see the final code:\r\n\r\n```js\r\n...\r\n...\r\nmoveHandlerA(){\r\n console.log('moving');\r\n}\r\n\r\nmoveHandlerB(){\r\n console.log('moving');\r\n}\r\n\r\nrender() {\r\n return `\r\n
\r\n
Drag Me A
\r\n
Drag Me B
\r\n
\r\n `;\r\n}\r\n...\r\n```\r\n\r\nWhere `omi-drag` modified:\r\n\r\n```js\r\n...\r\nvar handlerName = dom.getAttribute('dragMove');\r\n\r\nwindow.addEventListener('mousemove',function(evt){\r\n if(isMouseDown){\r\n currentX = evt.pageX;\r\n currentY = evt.pageY;\r\n if(preX != null){\r\n translateX += currentX - preX;\r\n translateY += currentY - preY;\r\n dom.style.transform = 'translateX('+translateX+'px) translateY('+translateY+'px)';\r\n }\r\n preX = currentX;\r\n preY = currentY;\r\n evt.preventDefault();\r\n instance[handlerName](evt);\r\n }\r\n},false);\r\n...\r\n```\r\n\r\n- We use `var handlerName = dom.getAttribute('dragMove')` to get the `dragMove` of dom\r\n- We use `instance[handlerName](evt)` to execute the method\r\n\r\nClick me for the live demo\r\n\r\n## More plugins\r\n\r\n* [omi-finger](https://github.com/AlloyTeam/omi/tree/master/plugins/omi-finger) The [AlloyFinger](https://github.com/AlloyTeam/AlloyFinger) plugin for Omi, which support touch events and gustures\r\n* [omi-transform](https://github.com/AlloyTeam/omi/tree/master/plugins/omi-transform) The [transformjs](http://alloyteam.github.io/AlloyTouch/transformjs/) plugin for Omi, which can easily set CSS3 Transform to DOM\r\n* [omi-touch](https://github.com/AlloyTeam/omi/tree/master/plugins/omi-touch) The [AlloyTouch](https://github.com/AlloyTeam/AlloyTouch) plugin for Omi. The touch movement solution for Omi (support touch scroll, rotate, flip, select, etc.)\r\n* [omi-jquery-date-picker](https://github.com/AlloyTeam/omi/tree/master/plugins/omi-jquery-date-picker) The date picker plugin for Omi, which support choose any time zone\r\n" - -/***/ }, -/* 36 */ -/***/ function(module, exports) { - - module.exports = "## Templates\r\n\r\nThere are three types of Omi. omi.js and omi.lite.js is for web side.\r\n\r\n- omi.js has a built-in [mustache.js](https://github.com/janl/mustache.js) as the template engine\r\n- omi.lite.js doesn't have any template engines\r\n\r\nOmi does not force developers to use mustache.js, you can use any template engine based on business scenarios or do not use any template engines.\r\n\r\nHow to use other template engines? Let's see the [artTemplate](https://github.com/aui/artTemplate) example.\r\n\r\n### Use artTemplate\r\n\r\n```js\r\nOmi.template = function(tpl, data){\r\n return artTemplate.compile(tpl)(data);\r\n}\r\n```\r\n\r\nWe need to rewrite the `Omi.template` method, the `tpl` is the incoming template, the `data` is the required data for the template, and the return value is HTML.\r\n\r\nAfter rewriting, you can use the artTemplate syntax in `render`, such as:\r\n\r\n```js\r\nclass List extends Omi.Component {\r\n constructor(data) {\r\n super(data);\r\n }\r\n\r\n style () {\r\n return `\r\n h1 { color:red; }\r\n li{ color:green;}\r\n `;\r\n }\r\n\r\n render () {\r\n return `

{{title}}

\r\n `;\r\n }\r\n}\r\n```\r\n\r\n### Links\r\n\r\n* [Demo Link](http://alloyteam.github.io/omi/example/artTemplate/)\r\n* [Source Code](https://github.com/AlloyTeam/omi/tree/master/example/artTemplate)" - -/***/ }, -/* 37 */ -/***/ function(module, exports) { - - module.exports = "## Thinking in Omi\r\n\r\nOmi is based on object-oriented programming, with plugin system.\r\n\r\nThe traditional one-way data flow or the event-throwing component communicating can increase the stability of the system, but it loses it's flexibility. To a certain extent also reduced the component reusing.\r\n\r\nObject-oriented system has an other logical layer, which let you control the instance of components. The logic between instances build the entire program.\r\n\r\nThen the issues like communication, reusing and logics between components are all solved.\r\n\r\n\r\nPlus, the component is also more single duty, more loosely coupled.\r\n\r\nFor functional programming, imperative programming and object-oriented programming, we can sum up the following list:\r\n\r\n- Imperative programming is well understood, we use loop and if-else condition to control processes, it emphasize the process of execution\r\n- Imperative programming is hardware friendly, easy to run, but hard to design complex program\r\n- Functional programming is all about input and output, not the process of execution\r\n- Functional programming advocates multiple simple execution units into complex operations\r\n- Object-oriented programming uses objects as the basic unit of the program, with more reusability, flexibility, and extensibility\r\n\r\nWhat kind of language is JavaScript? We have `class` in ES6+, so is JavaScript object-oriented language?\r\n\r\nJavaScript can pass a function as a argumant, so is JavaScript a functional language?\r\n\r\nThere are no right answer, it depands on how you use JavaScript.\r\n\r\nIt's free to chooce, you can use functional programming framework like React, or object-oriented framework like Omi. \r\n\r\n### Functional Programming VS Object-Oriented Programming\r\n\r\nIn the UI component framework scope, functional programming is represented by React, while Omi belongs to object-oriented programming.\r\n\r\nSo what are their strengths and weaknesses? The following is a comparison (in fact, functional programming and object-oriented programming comparison):\r\n\r\n| | React | Omi |\r\n| ------------- |:-------------:|:-----:|\r\n| Component communication | ★★★★☆| ★★★★★ |\r\n| Stability | ★★★★★ | ★★★★☆ |\r\n| Flexibility | ★★★★☆| ★★★★★ |\r\n| Scalability | ★★★★☆ | ★★★★★ |\r\n| Testability | ★★★★★ | ★★★★☆ |\r\n| File size | ★★★☆☆ | ★★★★★ |\r\n| Features | ★★★☆☆ | ★★★★☆ |\r\n| DOM performance | ★★★★★ | ★★★★☆ |\r\n| Animation performance | ★★★★☆ | ★★★★★ |\r\n| Abstract complexity | ★★★★☆ | ★★★★★ |\r\n| Asynchronous programming | ★★★★★ | ★★★★☆ |\r\n\r\nAs we can see, we can not have it both ways. Object-oriented programming is more reusable, flexible and scalable, the problem is more difficult to test.\r\n\r\nSpecifically, if the functional programming, the test area is state1 + state2 + ... + stateN; in object-oriented programming, the test area is state1 × event1 + state2 × event2 + ... + stateN × eventN.\r\n\r\nIn summary, it is more recommended to use the object-oriented programming to build UI component framework.\r\n\r\n
\r\n\r\n### The end. Thanks for reading. [Let's start the Omi journey](https://github.com/AlloyTeam/omi)!\r\n" - -/***/ }, -/* 38 */ -/***/ function(module, exports, __webpack_require__) { - - 'use strict'; - - Object.defineProperty(exports, "__esModule", { - value: true - }); - - var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); - - var _omi = __webpack_require__(2); - - var _omi2 = _interopRequireDefault(_omi); - - var _index = __webpack_require__(39); - - var _index2 = _interopRequireDefault(_index); - - var _config = __webpack_require__(4); - - var _config2 = _interopRequireDefault(_config); - - function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - - function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } - - function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; } - - function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } - - _omi2.default.makeHTML('List', _index2.default); - - var Sidebar = function (_Omi$Component) { - _inherits(Sidebar, _Omi$Component); - - function Sidebar(data) { - _classCallCheck(this, Sidebar); - - return _possibleConstructorReturn(this, (Sidebar.__proto__ || Object.getPrototypeOf(Sidebar)).call(this, data)); - } - - _createClass(Sidebar, [{ - key: 'install', - value: function install() { - this.data.items = _config2.default['menus'][this.data.lan]; - this.data.height = window.innerHeight - 45; - } - }, { - key: 'style', - value: function style() { - return __webpack_require__(42); - } - }, { - key: 'render', - value: function render() { - return __webpack_require__(43); - } - }]); - - return Sidebar; - }(_omi2.default.Component); - - exports.default = Sidebar; - -/***/ }, -/* 39 */ -/***/ function(module, exports, __webpack_require__) { - - 'use strict'; - - Object.defineProperty(exports, "__esModule", { - value: true - }); - - var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); - - var _omi = __webpack_require__(2); - - var _omi2 = _interopRequireDefault(_omi); - - function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - - function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } - - function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; } - - function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } - - var tpl = __webpack_require__(40); - var css = __webpack_require__(41); - - var List = function (_Omi$Component) { - _inherits(List, _Omi$Component); - - function List(data) { - _classCallCheck(this, List); - - var _this = _possibleConstructorReturn(this, (List.__proto__ || Object.getPrototypeOf(List)).call(this, data)); - - _omi2.default.mixIndexToArray(_this.data.list); - _this.data.currentIndex = 0; - var self = _this; - _this.data.isCurrent = function () { - return this.index === self.data.currentIndex && self.data.active; - }; - return _this; - } - - _createClass(List, [{ - key: 'goto', - value: function goto(name, index) { - var _this2 = this; - - _omi2.default.get('content').data.name = name; - _omi2.default.get('content').update(); - this.data.currentIndex = index; - this.parent.children.forEach(function (child, index) { - child.data.active = false; - if (child.id === _this2.id) { - _omi2.default.get('pager').activeIndex = index; - child.data.active = true; - } - child.update(); - }); - _omi2.default.get('pager').currentIndex = index; - _omi2.default.get('pager').update(); - document.body.scrollTop = 0; - } - }, { - key: 'render', - value: function render() { - return tpl; - } - }, { - key: 'style', - value: function style() { - return css; - } - }]); - - return List; - }(_omi2.default.Component); - - exports.default = List; - -/***/ }, -/* 40 */ -/***/ function(module, exports) { - - module.exports = "" - -/***/ }, -/* 41 */ -/***/ function(module, exports) { - - module.exports = "li.title{ font-size: 16px; font-weight: bold; margin-bottom:10px; margin-top:10px; text-indent: 23px;}li{ margin-bottom:3px; text-indent: 33px;}li a{ display:block; font-size:14px; height:20px; line-height:20px; color: #666;}li a.current{ background-color:#c3d4fc; color:white;}li a:hover{ background-color:#b3d4fc; color:white;}" - -/***/ }, -/* 42 */ -/***/ function(module, exports) { - - module.exports = "@media only screen and (max-width: 768px) { .list{ transform: translateX(-100%); background-color:white; -moz-transition: all .6s ease; -o-transition: all .6s ease; -webkit-transition: all .6s ease; transition: all .6s ease; } .list.show { -moz-transform: translateX(0%) translateZ(0); -ms-transform: translateX(0%) translateZ(0); -o-transform: translateX(0%) translateZ(0); -webkit-transform: translateX(0%) translateZ(0); transform: translateX(0%) translateZ(0); }}.list{ width:200px; text-indent: 20px; border-right: 1px solid #eee; overflow-x: hidden; overflow-y: auto; position:fixed; top:45px;}.version{ height:20px;}" - -/***/ }, -/* 43 */ -/***/ function(module, exports) { - - module.exports = "
{{#items}} {{/items}}
" - -/***/ }, -/* 44 */ -/***/ function(module, exports, __webpack_require__) { - - 'use strict'; - - Object.defineProperty(exports, "__esModule", { - value: true - }); - - var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); - - var _omi = __webpack_require__(2); - - var _omi2 = _interopRequireDefault(_omi); - - var _omiFinger = __webpack_require__(45); - - var _omiFinger2 = _interopRequireDefault(_omiFinger); - - function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - - function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } - - function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; } - - function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } - - var tpl = __webpack_require__(47); - var css = __webpack_require__(48); - - _omiFinger2.default.init(); - - var Head = function (_Omi$Component) { - _inherits(Head, _Omi$Component); - - function Head(data) { - _classCallCheck(this, Head); - - return _possibleConstructorReturn(this, (Head.__proto__ || Object.getPrototypeOf(Head)).call(this, data)); - } - - _createClass(Head, [{ - key: 'install', - value: function install() { - var _this2 = this; - - this.data.isEnLan = this.data.lan === 'en'; - document.body.addEventListener('touchend', function () { - setTimeout(function () { - _this2.removeClass(_omi2.default.get('sidebar').node, 'show'); - }, 300); - }, false); - } - }, { - key: 'toggleMenus', - value: function toggleMenus(evt) { - this.toggleClass(_omi2.default.get('sidebar').node, 'show'); - evt.stopPropagation(); - } - }, { - key: 'handleTouchEnd', - value: function handleTouchEnd(evt) { - evt.stopPropagation(); - } - }, { - key: 'toggleClass', - value: function toggleClass(element, className) { - if (!element || !className) { - return; - } - - var classString = element.className, - nameIndex = classString.indexOf(className); - if (nameIndex == -1) { - classString += ' ' + className; - } else { - classString = classString.substr(0, nameIndex) + classString.substr(nameIndex + className.length); - } - element.className = classString; - } - }, { - key: 'removeClass', - value: function removeClass(element, className) { - var classString = element.className, - nameIndex = classString.indexOf(className); - if (nameIndex !== -1) { - classString = classString.substr(0, nameIndex) + classString.substr(nameIndex + className.length); - } - element.className = classString; - } - }, { - key: 'style', - value: function style() { - return css; - } - }, { - key: 'render', - value: function render() { - return tpl; - } - }]); - - return Head; - }(_omi2.default.Component); - - exports.default = Head; - -/***/ }, -/* 45 */ -/***/ function(module, exports, __webpack_require__) { - - /*! - * omi-finger v0.1.3 by dntzhang - * Omi / AlloyFinger integration. Support touch and gesture events in your Omi project. - * Github: https://github.com/AlloyTeam/omi - * MIT Licensed. - */ - - ;(function () { - - var OmiFinger = {}; - var AlloyFinger = true - ? __webpack_require__(46) - : window.AlloyFinger; - var Omi = true - ? __webpack_require__(2) - : window.Omi; - - var noop = function(){ - - }; - - var getHandler = function(name, dom, instance) { - var value = dom.getAttribute(name); - if (value === null) { - return noop; - }else{ - return instance[value].bind(instance); - } - }; - - - OmiFinger.init = function(){ - Omi.extendPlugin('omi-finger',function(dom, instance){ - if(!instance.alloyFingerInstances)instance.alloyFingerInstances = []; - var len = instance.alloyFingerInstances.length; - var i = 0 ; - for(;i 1) r = 1; - return Math.acos(r); - } - - function cross(v1, v2) { - return v1.x * v2.y - v2.x * v1.y; - } - - function getRotateAngle(v1, v2) { - var angle = getAngle(v1, v2); - if (cross(v1, v2) > 0) { - angle *= -1; - } - - return angle * 180 / Math.PI; - } - - var HandlerAdmin = function(el) { - this.handlers = []; - this.el = el; - }; - - HandlerAdmin.prototype.add = function(handler) { - this.handlers.push(handler); - } - - HandlerAdmin.prototype.del = function(handler) { - if(!handler) this.handlers = []; - - for(var i=this.handlers.length; i>=0; i--) { - if(this.handlers[i] === handler) { - this.handlers.splice(i, 1); - } - } - } - - HandlerAdmin.prototype.dispatch = function() { - for(var i=0,len=this.handlers.length; i 0 && this.delta <= 250 && Math.abs(this.preTapPosition.x - this.x1) < 30 && Math.abs(this.preTapPosition.y - this.y1) < 30); - } - this.preTapPosition.x = this.x1; - this.preTapPosition.y = this.y1; - this.last = this.now; - var preV = this.preV, - len = evt.touches.length; - if (len > 1) { - this._cancelLongTap(); - this._cancelSingleTap(); - var v = { x: evt.touches[1].pageX - this.x1, y: evt.touches[1].pageY - this.y1 }; - preV.x = v.x; - preV.y = v.y; - this.pinchStartLen = getLen(preV); - this.multipointStart.dispatch(evt); - } - this.longTapTimeout = setTimeout(function () { - this.longTap.dispatch(evt); - }.bind(this), 750); - }, - move: function (evt) { - if (!evt.touches) return; - var preV = this.preV, - len = evt.touches.length, - currentX = evt.touches[0].pageX, - currentY = evt.touches[0].pageY; - this.isDoubleTap = false; - if (len > 1) { - var v = { x: evt.touches[1].pageX - currentX, y: evt.touches[1].pageY - currentY }; - - if (preV.x !== null) { - if (this.pinchStartLen > 0) { - evt.scale = getLen(v) / this.pinchStartLen; - this.pinch.dispatch(evt); - } - - evt.angle = getRotateAngle(v, preV); - this.rotate.dispatch(evt); - } - preV.x = v.x; - preV.y = v.y; - } else { - if (this.x2 !== null) { - evt.deltaX = currentX - this.x2; - evt.deltaY = currentY - this.y2; - - } else { - evt.deltaX = 0; - evt.deltaY = 0; - } - this.pressMove.dispatch(evt); - } - - this.touchMove.dispatch(evt); - - this._cancelLongTap(); - this.x2 = currentX; - this.y2 = currentY; - if (len > 1) { - evt.preventDefault(); - } - }, - end: function (evt) { - if (!evt.changedTouches) return; - this._cancelLongTap(); - var self = this; - if (evt.touches.length < 2) { - this.multipointEnd.dispatch(evt); - } - this.touchEnd.dispatch(evt); - //swipe - if ((this.x2 && Math.abs(this.x1 - this.x2) > 30) || - (this.y2 && Math.abs(this.y1 - this.y2) > 30)) { - evt.direction = this._swipeDirection(this.x1, this.x2, this.y1, this.y2); - this.swipeTimeout = setTimeout(function () { - self.swipe.dispatch(evt); - - }, 0) - } else { - this.tapTimeout = setTimeout(function () { - self.tap.dispatch(evt); - // trigger double tap immediately - if (self.isDoubleTap) { - self.doubleTap.dispatch(evt); - clearTimeout(self.singleTapTimeout); - self.isDoubleTap = false; - } - }, 0) - - if (!self.isDoubleTap) { - self.singleTapTimeout = setTimeout(function () { - self.singleTap.dispatch(evt); - }, 250); - } - } - - this.preV.x = 0; - this.preV.y = 0; - this.scale = 1; - this.pinchStartLen = null; - this.x1 = this.x2 = this.y1 = this.y2 = null; - }, - cancel: function (evt) { - clearTimeout(this.singleTapTimeout); - clearTimeout(this.tapTimeout); - clearTimeout(this.longTapTimeout); - clearTimeout(this.swipeTimeout); - this.touchCancel.dispatch(evt); - }, - _cancelLongTap: function () { - clearTimeout(this.longTapTimeout); - }, - _cancelSingleTap: function () { - clearTimeout(this.singleTapTimeout); - }, - _swipeDirection: function (x1, x2, y1, y2) { - return Math.abs(x1 - x2) >= Math.abs(y1 - y2) ? (x1 - x2 > 0 ? 'Left' : 'Right') : (y1 - y2 > 0 ? 'Up' : 'Down') - }, - - on: function(evt, handler) { - if(this[evt]) { - this[evt].add(handler); - } - }, - - off: function(evt, handler) { - if(this[evt]) { - this[evt].del(handler); - } - }, - - destroy: function() { - if(this.singleTapTimeout) clearTimeout(this.singleTapTimeout); - if(this.tapTimeout) clearTimeout(this.tapTimeout); - if(this.longTapTimeout) clearTimeout(this.longTapTimeout); - if(this.swipeTimeout) clearTimeout(this.swipeTimeout); - - this.element.removeEventListener("touchstart", this.start); - this.element.removeEventListener("touchmove", this.move); - this.element.removeEventListener("touchend", this.end); - this.element.removeEventListener("touchcancel", this.cancel); - - this.rotate.del(); - this.touchStart.del(); - this.multipointStart.del(); - this.multipointEnd.del(); - this.pinch.del(); - this.swipe.del(); - this.tap.del(); - this.doubleTap.del(); - this.longTap.del(); - this.singleTap.del(); - this.pressMove.del(); - this.touchMove.del(); - this.touchEnd.del(); - this.touchCancel.del(); - - this.preV = this.pinchStartLen = this.scale = this.isDoubleTap = this.delta = this.last = this.now = this.tapTimeout = this.singleTapTimeout = this.longTapTimeout = this.swipeTimeout = this.x1 = this.x2 = this.y1 = this.y2 = this.preTapPosition = this.rotate = this.touchStart = this.multipointStart = this.multipointEnd = this.pinch = this.swipe = this.tap = this.doubleTap = this.longTap = this.singleTap = this.pressMove = this.touchMove = this.touchEnd = this.touchCancel = null; - - return null; - } - }; - - if (true) { - module.exports = AlloyFinger; - } else { - window.AlloyFinger = AlloyFinger; - } - })(); - - -/***/ }, -/* 47 */ -/***/ function(module, exports) { - - module.exports = "
\"\"
Omi
" - -/***/ }, -/* 48 */ -/***/ function(module, exports) { - - module.exports = ".head{ position:fixed; height:45px; line-height: 45px; border-bottom: 1px solid #eee; width:100%; background-color:#303030; z-index:100;}ul,li{ display: inline-block;}.logo_box{ width:100px; display: inline-block; text-align:center; line-height: 60px;}.menu a,.logo_box a{ display: inline-block; height:45px; color:#ddd;}.menu{ position: absolute; right:20px;}.menu li{ margin-left:15px;}.logo_box a{ font-size: 34px; font-weight: bold; color: #00bff3; padding: 0px 15px; line-height: 45px; cursor: pointer;}.menu a:hover{ color: white;}.m_menu{ position:fixed; display:none;}@media only screen and (max-width: 768px) { .menu li{ display:none; } .menu .m_show{ display:block; } .logo_box{ display:inline-block; } .head{ text-align:center; } .m_menu{ top:0; left:0; display:block; width:50px; height:50px; padding-top: 6px; } .m_menu img{ width:30px; }}" - -/***/ }, -/* 49 */ -/***/ function(module, exports, __webpack_require__) { - - 'use strict'; - - Object.defineProperty(exports, "__esModule", { - value: true - }); - - var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); - - var _omi = __webpack_require__(2); - - var _omi2 = _interopRequireDefault(_omi); - - var _config = __webpack_require__(4); - - var _config2 = _interopRequireDefault(_config); - - var _omiFinger = __webpack_require__(45); - - var _omiFinger2 = _interopRequireDefault(_omiFinger); - - function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - - function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } - - function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; } - - function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } - - _omiFinger2.default.init(); - - var Pager = function (_Omi$Component) { - _inherits(Pager, _Omi$Component); - - function Pager(data) { - _classCallCheck(this, Pager); - - var _this = _possibleConstructorReturn(this, (Pager.__proto__ || Object.getPrototypeOf(Pager)).call(this, data)); - - _this.activeIndex = 0; - _this.currentIndex = 0; - return _this; - } - - _createClass(Pager, [{ - key: 'updatePager', - value: function updatePager() { - this.data.preMd = null; - this.data.preName = null; - this.data.nextMd = null; - this.data.nextName = null; - var item = _config2.default.menus[this.data.lan][this.activeIndex]; - - var pre = item.list[this.currentIndex - 1]; - if (pre) { - this.data.preMd = pre.md; - this.data.preName = pre.name; - } - var next = item.list[this.currentIndex + 1]; - if (next) { - this.data.nextMd = next.md; - this.data.nextName = next.name; - } - } - }, { - key: 'goto', - value: function goto(name, dir) { - var sidebar = _omi2.default.get('sidebar'); - if (dir === 'next') { - sidebar.children[this.activeIndex].goto(name, ++this.currentIndex); - } else { - sidebar.children[this.activeIndex].goto(name, --this.currentIndex); - } - this.update(); - } - }, { - key: 'handleTap', - value: function handleTap(evt) { - var dir = evt.target.getAttribute('data-dir'); - var name = evt.target.getAttribute('data-name'); - this.goto(name, dir); - } - }, { - key: 'isMobile', - value: function isMobile() { - var browser = { - versions: function () { - var u = navigator.userAgent, - app = navigator.appVersion; - return { //移动终端浏览器版本信息 - trident: u.indexOf('Trident') > -1, //IE内核 - presto: u.indexOf('Presto') > -1, //opera内核 - webKit: u.indexOf('AppleWebKit') > -1, //苹果、谷歌内核 - gecko: u.indexOf('Gecko') > -1 && u.indexOf('KHTML') == -1, //火狐内核 - mobile: !!u.match(/AppleWebKit.*Mobile.*/), //是否为移动终端 - ios: !!u.match(/\(i[^;]+;( U;)? CPU.+Mac OS X/), //ios终端 - android: u.indexOf('Android') > -1 || u.indexOf('Linux') > -1, //android终端或者uc浏览器 - iPhone: u.indexOf('iPhone') > -1, //是否为iPhone或者QQHD浏览器 - iPad: u.indexOf('iPad') > -1, //是否iPad - webApp: u.indexOf('Safari') == -1 //是否web应该程序,没有头部与底部 - }; - }(), - language: (navigator.browserLanguage || navigator.language).toLowerCase() - }; - - if (browser.versions.mobile || browser.versions.ios || browser.versions.android || browser.versions.iPhone || browser.versions.iPad) { - return true; - } - return false; - } - }, { - key: 'render', - value: function render() { - this.updatePager(); - if (this.isMobile()) { - return '\n
\n {{#preName}} \u2190{{preName}}{{/preName}}\n {{#nextName}} {{/nextName}}\n
'; - } else { - return '\n
\n {{#preName}} \u2190{{preName}}{{/preName}}\n {{#nextName}} {{/nextName}}\n
'; - } - } - }, { - key: 'style', - value: function style() { - return __webpack_require__(50); - } - }]); - - return Pager; - }(_omi2.default.Component); - - exports.default = Pager; - -/***/ }, -/* 50 */ -/***/ function(module, exports) { - - module.exports = ".pager { width:85%; height:80px; line-height:80px; position: relative; font-size:16px;}@media only screen and (max-width: 768px) { .pager { width:100%; }}.pre{ position: absolute; left:10px; top:10px;}.next{ position: absolute; right:10px; top:10px;}" - -/***/ } -]); \ No newline at end of file diff --git a/website/js/docs-cn.af59252f.js b/website/js/docs-cn.af59252f.js deleted file mode 100644 index 92dd0e0d6..000000000 --- a/website/js/docs-cn.af59252f.js +++ /dev/null @@ -1,1401 +0,0 @@ -window.Root ={}; Root.isDev = false;webpackJsonp([0],[ -/* 0 */ -/***/ function(module, exports, __webpack_require__) { - - 'use strict'; - - var _frame = __webpack_require__(1); - - var _frame2 = _interopRequireDefault(_frame); - - function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - - Omi.render(new _frame2.default({ lan: 'cn' }), 'body', true); - -/***/ }, -/* 1 */ -/***/ function(module, exports, __webpack_require__) { - - 'use strict'; - - Object.defineProperty(exports, "__esModule", { - value: true - }); - - var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); - - var _omi = __webpack_require__(2); - - var _omi2 = _interopRequireDefault(_omi); - - var _index = __webpack_require__(3); - - var _index2 = _interopRequireDefault(_index); - - var _index3 = __webpack_require__(38); - - var _index4 = _interopRequireDefault(_index3); - - var _index5 = __webpack_require__(44); - - var _index6 = _interopRequireDefault(_index5); - - var _config = __webpack_require__(4); - - var _config2 = _interopRequireDefault(_config); - - var _index7 = __webpack_require__(49); - - var _index8 = _interopRequireDefault(_index7); - - function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - - function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } - - function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; } - - function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } - - _omi2.default.makeHTML('Content', _index2.default); - _omi2.default.makeHTML('Sidebar', _index4.default); - _omi2.default.makeHTML('Head', _index6.default); - _omi2.default.makeHTML('Pager', _index8.default); - - var Frame = function (_Omi$Component) { - _inherits(Frame, _Omi$Component); - - function Frame(data) { - _classCallCheck(this, Frame); - - return _possibleConstructorReturn(this, (Frame.__proto__ || Object.getPrototypeOf(Frame)).call(this, data)); - } - - _createClass(Frame, [{ - key: 'install', - value: function install() { - var _this2 = this; - - this.setViewport(); - window.onresize = function () { - if (window.innerWidth < 768) { - _this2.refs.main.style.width = '100%'; - } else { - _this2.refs.main.style.width = window.innerWidth - 220 + 'px'; - } - }; - } - }, { - key: 'setViewport', - value: function setViewport() { - if (window.innerWidth < 768) { - this.data.width = '100%'; - } else { - this.data.width = window.innerWidth - 220 + 'px'; - } - } - }, { - key: 'style', - value: function style() { - return '\n \n '; - } - }, { - key: 'render', - value: function render() { - return '
\n \n
\n \n \n
\n \n
'; - } - }]); - - return Frame; - }(_omi2.default.Component); - - exports.default = Frame; - -/***/ }, -/* 2 */, -/* 3 */ -/***/ function(module, exports, __webpack_require__) { - - 'use strict'; - - Object.defineProperty(exports, "__esModule", { - value: true - }); - - var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); - - var _omi = __webpack_require__(2); - - var _omi2 = _interopRequireDefault(_omi); - - var _config = __webpack_require__(4); - - var _config2 = _interopRequireDefault(_config); - - var _highlightLines = __webpack_require__(5); - - var _highlightLines2 = _interopRequireDefault(_highlightLines); - - function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - - function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } - - function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; } - - function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } - - var tpl = __webpack_require__(6); - var css = __webpack_require__(7); - - var Content = function (_Omi$Component) { - _inherits(Content, _Omi$Component); - - function Content(data) { - _classCallCheck(this, Content); - - data = Object.assign({ - lan: 'cn', - name: 'installation' - }, data); - - var _this = _possibleConstructorReturn(this, (Content.__proto__ || Object.getPrototypeOf(Content)).call(this, data)); - - _this.md = new Remarkable({ html: true }); - return _this; - } - - _createClass(Content, [{ - key: 'getMarkDown', - value: function getMarkDown(name, lan) { - return __webpack_require__(8)("./" + lan + "/" + name + ".md"); - } - }, { - key: 'installed', - value: function installed() { - this.initCodeStyle(); - } - }, { - key: 'afterUpdate', - value: function afterUpdate() { - this.initCodeStyle(); - } - }, { - key: 'initCodeStyle', - value: function initCodeStyle() { - var _this2 = this; - - var codes = _omi2.default.$$("code"); - var codeHlNumArr = []; - codes.forEach(function (code) { - hljs.highlightBlock(code); - var arr = code.className.match(/{\S*}/); - var hllNums = null; - if (arr) { - var numArr = arr[0].replace(/[{|}]/g, '').split(','); - hllNums = _this2._arrToNumber(numArr); - } - codeHlNumArr.push(hllNums); - }); - - (0, _highlightLines2.default)(); - - codes.forEach(function (code, index) { - _this2._hll(code, codeHlNumArr[index]); - }); - } - }, { - key: '_arrToNumber', - value: function _arrToNumber(numArr) { - var arr = []; - numArr.forEach(function (item) { - if (item.indexOf('-') !== -1) { - var tempArr = item.split('-'); - var begin = Number(tempArr[0]); - var end = Number(tempArr[1]); - for (var i = begin; i < end + 1; i++) { - arr.push(i); - } - } else { - arr.push(Number(item)); - } - }); - return arr; - } - }, { - key: '_hll', - value: function _hll(code, hllNums) { - var spans = _omi2.default.$$('.line', code); - hllNums && hllNums.forEach(function (num) { - spans[num] && spans[num].classList.add('highlight'); - }); - } - }, { - key: 'render', - value: function render() { - this.data.html = this.md.render(this.getMarkDown(this.data.name, this.data.lan)); - return tpl; - } - }, { - key: 'style', - value: function style() { - return css; - } - }]); - - return Content; - }(_omi2.default.Component); - - exports.default = Content; - -/***/ }, -/* 4 */ -/***/ function(module, exports) { - - 'use strict'; - - Object.defineProperty(exports, "__esModule", { - value: true - }); - var config = { - menus: { - cn: [{ - active: true, - title: '快速开始', - currentIndex: 0, - list: [{ 'name': '安装', md: 'installation' }, { 'name': 'Hello World', md: 'hello_world' }, { 'name': '组件', md: 'components' }, { 'name': '组件通讯', md: 'communication' }, { 'name': '生命周期', md: 'lifecycle' }, { 'name': '事件处理', md: 'events' }, { 'name': '条件判断', md: 'condition' }, { 'name': '循环遍历', md: 'loop' }, { 'name': 'Store体系', md: 'store' }, { 'name': '表单', md: 'form' }, { 'name': '继承', md: 'inherit' }, { 'name': '模板切换', md: 'template' }, { 'name': '获取DOM节点', md: 'get_dom' }, { 'name': '插件体系', md: 'plugin' }, { 'name': 'Omi的理念', md: 'thinking_in_omi' }] - }], - en: [{ - title: 'QUICK START', - active: true, - currentIndex: 0, - list: [{ 'name': 'Installation', md: 'installation' }, { 'name': 'Hello World', md: 'hello_world' }, { 'name': 'Components', md: 'components' }, { 'name': 'Communication', md: 'communication' }, { 'name': 'Lifecycle', md: 'lifecycle' }, { 'name': 'Handling Events', md: 'events' }, { 'name': 'Conditional Rendering', md: 'condition' }, { 'name': 'Loop', md: 'loop' }, { 'name': 'Forms', md: 'form' }, { 'name': 'Inheritance', md: 'inherit' }, { 'name': 'Templates', md: 'template' }, { 'name': 'Get DOM', md: 'get_dom' }, { 'name': 'Plugin', md: 'plugin' }, { 'name': 'Thinking in Omi', md: 'thinking_in_omi' }] - }] - } - }; - - exports.default = config; - -/***/ }, -/* 5 */ -/***/ function(module, exports) { - - 'use strict'; - - Object.defineProperty(exports, "__esModule", { - value: true - }); - - // Iterates through `array`, running `callback` for each `array` element. - function forEach(array, callback) { - var i = -1, - length = array ? array.length : 0; - while (++i < length) { - callback(array[i]); - } - } - - function indexOf(array, elem) { - var i = -1, - length = array ? array.length : 0; - while (++i < length) { - if (array[i] === elem) { - return i; - } - } - } - function highlightLines() { - // TODO: mark as parsed. - forEach(document.querySelectorAll('pre code'), function (element) { - // Trim whitespace if the `data-trim` attribute is present. - if (element.hasAttribute('data-trim') && typeof element.innerHTML.trim == 'function') { - element.innerHTML = element.innerHTML.trim(); - } - - // Highlight code using highlight.js. - hljs.highlightBlock(element); - - // Split highlighted code into lines. - var openTags = [], - reHtmlTag = /<(\/?)span(?:\s+(?:class=(['"])hljs-.*?\2)?\s*|\s*)>/g; - element.innerHTML = element.innerHTML.replace(/(.*?)\r?\n/g, function (_, string) { - if (!string) { - return ' '; - } - var openTag, stringPrepend; - // Re-open all tags that were previously closed. - if (openTags.length) { - stringPrepend = openTags.join(''); - } - // Match all HTML `` tags. - reHtmlTag.lastIndex = 0; - while (openTag = reHtmlTag.exec(string)) { - // If it is a closing tag, remove the opening tag from the list. - if (openTag[1]) { - openTags.pop(); - } - // Otherwise if it is an opening tag, push it to the list. - else { - openTags.push(openTag[0]); - } - } - // Close all opened tags, so that strings can be wrapped with `span.line`. - if (openTags.length) { - string += Array(openTags.length + 1).join(''); - } - if (stringPrepend) { - string = stringPrepend + string; - } - return '' + string + ''; - }); - }); - } - - exports.default = highlightLines; - -/***/ }, -/* 6 */ -/***/ function(module, exports) { - - module.exports = "
{{{html}}}
" - -/***/ }, -/* 7 */ -/***/ function(module, exports) { - - module.exports = ".content{ width: 80%;}h3{ color:#444444;}pre{ border: 1px solid #eee; width: 100%;}li{ text-indent: 20px; list-style:disc inside ;}@media only screen and (max-width: 768px) { .content{ width: 100%; }}" - -/***/ }, -/* 8 */ -/***/ function(module, exports, __webpack_require__) { - - var map = { - "./cn/communication.md": 9, - "./cn/components.md": 10, - "./cn/condition.md": 11, - "./cn/events.md": 12, - "./cn/form.md": 13, - "./cn/get_dom.md": 14, - "./cn/hello_world.md": 15, - "./cn/inherit.md": 16, - "./cn/installation.md": 17, - "./cn/lifecycle.md": 18, - "./cn/loop.md": 19, - "./cn/plugin.md": 20, - "./cn/store.md": 21, - "./cn/template.md": 22, - "./cn/thinking_in_omi.md": 23, - "./en/communication.md": 24, - "./en/components.md": 25, - "./en/condition.md": 26, - "./en/events.md": 27, - "./en/form.md": 28, - "./en/get_dom.md": 29, - "./en/hello_world.md": 30, - "./en/inherit.md": 31, - "./en/installation.md": 32, - "./en/lifecycle.md": 33, - "./en/loop.md": 34, - "./en/plugin.md": 35, - "./en/template.md": 36, - "./en/thinking_in_omi.md": 37 - }; - function webpackContext(req) { - return __webpack_require__(webpackContextResolve(req)); - }; - function webpackContextResolve(req) { - return map[req] || (function() { throw new Error("Cannot find module '" + req + "'.") }()); - }; - webpackContext.keys = function webpackContextKeys() { - return Object.keys(map); - }; - webpackContext.resolve = webpackContextResolve; - module.exports = webpackContext; - webpackContext.id = 8; - - -/***/ }, -/* 9 */ -/***/ function(module, exports) { - - module.exports = "## 组件通讯\r\n\r\n[Omi框架](https://github.com/AlloyTeam/omi)组建间的通讯非常遍历灵活,因为有许多可选方案进行通讯:\r\n\r\n* 通过在组件上声明 data-* 传递给子节点 \r\n* 通过在组件上声明 data 传递给子节点 (支持复杂数据类型的映射)\r\n* 声明 group-data 传递(支持复杂数据类型的映射)\r\n* 完全面向对象,可以非常容易地拿到对象的实例,之后可以设置实例属性和调用实例的方法\r\n\r\n所以通讯变得畅通无阻,下面一一来举例说明。\r\n\r\n### data-*通讯 \r\n\r\n```js {36}\r\nclass Hello extends Omi.Component {\r\n constructor(data) {\r\n super(data);\r\n }\r\n \r\n style () {\r\n return `\r\n h1{\r\n \tcursor:pointer;\r\n }\r\n `;\r\n }\r\n \r\n handleClick(target, evt){\r\n alert(target.innerHTML);\r\n }\r\n \r\n render() {\r\n return `\r\n
\r\n \t

Hello ,{{name}}!

\r\n
\r\n \t\t`;\r\n }\r\n}\r\n\r\nOmi.makeHTML('Hello', Hello);\r\n\r\nclass App extends Omi.Component {\r\n constructor(data) {\r\n super(data);\r\n }\r\n \r\n render() {\r\n return `\r\n
\r\n \r\n
\r\n `;\r\n }\r\n}\r\n\r\nOmi.render(new App(),\"#container\");\r\n```\r\n\r\n一般data-*用来传递值类型,如string、number。值得注意的是,通过data-*接收到的数据类型都是string,需要自行转成number类型。\r\n通常情况下,data-*能满足我们的要求,但是遇到复杂的数据类型是没有办法通过大量data-*去表达,所以可以通过data通讯,请往下看。\r\n\r\n### data通讯 \r\n\r\n如上面代码所示,通过 data-name=\"Omi\"可以把name传递给子组件。下面的代码也可以达到同样的效果。\r\n\r\n```js {4,10}\r\n...\r\nclass App extends Omi.Component {\r\n constructor(data) {\r\n super(data);\r\n this.helloData = { name : 'Omi' };\r\n }\r\n \r\n render() {\r\n return `\r\n
\r\n \r\n
\r\n `;\r\n }\r\n}\r\n\r\nOmi.render(new App(),\"#container\");\r\n```\r\n\r\n使用data声明,会去组件的instance(也就是this)下找对应的属性,this下可以挂载任意复杂的对象。所以这也就突破了data-*的局限性。\r\n\r\n如果instance下面的某个属性下面的某个属性下面的某个数组的第一个元素的某个属性要作为data传递Hello怎么办?\r\n没关系,data声明是支持复杂类型的,使用方式如下:\r\n\r\n```js\r\n...\r\nclass App extends Omi.Component {\r\n constructor(data) {\r\n super(data);\r\n this.complexData ={\r\n a:{\r\n b:{\r\n c:[\r\n {\r\n e:[{\r\n name:'ComplexData Support1'\r\n },{\r\n name:'ComplexData Support2'\r\n }]\r\n },\r\n {\r\n name: 'ComplexData Support3'\r\n }\r\n ]\r\n }\r\n }\r\n };\r\n }\r\n \r\n render() {\r\n return `\r\n
\r\n \r\n
\r\n `;\r\n }\r\n}\r\n...\r\n```\r\n\r\n点击这里→data映射复杂数据\r\n\r\n### group-data通讯\r\n\r\ngroup-data专门是为了给一组组件批量传递data而设计。\r\n\r\n```js\r\nimport Hello from './hello.js';\r\n\r\n\r\nOmi.makeHTML('Hello', Hello);\r\n\r\nclass App extends Omi.Component {\r\n constructor(data) {\r\n super(data);\r\n this.testData = [{name: 'Omi'}, {name: 'dntzhang'}, {name: 'AlloyTeam'}];\r\n }\r\n\r\n render() {\r\n return `\r\n
\r\n \r\n \r\n \r\n
\r\n `;\r\n\r\n }\r\n}\r\n\r\nOmi.render(new App(),\"#container\");\r\n```\r\n\r\n只需要在声明的子组件上标记group-data,就会去当前组件的instance(也就是this)下面找对应的属性,然后根据当前的位置,和对应数组的位置会一一对应起来。\r\n\r\n运行结果如下:\r\n![](http://images2015.cnblogs.com/blog/105416/201702/105416-20170216110701535-1698390390.png)\r\n\r\n点击这里→group-data\r\n\r\n同样group-data支持复杂数据类型的映射,需要注意的是,group-data映射的终点必须是一个数组:\r\n\r\n```js\r\nimport Hello from './hello.js';\r\n\r\n\r\nOmi.makeHTML('Hello', Hello);\r\n\r\nclass App extends Omi.Component {\r\n constructor(data) {\r\n super(data);\r\n this.complexData ={\r\n a:{\r\n b:{\r\n c:[\r\n {\r\n e:[{\r\n name:'ComplexData Support1'\r\n },{\r\n name:'ComplexData Support2'\r\n }]\r\n },\r\n {\r\n name: 'ComplexData Support3'\r\n }\r\n ]\r\n }\r\n }\r\n };\r\n }\r\n\r\n render() {\r\n return `\r\n
\r\n \r\n \r\n
\r\n `;\r\n\r\n }\r\n}\r\n\r\nOmi.render(new App(),\"#container\");\r\n```\r\n\r\n点击这里→group-data映射复杂数据\r\n\r\n### 通过对象实例\r\n\r\n```js {7}\r\n...\r\nclass App extends Omi.Component {\r\n constructor(data) {\r\n super(data);\r\n }\r\n \r\n installed(){\r\n this.hello.data.name = \"Omi\";\r\n this.update()\r\n }\r\n \r\n render() {\r\n return `\r\n
\r\n \r\n
\r\n `;\r\n }\r\n}\r\n\r\nOmi.render(new App(),\"#container\");\r\n```\r\n\r\n### 通过omi-id\r\n\r\n```js {7,14}\r\n...\r\nclass App extends Omi.Component {\r\n constructor(data) {\r\n super(data);\r\n }\r\n \r\n installed(){\r\n Omi.get(\"hello\").data.name = \"Omi\";\r\n this.update()\r\n }\r\n \r\n render() {\r\n return `\r\n
\r\n \r\n
\r\n `;\r\n }\r\n}\r\n\r\nOmi.render(new App(),\"#container\");\r\n```\r\n\r\n通过在组件上声明omi-id,在程序任何地方拿到该对象的实例。这个可以算是跨任意组件通讯神器。\r\n\r\n" - -/***/ }, -/* 10 */ -/***/ function(module, exports) { - - module.exports = "## 组件\r\n\r\n[Omi框架](https://github.com/AlloyTeam/omi)完全基于组件体系设计,我们希望开发者可以像搭积木一样制作Web程序,一切皆是组件,组件也可以嵌套子组件形成新的组件,新的组件又可以当作子组件嵌套至任意组件形成新的组件...\r\n\r\n![](http://images2015.cnblogs.com/blog/105416/201702/105416-20170210093427338-1536910080.png)\r\n\r\n## 简单组件\r\n\r\n这里使用Todo的例子来讲解Omi组件体系的使用。\r\n\r\n```js\r\nclass Todo extends Omi.Component {\r\n constructor(data) {\r\n super(data);\r\n }\r\n \r\n add (evt) {\r\n evt.preventDefault();\r\n this.data.items.push(this.data.text);\r\n this.data.text = '';\r\n this.update();\r\n }\r\n\r\n style () {\r\n return `\r\n h3 { color:red; }\r\n button{ color:green;}\r\n `;\r\n }\r\n\r\n handleChange(target){\r\n this.data.text = target.value;\r\n }\r\n\r\n render () {\r\n return `
\r\n

TODO

\r\n
    {{#items}}
  • {{.}}
  • {{/items}}
\r\n
\r\n \r\n \r\n
\r\n
`;\r\n }\r\n}\r\n\r\nOmi.render(new Todo({ items: [] ,text : '' }),\"body\");\r\n```\r\n\r\n组件生成的HTML最终会插入到body中。上面的例子展示了Omi的部分特性:\r\n\r\n- data传递: new Todo(data,..)的data可以直接提供给render方法里的模板\r\n- 局部CSS: h3只对render里的h3生效,不会污染外面的h3;button也是同样的\r\n- 声明式事件绑定: onchange调用的就是组件内的handleChange,this可以拿到当然的DOM元素,还可以拿到当前的event\r\n- 需要手动调用update方法才能更新组件\r\n\r\n这里需要特别强调的是,为了更加的自由和灵活度。Omi没有内置数据变更的自动更新,需要开发者自己调用update方法。\r\n\r\n点击这里→在线试试\r\n\r\n## 组件嵌套\r\n\r\n如果页面超级简单的话,可以没有组件嵌套。但是绝大部分Web网页或者Web应用,需要嵌套定义的组件来完成所有的功能和展示。比如上面的Todo,我们也是可以抽取出List。\r\n这样让程序易维护、可扩展、方便复用。如,我们抽取出List:\r\n\r\n```js\r\nclass List extends Omi.Component {\r\n constructor(data) {\r\n super(data);\r\n }\r\n\r\n render () {\r\n return `
    {{#items}}
  • {{.}}
  • {{/items}}
`;\r\n }\r\n}\r\n```\r\n\r\n怎么使用这个List?我们需要使用Omi.makeHTML把List制作成可以声明式的标签,在render方法中就能直接使用该标签。如下所示:\r\n\r\n```js\r\nimport List from './list.js';\r\n\r\nOmi.makeHTML('List', List);\r\n\r\nclass Todo extends Omi.Component {\r\n constructor(data) {\r\n super(data);\r\n this.data.length = this.data.items.length;\r\n this.listData = { items : this.data.items };\r\n }\r\n\r\n add (evt) {\r\n evt.preventDefault();\r\n this.list.data.items.push(this.data.text);\r\n this.data.length = this.list.data.items.length;\r\n this.data.text = '';\r\n this.update();\r\n }\r\n\r\n style () {\r\n return `\r\n h3 { color:red; }\r\n button{ color:green;}\r\n `;\r\n }\r\n\r\n handleChange(target){\r\n this.data.text = target.value;\r\n }\r\n\r\n render () {\r\n return `
\r\n

TODO

\r\n \r\n
\r\n \r\n \r\n
\r\n
`;\r\n }\r\n}\r\n```\r\n\r\n* 第3行,通过makeHTML方法把组件制作成可以在render中使用的标签。当然Omi.makeHTML('List', List);也可以写在List组件的代码下面。\r\n* 第9行,在父组件上定义listData属性用来传递给子组件。\r\n* 第34行,在render方法中使用List组件。其中name方法可以让你在代码里通过this快速方法到该组件的实例。data=\"listData\"可以让你把this.listData传递给子组件。\r\n\r\n需要注意的是,父组件的this.listData会被通过Object.assign浅拷贝到子组件。\r\n这样做的目的主要是希望以后DOM的变更都尽量修改子组件自身的data,然后再调用其update方法,而不是去更改父组件的listData。\r\n\r\n关于Omi组件通讯其实有4种方案,这个后续教程会专门来讲。\r\n\r\n点击这里→在线试试\r\n" - -/***/ }, -/* 11 */ -/***/ function(module, exports) { - - module.exports = "## 条件判断\r\n\r\n我们经常需要根据不同的状态呈现不同的界面,比如有的用户是vip要显示vip的Logo。Omi有许多种方式满足你的要求。\r\n\r\n### 方式一\r\n\r\n```js\r\nclass ConditionTest extends Omi.Component {\r\n constructor(data) {\r\n super(data);\r\n }\r\n\r\n render () {\r\n return `{{#isVip}}\r\n
you are VIP.
\r\n {{/isVip}}\r\n {{^isVip}}\r\n
you are not VIP.
\r\n {{/isVip}}`;\r\n }\r\n}\r\n```\r\n\r\n上面完全使用mustachejs的条件判断的语法。当然Omi不强制你使用mustachejs。你可以是omi.lite.js,然后重写Omi.template方法去使用任意你喜爱的模板引擎。\r\n\r\n### 方式二\r\n\r\n```js\r\nclass ConditionTest extends Omi.Component {\r\n constructor(data) {\r\n super(data);\r\n }\r\n\r\n render () {\r\n if(this.data.isVip){\r\n return '
you are VIP.
';\r\n }else{\r\n return '
you are not VIP.
';\r\n }\r\n }\r\n}\r\n```\r\n\r\nrender就是提供了很好的可编程性,里面可以写任意js逻辑代码。对了,差点忘了,style方法里面也可以写js逻辑的。\r\n\r\n```js\r\nclass ConditionTest extends Omi.Component {\r\n constructor(data) {\r\n super(data);\r\n }\r\n\r\n style (){\r\n if(this.data.isVip){\r\n return 'div{ color : red; }';\r\n }else{\r\n return 'div{ color : green; }';\r\n }\r\n }\r\n\r\n render () {\r\n if(this.data.isVip){\r\n return '
you are VIP.
';\r\n }else{\r\n return '
you are not VIP.
';\r\n }\r\n }\r\n}\r\n```\r\n\r\n### 方式三\r\n\r\n```js\r\nclass ConditionTest extends Omi.Component {\r\n constructor(data) {\r\n super(data);\r\n }\r\n\r\n render() {\r\n return `\r\n ${this.data.isVip\r\n ?\"
you are VIP.
\"\r\n :\"
you are not VIP.
\"\r\n \t\t}\r\n `;\r\n }\r\n}\r\n```\r\n\r\n当然可以使用${ }里面写javascript代码进行输出。" - -/***/ }, -/* 12 */ -/***/ function(module, exports) { - - module.exports = "## 事件处理\r\n\r\nOmi的事件分内置事件和自定义事件。在内置事件处理方面巧妙地利用了浏览器自身的管线机制,可以通过event和this轻松拿到事件实例和触发该事件的元素。\r\n\r\n### 内置事件\r\n\r\n什么算内置事件?只要下面正则能匹配到就算内置事件。\r\n\r\n```js\r\non(abort|blur|cancel|canplay|canplaythrough|change|click|close|contextmenu|cuechange|dblclick|drag|dragend|dragenter|dragleave|dragover|dragstart|drop|durationchange|emptied|ended|error|focus|input|invalid|keydown|keypress|keyup|load|loadeddata|loadedmetadata|loadstart|mousedown|mouseenter|mouseleave|mousemove|mouseout|mouseover|mouseup|mousewheel|pause|play|playing|progress|ratechange|reset|resize|scroll|seeked|seeking|select|show|stalled|submit|suspend|timeupdate|toggle|volumechange|waiting|autocomplete|autocompleteerror|beforecopy|beforecut|beforepaste|copy|cut|paste|search|selectstart|wheel|webkitfullscreenchange|webkitfullscreenerror|touchstart|touchmove|touchend|touchcancel|pointerdown|pointerup|pointercancel|pointermove|pointerover|pointerout|pointerenter|pointerleave)\r\n```\r\n\r\n内置事件怎么绑定?如下所示:\r\n\r\n```js\r\nclass EventTest extends Omi.Component {\r\n constructor(data) {\r\n super(data);\r\n }\r\n\r\n handleClick(dom, evt){\r\n alert(dom.innerHTML);\r\n }\r\n\r\n render () {\r\n return `
Hello, Omi!
`;\r\n }\r\n}\r\n```\r\n\r\n### 自定义事件\r\n\r\n开发者自己定义的组件的事件,称为自定义事件,自定义事件必须以on开头,即onXXXX的格式,不然Omi识别不到。这里拿分页作为例子:\r\n\r\n```js\r\nimport Omi from '../../src/index.js';\r\nimport Pagination from './pagination.js';\r\nimport Content from './content.js';\r\n\r\nOmi.makeHTML('Pagination', Pagination);\r\nOmi.makeHTML('Content', Content);\r\n\r\nclass Main extends Omi.Component {\r\n constructor(data) {\r\n super(data);\r\n }\r\n\r\n installed(){\r\n this.content.goto(this.pagination.data.currentPage+1);\r\n }\r\n \r\n handlePageChange(index){\r\n this.content.goto(index+1);\r\n }\r\n\r\n render () {\r\n return `
\r\n

Pagination Example

\r\n \r\n \r\n
`;\r\n }\r\n}\r\n\r\nOmi.render( new Main(),'body');\r\n```\r\n\r\n如上面的onPageChange就是自定义事件,触发会执行handlePageChange。onPageChange方法是在Pagination中执行:\r\n\r\n```js\r\nimport Omi from '../../src/index.js';\r\n\r\nclass Pagination extends Omi.Component {\r\n ...\r\n ...\r\n ...\r\n linkTo: \"#\",\r\n prevText: \"Prev\",\r\n nextText: \"Next\",\r\n ellipseText: \"...\",\r\n prevShow: true,\r\n nextShow: true,\r\n onPageChange: function () { return false; }\r\n }, this.data);\r\n\r\n this.pageNum = Math.ceil(this.data.total / this.data.pageSize);\r\n }\r\n \r\n goto (index,evt) {\r\n evt.preventDefault();\r\n this.data.currentPage=index;\r\n this.update();\r\n this.data.onPageChange(index);\r\n }\r\n ...\r\n ...\r\n ...\r\n}\r\n```\r\n\r\n这里取了Pagination组件的部分代码。高亮的就是执行onPageChange的地方。\r\n\r\n### 相关地址\r\n\r\n* [演示地址](http://alloyteam.github.io/omi/example/pagination/)\r\n* [源码地址](https://github.com/AlloyTeam/omi/tree/master/example/pagination)\r\n" - -/***/ }, -/* 13 */ -/***/ function(module, exports) { - - module.exports = "## 表单\r\n\r\nOmi让一些表单操控起来更加方便,特别是select!\r\n\r\n### select标签\r\n\r\n以前,我们需要像如下的方式选中一个选项:\r\n\r\n```html\r\n\r\n```\r\n\r\n第三个option由于加上了selected,所有会被选中。这样带来的问题就是,开发者写的程序可能要操遍历每个option。而使用Omi,你只需要这样子:\r\n\r\n```html\r\n\r\n```\r\n\r\n这样就能达到同样的效果。比如你想选择第一项:\r\n\r\n```html\r\n\r\n```\r\n\r\n是不是非常方便?\r\n\r\n### 举个例子\r\n\r\n```js\r\nclass FormTest extends Omi.Component {\r\n constructor(data) {\r\n super(data);\r\n \r\n }\r\n\r\n handleChange(target){\r\n console.log(target.value)\r\n this.data.value = target.value;\r\n }\r\n\r\n handleSubmit(evt) {\r\n alert('Your favorite flavor is: ' + this.data.value);\r\n evt.preventDefault();\r\n }\r\n \r\n render () {\r\n return `\r\n
\r\n \r\n \r\n
`;\r\n }\r\n}\r\n\r\nOmi.render(new FormTest({ value: 'mango' }),'#container');\r\n```\r\n\r\n点击这里→在线试试" - -/***/ }, -/* 14 */ -/***/ function(module, exports) { - - module.exports = "## 获取DOM节点\r\n\r\n虽然绝大部分情况下,开发者不需要去查找获取DOM,但是还是有需要获取DOM的场景,所以Omi提供了方便获取DOM节点的方式。\r\n\r\n### ref和refs\r\n\r\n```js\r\nclass Hello extends Omi.Component {\r\n constructor(data) {\r\n super(data);\r\n }\r\n \r\n style () {\r\n return `\r\n h1{\r\n cursor:pointer;\r\n }\r\n `;\r\n }\r\n \r\n handleClick(){\r\n alert(this.refs.abc.innerHTML);\r\n }\r\n \r\n render() {\r\n return `\r\n
\r\n

Hello ,{{name}}!

\r\n
\r\n `;\r\n }\r\n}\r\n\r\nOmi.render(new Hello({ name : \"Omi\" }),\"#container\");\r\n```\r\n\r\n可以看到通过在HTML中标记ref为abc,那么就通过this.refs.abc访问到该DOM节点。\r\n\r\n点击这里→在线试试" - -/***/ }, -/* 15 */ -/***/ function(module, exports) { - - module.exports = "## Hello World\r\n\r\n你可以使用ES6+或者ES5的方式编写Omi程序来搭建你的Web程序。\r\n\r\n### Hello World with ES6+\r\n\r\n你可以使用 [webpack](https://webpack.github.io/) 打包工具,webpack会把你的模块代码打成一个很小的包,优化加载时间。使用[babel](http://babeljs.io/),让你立刻马上使用ES6+来编写你的web程序。你只需要在webpack配置的module设置好[babel-loader](https://github.com/babel/babel-loader)便可。\r\n\r\n一个Omi的简短的例子如下所示:\r\n\r\n```js\r\nimport Omi from './omi.js';\r\n\r\nclass Hello extends Omi.Component {\r\n constructor(data) {\r\n super(data);\r\n }\r\n \r\n style () {\r\n //注意,return中的包裹是可选的。主要是为了识别为JSX文件可以有CSS高亮。\r\n return `\r\n \r\n `;\r\n }\r\n \r\n handleClick(target, evt){\r\n alert(target.innerHTML);\r\n }\r\n \r\n render() {\r\n return `\r\n
\r\n

Hello ,{{name}}!

\r\n
\r\n `;\r\n }\r\n}\r\n\r\nOmi.render(new Hello({ name : \"Omi\" }),\"#container\");\r\n```\r\n\r\n组件生成的HTML最终会插入到#container中。上面的例子展示了Omi的部分特性:\r\n\r\n- data传递: new Hello(data,..)的data可以直接提供给render方法里的模板\r\n- 局部CSS: h1只对render里的h1生效,不会污染外面的h1\r\n- 声明式事件绑定: onclick调用的就是组件内的handleClick,this可以拿到当前的DOM元素,还可以拿到当前的event\r\n\r\n点击这里→在线试试\r\n\r\n你可以使用Omi.makeHTML来生成组件标签用于嵌套。\r\n```js\r\n Omi.makeHTML('Hello', Hello);\r\n```\r\n那么你就在其他组件中使用,如\r\n```js\r\n ...\r\n render() {\r\n return `\r\n
\r\n
Test
\r\n \r\n
\r\n `;\r\n }\r\n ...\r\n```\r\n\r\n点击这里→在线试试\r\n\r\n### Hello World with ES5\r\n\r\n当然Omi没有抛弃ES5的用户。你可以使用ES5的方式编写Omi。如,在你的HTML中引用omi.js:\r\n\r\n```html\r\n\r\n```\r\n\r\n然后:\r\n\r\n```js\r\nvar Hello = Omi.create(\"Hello\", {\r\n style: function () {\r\n return \"h1{ cursor:pointer }\";\r\n },\r\n \r\n handleClick: function (dom) {\r\n alert(dom.innerHTML)\r\n },\r\n \r\n render: function () {\r\n return '
\\\r\n

\\\r\n Hello ,{{name}}!\\\r\n

\\\r\n
'\r\n }\r\n});\r\n\r\nvar Test = Omi.create(\"Test\", {\r\n render: function () {\r\n return '
\\\r\n
Test
\\\r\n \\\r\n
'\r\n }\r\n});\r\n\r\nOmi.render(new Test(),'#container');\r\n```\r\n当然除了在HTML引入脚本,你还可以使用AMD、CMD或者CommonJS的方式引入Omi,这里就不再一一列举。\r\n\r\n需要注意的是,Omi.create的第一个参数Hello是用来生成Tag Name的。你可以在其他地方嵌入你的组件。如:\r\n\r\n```js\r\n ...\r\n render:function() {\r\n return '
\\\r\n \\\r\n
Test XXXX
\\\r\n \\\r\n
';\r\n }\r\n ...\r\n```\r\n\r\n点击这里→在线试试\r\n" - -/***/ }, -/* 16 */ -/***/ function(module, exports) { - - module.exports = "## 继承\r\n\r\n通过继承机制,可以利用已有的数据类型来定义新的数据类型。所定义的新的数据类型不仅拥有新定义的成员,而且还同时拥有旧的成员。我们称已存在的用来派生新类的类为基类,又称为父类。由已存在的类派生出的新类称为派生类,又称为子类。\r\n\r\n### 举个例子\r\n\r\n```js\r\nclass Hello extends Omi.Component {\r\n constructor(data) {\r\n super(data);\r\n }\r\n \r\n style () {\r\n return `\r\n div{\r\n cursor:pointer;\r\n }\r\n `;\r\n }\r\n \r\n handleClick(target, evt){\r\n alert(target.innerHTML);\r\n }\r\n \r\n render() {\r\n return '
Hello {{name}}!
'\r\n }\r\n}\r\n\r\nclass SubHello extends Hello {\r\n constructor(data) {\r\n super(data);\r\n }\r\n}\r\n\r\nOmi.render(new SubHello({ name : 'Omi' }),'#container');\r\n```\r\n\r\n点击这里→在线试试\r\n\r\n### ES5下的继承\r\n\r\n```js\r\nvar Hello = Omi.create(\"Hello\",{\r\n render:function(){\r\n return '
Hello {{name}}!
'\r\n }\r\n})\r\n\r\nvar SubHello = Omi.create(\"SubHello\",Hello,{ });\r\n\r\n\r\nOmi.render(new SubHello({ name : 'Omi' }),'#container');\r\n```\r\n\r\n点击这里→在线试试" - -/***/ }, -/* 17 */ -/***/ function(module, exports) { - - module.exports = "## 安装\n\n[Omi](https://github.com/AlloyTeam/omi)(读音 / [ˈomɪ] /, 汉字类似于 欧米) 是一款用于创建用户界面的组件化框架,开放并且现代,故得名:Omi。\n\n### 安装 Omi\n\n我们推荐使用 [npm](https://www.npmjs.com/) 来管理你的前端依赖.\n\n通过npm安装Omi,你只需要执行下面的命令:\n\n``` js\n$ npm install omi\n```\n\n## omi-cli\n\n你也可以通过omi-cli去初始化你的项目:\n\n``` js\n$ npm install omi-cli -g //安装cli\n$ omi init your_project_name //初始化项目,你也可以在一个空的文件夹下执行 omi init\n$ cd your_project_name //如果你是在空文件夹下执行的 omi init。请无视这条命令\n$ npm run dev //开发\n$ npm run dist //部署发布\n```" - -/***/ }, -/* 18 */ -/***/ function(module, exports) { - - module.exports = "## 生命周期\r\n\r\n|name |avatars |company | \r\n|---|---|---|\r\n| constructor | 构造函数 | new的时候 |\r\n| install | 初始化安装,这可以拿到用户传进的data进行处理 | 实例化 |\r\n| installed | 安装完成,HTML已经插入页面之后执行 | 实例化 |\r\n| uninstall | 卸载组件。执行remove方法会触发该事件 | 销毁时 |\r\n| beforeUpdate | 更新前 | 存在期 |\r\n| afterUpdate | 更新后 | 存在期 |\r\n\r\n## 示意图\r\n\r\n![lc](http://images2015.cnblogs.com/blog/105416/201703/105416-20170322083548924-1871234168.jpg)\r\n \r\n### 举个例子\r\n\r\n```js\r\nclass Timer extends Omi.Component {\r\n constructor(data) {\r\n super(data);\r\n }\r\n\r\n install () {\r\n this.data = {secondsElapsed: 0};\r\n }\r\n\r\n tick() {\r\n this.data.secondsElapsed++;\r\n this.update();\r\n }\r\n\r\n installed(){\r\n this.interval = setInterval(() => this.tick(), 1000);\r\n }\r\n\r\n uninstall() {\r\n clearInterval(this.interval);\r\n }\r\n\r\n\r\n style () {\r\n return `\r\n .num { color:red; }\r\n `;\r\n }\r\n\r\n render () {\r\n return `
Seconds Elapsed: {{secondsElapsed}}
`;\r\n }\r\n}\r\n```\r\n\r\n点击这里→在线试试\r\n" - -/***/ }, -/* 19 */ -/***/ function(module, exports) { - - module.exports = "## 循环遍历\r\n\r\n下面介绍mustache.js的方式和javascript遍历的方式。\r\n\r\n### 方式一\r\n\r\n```js\r\nclass List extends Omi.Component {\r\n constructor(data) {\r\n super(data);\r\n }\r\n\r\n render () {\r\n return `
\r\n
    \r\n {{#items}} \r\n
  • {{text}}
  • \r\n {{/items}}\r\n
\r\n
`;\r\n }\r\n}\r\n\r\nOmi.render(new List({\r\n items: [\r\n {id: 1, text: 'Omi'},\r\n {id: 2, text: 'dntzhang'},\r\n {id: 3, text: 'AlloyTeam'}\r\n ]\r\n}),\"body\");\r\n```\r\n\r\nmustache.js更详细的循环遍历使用可看[https://github.com/janl/mustache.js#non-empty-lists](https://github.com/janl/mustache.js#non-empty-lists)。 比如还支持:\r\n\r\n* 如果items的每一项是字符串,可以直接**{{.}}**的方式来输出每一项\r\n* 循环的时候调用定义好的函数\r\n\r\n点击这里→在线试试\r\n\r\n### 方式二\r\n\r\n既然ES6+了,当然可以使用${ }以及Array的map方法: \r\n\r\n```js\r\nclass List extends Omi.Component {\r\n constructor(data) {\r\n super(data);\r\n }\r\n\r\n render() {\r\n return `
\r\n
    \r\n ${this.data.items.map(item =>\r\n `
  • ${item.text}
  • `\r\n ).join('')}\r\n
\r\n
`;\r\n }\r\n}\r\n\r\nOmi.render(new List({\r\n items: [\r\n {id: 1, text: 'Omi'},\r\n {id: 2, text: 'dntzhang'},\r\n {id: 3, text: 'AlloyTeam'}\r\n ]\r\n}),\"body\");\r\n```\r\n\r\n你将在页面看到如下效果:\r\n\r\n![pv](http://images2015.cnblogs.com/blog/105416/201701/105416-20170122095724129-2059595233.png)\r\n\r\n点击这里→在线试试\r\n\r\n如果想在循环里加些判断呢?比如需要把id为偶数的隐藏起来:\r\n\r\n```js\r\nrender() {\r\n return `
\r\n
    \r\n ${this.data.items.map(item =>\r\n `
  • ${item.text}
  • `\r\n ).join('')}\r\n
\r\n
`;\r\n}\r\n```\r\n\r\n所以模板字符串还是非常方便,随着ES继续发展下去,模板引擎估计会慢慢消失。所以omi提供了 omi.lite.js 版本不包含任何模板引擎。" - -/***/ }, -/* 20 */ -/***/ function(module, exports) { - - module.exports = "## 插件体系\r\n\r\n[Omi](https://github.com/AlloyTeam/omi)是Web组件化框架,怎么又来了个插件的概念?\r\n\r\n可以这么理解: Omi插件体系可以赋予dom元素一些能力,并且可以和组件的实例产生关联。\r\n\r\n### omi-drag\r\n\r\n且看这个例子:\r\n\r\n点击这里→在线试试\r\n\r\n```js\r\nimport OmiDrag from './omi-drag.js';\r\n\r\nOmiDrag.init();\r\n\r\nclass App extends Omi.Component {\r\n constructor(data) {\r\n super(data);\r\n }\r\n\r\n render() {\r\n return `\r\n
\r\n
Drag Me
\r\n
\r\n `;\r\n\r\n }\r\n\r\n style(){\r\n return `\r\n .test{\r\n width:100px;\r\n height:100px;\r\n color:white;\r\n line-height:90px;\r\n text-align:center;\r\n background-color:#00BFF3;\r\n }\r\n `\r\n }\r\n}\r\n\r\nOmi.render(new App(),\"#container\");\r\n```\r\n\r\n如上面的代码所示,通过在div上标记omi-drag,这个div就能够被用户使用鼠标拖拽。我们称omi-drag.js为omi插件。\r\n是不是非常方便?那么这个omi-drag是怎么实现的?\r\n\r\n## Omi.extendPlugin\r\n\r\n核心方法: Omi.extendPlugin( pluginName, handler )\r\n\r\n下面的代码就是展示了如何通过 Omi.extendPlugin 赋予dom拖拽的能力:\r\n\r\n```js\r\n;(function () {\r\n\r\n var OmiDrag = {};\r\n var Omi = typeof require === 'function'\r\n ? require('omi')\r\n : window.Omi;\r\n\r\n OmiDrag.init = function(){\r\n Omi.extendPlugin('omi-drag',function(dom, instance){\r\n dom.style.cursor='move';\r\n var isMouseDown = false,\r\n preX = null,\r\n preY = null,\r\n currentX = null,\r\n currentY = null,\r\n translateX = 0,\r\n translateY = 0;\r\n\r\n dom.addEventListener('mousedown',function(evt){\r\n isMouseDown = true;\r\n preX = evt.pageX;\r\n preY = evt.pageY;\r\n evt.stopPropagation();\r\n },false);\r\n\r\n window.addEventListener('mousemove',function(evt){\r\n if(isMouseDown){\r\n currentX = evt.pageX;\r\n currentY = evt.pageY;\r\n if(preX != null){\r\n translateX += currentX - preX;\r\n translateY += currentY - preY;\r\n dom.style.transform = 'translateX('+translateX+'px) translateY('+translateY+'px)';\r\n }\r\n preX = currentX;\r\n preY = currentY;\r\n evt.preventDefault();\r\n }\r\n },false);\r\n\r\n window.addEventListener('mouseup',function(){\r\n isMouseDown = false;\r\n preX = preY = currentX = currentY = null;\r\n },false);\r\n });\r\n }\r\n\r\n OmiDrag.destroy = function(){\r\n delete Omi.plugins['omi-drag'];\r\n };\r\n\r\n if (typeof exports == \"object\") {\r\n module.exports = OmiDrag;\r\n } else if (typeof define == \"function\" && define.amd) {\r\n define([], function(){ return OmiDrag });\r\n } else {\r\n window.OmiDrag = OmiDrag;\r\n }\r\n\r\n})();\r\n```\r\n\r\n方法: Omi.extendPlugin( pluginName, handler )\r\n\r\n其中pluginName为插件的名称\r\n其中handler为处理器。handler可以拿到标记了pluginName的dom以及dom所在的组件的实例,即 dom 和 instance。\r\n\r\n通过 Omi.extendPlugin,可以赋予dom元素一些能力,也可以和组件的实例(instance)产生关联。\r\n但是上面的例子没有和instance产生关联,我们接下来试试:\r\n\r\n## 关联instance\r\n\r\n我们想在组件里面能够监听到move并且执行回调。如下:\r\n\r\n```js\r\n...\r\n...\r\nmoveHandler(){\r\n console.log('moving');\r\n}\r\n\r\nrender() {\r\n return `\r\n
\r\n
Drag Me
\r\n
\r\n `;\r\n}\r\n...\r\n```\r\n\r\n主要被拖动过程中,moveHandler就不断地被执行。插件代码需要修改:\r\n\r\n```js\r\n...\r\nwindow.addEventListener('mousemove',function(evt){\r\n if(isMouseDown){\r\n currentX = evt.pageX;\r\n currentY = evt.pageY;\r\n if(preX != null){\r\n translateX += currentX - preX;\r\n translateY += currentY - preY;\r\n dom.style.transform = 'translateX('+translateX+'px) translateY('+translateY+'px)';\r\n }\r\n preX = currentX;\r\n preY = currentY;\r\n evt.preventDefault();\r\n instance.moveHandler(evt);\r\n }\r\n},false);\r\n```\r\n\r\n我们在里面增加了instance.moveHandler(evt);方法,用来执行组件实例上的moveHandler方法。\r\n这样的话:就是组件的实例(instance)产生关联。但是还是有问题?如果标记了多个omi-drag 就会有问题!如:\r\n\r\n```js\r\n...\r\nrender() {\r\n return `\r\n
\r\n
Drag Me
\r\n
Drag Me
\r\n
\r\n `;\r\n}\r\n...\r\n```\r\n\r\n通常我们系统每个omi-drag都能对应一个回调函数,如:\r\n\r\n```js\r\n...\r\n...\r\nmoveHandlerA(){\r\n console.log('moving');\r\n}\r\n\r\nmoveHandlerB(){\r\n console.log('moving');\r\n}\r\n\r\nrender() {\r\n return `\r\n
\r\n
Drag Me A
\r\n
Drag Me B
\r\n
\r\n `;\r\n}\r\n...\r\n```\r\n\r\n怎么办?怎么实现?有办法!通过dom传递数据给插件。\r\n\r\n## 传递数据\r\n\r\n先来看最后实现的效果:\r\n\r\n```js\r\n...\r\n...\r\nmoveHandlerA(){\r\n console.log('moving');\r\n}\r\n\r\nmoveHandlerB(){\r\n console.log('moving');\r\n}\r\n\r\nrender() {\r\n return `\r\n
\r\n
Drag Me A
\r\n
Drag Me B
\r\n
\r\n `;\r\n}\r\n...\r\n```\r\n\r\nomi-drag修改的地方:\r\n\r\n```js\r\n...\r\nvar handlerName = dom.getAttribute('dragMove');\r\n\r\nwindow.addEventListener('mousemove',function(evt){\r\n if(isMouseDown){\r\n currentX = evt.pageX;\r\n currentY = evt.pageY;\r\n if(preX != null){\r\n translateX += currentX - preX;\r\n translateY += currentY - preY;\r\n dom.style.transform = 'translateX('+translateX+'px) translateY('+translateY+'px)';\r\n }\r\n preX = currentX;\r\n preY = currentY;\r\n evt.preventDefault();\r\n instance[handlerName](evt);\r\n }\r\n},false);\r\n...\r\n```\r\n\r\n* 通过 var handlerName = dom.getAttribute('dragMove') 拿到dom上声明的dragMove\r\n* 通过 instance[handlerName](evt) 去执行对应的方法\r\n\r\n点击这里→在线试试\r\n\r\n## 更多插件\r\n\r\n* [omi-finger](https://github.com/AlloyTeam/omi/tree/master/plugins/omi-finger) Omi的[AlloyFinger](https://github.com/AlloyTeam/AlloyFinger)插件,支持各种触摸事件和手势\r\n* [omi-transform](https://github.com/AlloyTeam/omi/tree/master/plugins/omi-transform) Omi的[transformjs](http://alloyteam.github.io/AlloyTouch/transformjs/)插件,快速方便地设置DOM的CSS3 Transform属性\r\n* [omi-touch](https://github.com/AlloyTeam/omi/tree/master/plugins/omi-touch) Omi的[AlloyTouch](https://github.com/AlloyTeam/AlloyTouch)插件,Omi项目的触摸运动解决方案(支持触摸滚动、旋转、翻页、选择等等)\r\n* [omi-jquery-date-picker](https://github.com/AlloyTeam/omi/tree/master/plugins/omi-jquery-date-picker) Omi的时间选择插件,支持各种时间或者时间区域选择\r\n" - -/***/ }, -/* 21 */ -/***/ function(module, exports) { - - module.exports = "## Store 体系\r\n\r\n先说说Store系统是干什么的!为什么要造这样一个东西?能够给系统架构带来什么?\r\n\r\n当我们组件之间,拥有共享的数据的时候,经常需要进行组件通讯。在Omi框架里,父组件传递数据给子组件非常方便:\r\n\r\n* 通过在组件上声明 data-* 或者 :data-* 传递给子节点\r\n* 通过在组件上声明 data 或者 :data 传递给子节点 (支持复杂数据类型的映射)\r\n* 声明 group-data 把数组里的data传给一堆组件传递(支持复杂数据类型的映射)\r\n\r\n注:上面带有冒号的是传递javascript表达式\r\n\r\n通过声明onXxx=\"xxxx\"可以让子组件内执行父组件的方法。具体的如下图所示:\r\n\r\n![](http://images2015.cnblogs.com/blog/105416/201703/105416-20170323100946955-1938506287.jpg)\r\n\r\n\r\n如果还不明白的话,那... 我就直接上代码了:\r\n\r\n```js\r\nclass Main extends Omi.Component {\r\n\r\n handlePageChange(index){\r\n this.content.goto(index+1)\r\n this.update()\r\n }\r\n\r\n render () {\r\n return `
\r\n

Pagination Example

\r\n \r\n \r\n
`;\r\n }\r\n}\r\n```\r\n\r\n上面的例子中,\r\n\r\n* 父组件的render方法里,通过 data-✽ 传递数据给子组件 Pagination\r\n* 通过onPageChange=\"handlePageChange\"实现子组件与父组件通讯\r\n\r\n详细代码可以点击: [分页例子地址](https://github.com/AlloyTeam/omi/tree/master/example/pagination)\r\n\r\n当然你也可以使用event emitter / pubsub库在组件之间通讯,比如这个只有 200b 的超小库[mitt](https://github.com/developit/mitt) 。但是需要注意mitt兼容到IE9+,Omi兼容IE8。但是,使用event emitter / pubsub库会对组件代码进行入侵,所以非常不建议在基础非业务组件使用这类代码库。\r\n\r\n虽然组件通讯非常方便,但是在真实的业务场景中,不仅仅是父子、爷孙、爷爷和堂兄、嫂子和堂弟...\r\nonXxx=\"xxxx\"就显得无能为力,力不从心了,各种数据传递、组件实例互操作、 emitter/pubsub或者循环依赖,让代码非常难看且难以维护。所以:\r\n\r\n\tOmi.Store是用来管理共享数据以及共享数据的逻辑 。\r\n\t\r\nOmi Store使用足够简便,对架构入侵性极极极小(3个极代表比极小还要小)。下面一步一步从todo的例子看下Store体系怎么使用。\r\n\t\r\n### 定义 Omi.Store\r\n\r\nOmi.Store是基类,我们可以继承Omi.Store来定义自己的Store,比如下面的TodoStore。\r\n\r\n```js\r\nimport Omi from 'omi'\r\n\r\nclass TodoStore extends Omi.Store {\r\n constructor(data , isReady) {\r\n super(isReady)\r\n\r\n this.data = Object.assign({\r\n items:[],\r\n length:0\r\n },data)\r\n\r\n this.data.length = this.data.items.length\r\n }\r\n\r\n add(value){\r\n this.data.items.push(value)\r\n this.data.length = this.data.items.length\r\n this.update()\r\n }\r\n\r\n clear(){\r\n this.data.items.length = 0\r\n this.data.length = 0\r\n this.update()\r\n }\r\n}\r\n\r\nexport default TodoStore\r\n```\r\n\r\nTodoStore定义了数据的基本格式和数据模型的逻辑。\r\n比如 this.data 就是数据的基本格式:\r\n\r\n```js\r\n{\r\n items:[],\r\n length:0\r\n}\r\n```\r\n\r\nadd和clear就是共享数据相关的逻辑。\r\n\r\n值得注意的是,在add和clear方法里都有调用this.update();这个是用来更新组件的,this.update并不会更新所有组件。但是他到底会更新哪些组件呢?等讲到store的addView方法你就明白了。\r\n\r\n### 创建 Omi.Store\r\n\r\n通过 new 关键字来使用TodoStore对象的实例。\r\n\r\n```js\r\nlet store = new TodoStore({ /* 初始化数据 */ ,/* 数据是否准备好 */ })\r\n```\r\n\r\n上面可以传入一些初始化配置信息,store里面便包含了整个应用程序共享的状态数据以及贡献数据逻辑方法(add,clear)。\r\n\r\n当然,这些初始化配置信息可能是异步拉取的。所以,有两种方法解决异步拉取store配置的问题:\r\n\r\n* 拉取数据,然后new TodoStore(),再Omi.render\r\n* 先let store = new TodoStore(),再Omi.render,组件内部监听store.ready,拉取数据更改store的data信息,然后执行store.beReady()\r\n\r\n\r\n### 根组件注入 store\r\n\r\n为了让组件树能够使用到 store,可以通过Omi.render的第三个参数给根组件注入 store:\r\n\r\n```js\r\nOmi.render(new Todo(),'body',{\r\n store: store\r\n});\r\n```\r\n\r\n当然ES2015已经允许你这样写了:\r\n\r\n```js\r\nOmi.render(new Todo(),'body',{\r\n store\r\n});\r\n```\r\n\r\n两份代码同样的效果。\r\n\r\n通过Omi.render注入之后,在组件树的**所有组件**都可以通过 this.$store 访问到 store。\r\n\r\n### 利用 beforeRender\r\n\r\n为什么要说beforeRender这个函数? 因为通过beforeRender转换store的data到组件的data,这样store的数据和组件的数据就解耦开了。\r\n\r\nbeforeRender是生命周期的一部分。且看下面这张图:\r\n\r\n![beforeRender](http://images2015.cnblogs.com/blog/105416/201703/105416-20170322083548924-1871234168.jpg)\r\n\r\n不管是实例化或者存在期间,在render之前,会去执行beforeRender方法。所以可以利用该方法写store的data到组件data的转换逻辑。比如:\r\n\r\n```js\r\nimport Omi from '../../src/index.js';\r\nimport List from './list.js';\r\n\r\nOmi.makeHTML('List', List);\r\n\r\nclass Todo extends Omi.Component {\r\n constructor(data) {\r\n super(data)\r\n }\r\n\r\n install(){\r\n this.$store.addView(this)\r\n }\r\n\r\n beforeRender(){\r\n this.data.length = this.$store.data.items.length\r\n }\r\n\r\n add (evt) {\r\n evt.preventDefault()\r\n let value = this.data.text\r\n this.data.text = ''\r\n this.$store.add(value)\r\n }\r\n\r\n style () {\r\n return `\r\n h3 { color:red; }\r\n button{ color:green;}\r\n `;\r\n }\r\n\r\n clear(){\r\n this.data.text = ''\r\n this.$store.clear()\r\n }\r\n\r\n handleChange(evt){\r\n this.data.text = evt.target.value\r\n }\r\n\r\n render () {\r\n return `
\r\n

TODO

\r\n \r\n \r\n
\r\n \r\n \r\n
\r\n\r\n
`;\r\n }\r\n}\r\n\r\nexport default Todo;\r\n```\r\n\r\n为什么要去写beforeRender方法?因为render只会使用this.data去渲染页面而不会去使用this.$store.data,所以需要把数据转移到组件的this.data下。这样组件既能使用自身的data,也能使用全局放this.$store.data了,不会耦合在一起。\r\n\r\n注意看上面的:\r\n\r\n```js\r\n install(){\r\n this.$store.addView(this)\r\n }\r\n```\r\n\r\n通过 addView 可以让 store 和 view(也就是组件的实例) 关联起来,以后store执行update方法的时候,关联的view都会自动更新!\r\n\r\n再看上面的子组件声明:\r\n\r\n```js\r\n\r\n```\r\n\r\n这样相当于把this.$store.data传递给了List组件。所以在List内部,就不再需要写beforeRender方法转换了。\r\n\r\n```js\r\nclass List extends Omi.Component {\r\n constructor(data) {\r\n super(data)\r\n }\r\n\r\n render () {\r\n return `
    {{#items}}
  • {{.}}
  • {{/items}}
`\r\n }\r\n}\r\n```\r\n\r\n\t这里需要特别强调,不需要把所有的数据提取到store里,只提取共享数据就好了,组件自身的数据还是放在组件自己进行管理。\r\n\r\n\r\n## 异步数据\r\n\r\n通常,在真实的业务需求中,数据并不是马上能够拿到。所以这里模拟的异步拉取的todo数据:\r\n\r\n```js\r\nlet todoStore = new TodoStore()\r\nsetTimeout(()=>{\r\n todoStore.data.items = [\"omi\",\"store\"];\r\n todoStore.data.length = todoStore.data.items.length\r\n todoStore.beReady();\r\n},2000)\r\n```\r\n\r\n上面的beReady就是代码已经准备就绪,在组件内部可以监听ready方法:\r\n\r\n```js\r\nclass Todo extends Omi.Component {\r\n constructor(data) {\r\n super(data)\r\n }\r\n\r\n install(){\r\n this.$store.addView(this)\r\n }\r\n\r\n installed(){\r\n this.$store.ready(()=>this.$store.update())\r\n }\r\n \r\n add (evt) {\r\n evt.preventDefault()\r\n if(!this.$store.isReady){\r\n return\r\n }\r\n let value = this.data.text\r\n this.data.text = ''\r\n this.$store.add(value)\r\n }\r\n```\r\n\r\n可以看到上面的add方法可以通过this.$store.isReady获取组件store是否准备就绪。\r\n\r\n## 源码地址\r\n\r\n* 更为详细的代码可以[点击这里](https://github.com/AlloyTeam/omi/tree/master/example/todo-store)\r\n* 异步拉取的代码可以[点击这里](https://github.com/AlloyTeam/omi/tree/master/example/todo-store-async)" - -/***/ }, -/* 22 */ -/***/ function(module, exports) { - - module.exports = "## 模板切换\r\n\r\nOmi有三个版本。其中的omi.js和omi.lite.js属于Web端使用的版本。\r\n\r\n* omi.js内置了[mustache.js](https://github.com/janl/mustache.js)作为模版引擎\r\n* omi.lite.js不包含任何模版引擎\r\n\r\nOmi不强制开发者使用mustache.js,你可以根据业务场景使用任意模板引擎或者不使用模板引擎。\r\n\r\n那么怎么使用别的模板引擎?下面拿[artTemplate](https://github.com/aui/artTemplate)作为例子。\r\n\r\n### 使用artTemplate\r\n\r\n```js\r\nOmi.template = function(tpl, data){\r\n return artTemplate.compile(tpl)(data);\r\n}\r\n```\r\n重写Omi.template方法,tpl为传入的模板,data为模板所需的数据,返回值为HTML。\r\n重写完毕后就能在render使用artTemplate的语法,如:\r\n\r\n```js\r\nclass List extends Omi.Component {\r\n constructor(data) {\r\n super(data);\r\n }\r\n\r\n style () {\r\n return `\r\n h1 { color:red; }\r\n li{ color:green;}\r\n `;\r\n }\r\n\r\n render () {\r\n return `

{{title}}

\r\n
    \r\n {{each list as value i}}\r\n
  • 索引 {{i + 1}} :{{value}}
  • \r\n {{/each}}\r\n
`;\r\n }\r\n}\r\n```\r\n\r\n### 相关地址\r\n\r\n* [演示地址](http://alloyteam.github.io/omi/example/artTemplate/)\r\n* [源码地址](https://github.com/AlloyTeam/omi/tree/master/example/artTemplate)" - -/***/ }, -/* 23 */ -/***/ function(module, exports) { - - module.exports = "## Omi的理念\n\nOmi的理念是基于面向对象编程体系,内建积木系统。\n 传统的单向数据流或者抛出event的组件通讯方式增加了系统的稳定性,但是丧失了灵活性。一定程度上也降低了组件的复用。所谓鱼和熊掌不可兼得。\n 面向对象体系需要多一个逻辑层,可以自由操作所有组件的instance,instance之间的逻辑关系构建出了整个程序。这样组件间的逻辑,通信,复用就全部迎刃而解。组件也更加单一职责,更松耦合。\n\n对比函数式编程、命令式编程与面向对象编程,可以归纳总结出下面几条:\n\n- 命令式编程干脆直接,利用循环条件等控制流程,强调执行过程\n- 命令式编程对硬件执行友好,运行更容易,却阻碍了复杂程序的设计\n- 函数式强调输入和输出,并非执行过程\n- 函数式倡导多个简单执行单元组合成复杂运算程序\n- 面向对象编程将对象作为程序的基本单元,更具有重用性、灵活性和扩展性\n\nJavascript是哪种类型的语言?现在ES6+已经有了class。那么他是面向对象语言?\n但是JS可以在任意地方定义函数并且当作把函数当作值来传递。那么他是函数式编程语言?\n所以,没有精准的定义,取决于你的用法和姿势。其次,Web组件化架构层面编程模型和语言层面编程模型是非常自由的关系。意思就是,你可以用Javascript构建函数式编程框架如React,也可以基于面向对象体系搭建Omi。\n\n### 函数式编程 VS 面向对象编程\n\n在UI组件框架层面,函数式编程的代表有React,Omi属于面向对象编程体系。那么他们各有什么优缺点?下面做了个对比(其实也是函数式编程与面向对象编程的对比):\n\n| | React | Omi |\n| ------------- |:-------------:|:-----:|\n| 组件通信 | ★★★★☆| ★★★★★ |\n| 稳定性 | ★★★★★ | ★★★★☆ |\n| 灵活性 | ★★★★☆| ★★★★★ |\n| 扩展性 | ★★★★☆ | ★★★★★ |\n| 测试性 | ★★★★★ | ★★★★☆ |\n| 文件大小 | ★★★☆☆ | ★★★★★ |\n| 功能特性 | ★★★☆☆ | ★★★★☆ |\n| DOM性能 | ★★★★★ | ★★★★☆ |\n| 动画性能 | ★★★★☆ | ★★★★★ |\n| 抽象复杂度 | ★★★★☆ | ★★★★★ |\n| 异步编程 | ★★★★★ | ★★★★☆ |\n\n可以看得出,鱼和熊掌不可兼得。面向对象编程更具有重用性、灵活性和扩展性,带来的问题就是更加难测试。\n具体来说,如函数式编程,其测试面积是state1 + state2 + ... + stateN;在面向对象编程中,其测试面积是state1×event1 + state2×event2 + ... + stateN×eventN。\n\n总结来说,更加推荐使用面向对象的方式去搭建UI组件化框架。\n\n
\n\n### 全文结束,感谢阅读。[开始Omi之旅吧!](https://github.com/AlloyTeam/omi) \n\n" - -/***/ }, -/* 24 */ -/***/ function(module, exports) { - - module.exports = "## Component Communication\r\n\r\nCommunication between [Omi](https://github.com/AlloyTeam/omi) components is very flexible, there are many options:\r\n\r\n- By declaring `data-*` on the component to pass data to child node\r\n- By declaring `data` on the component to pass data to child node (support complex data types mapping)\r\n- By declaring `group-data` (support complex data types mapping)\r\n- It's completely object-oriented, you can easily get the object instance, then you can set the instance of the property or call the instance of the method\r\n\r\nLet's see some examples.\r\n\r\n### Communicate by `data-*`\r\n\r\n```js\r\nclass Hello extends Omi.Component {\r\n constructor(data) {\r\n super(data);\r\n }\r\n \r\n style () {\r\n return `\r\n h1{\r\n \tcursor:pointer;\r\n }\r\n `;\r\n }\r\n \r\n handleClick(target, evt){\r\n alert(target.innerHTML);\r\n }\r\n \r\n render() {\r\n return `\r\n
\r\n \t

Hello ,{{name}}!

\r\n
\r\n \t\t`;\r\n }\r\n}\r\n\r\nOmi.makeHTML('Hello', Hello);\r\n\r\nclass App extends Omi.Component {\r\n constructor(data) {\r\n super(data);\r\n }\r\n \r\n render() {\r\n return `\r\n
\r\n \r\n
\r\n `;\r\n }\r\n}\r\n\r\nOmi.render(new App(),\"#container\");\r\n```\r\n\r\nGenerally `data-*` is used to pass value types such as string and number. It is worth noting that, through `data-*`, received data types are string. You need to manually transform it to the number type.\r\n\r\nNormally, communicate by `data-*` is enough, but sometimes we may need to use complex data types, then we can use `data` to communicate.\r\n\r\n### Communicate by `data`\r\n\r\nAs shown in the above code, name can be passed to the subcomponent by `data-name=\"Omi\"`. The following code can also achieve the same effect.\r\n\r\n```js\r\n...\r\nclass App extends Omi.Component {\r\n constructor(data) {\r\n super(data);\r\n this.helloData = { name : 'Omi' };\r\n }\r\n \r\n render() {\r\n return `\r\n
\r\n \r\n
\r\n `;\r\n }\r\n}\r\n\r\nOmi.render(new App(),\"#container\");\r\n```\r\n\r\nUse the `data` tag, it will find the property from the component instance (that is, this), this can be mounted with any complex objects. This also broke the limitations of `data-*`.\r\n\r\nThen how do we pass `data` that is in a deep depth of the instance to the Hello? No worries, `data` tag can be a complex statement:\r\n\r\n```js\r\n...\r\nclass App extends Omi.Component {\r\n constructor(data) {\r\n super(data);\r\n this.complexData ={\r\n a:{\r\n b:{\r\n c:[\r\n {\r\n e:[{\r\n name:'ComplexData Support1'\r\n },{\r\n name:'ComplexData Support2'\r\n }]\r\n },\r\n {\r\n name: 'ComplexData Support3'\r\n }\r\n ]\r\n }\r\n }\r\n };\r\n }\r\n \r\n render() {\r\n return `\r\n
\r\n \r\n
\r\n `;\r\n }\r\n}\r\n...\r\n```\r\n\r\nClick me for the complex data mapping\r\n\r\n### Communicate by `group-data`\r\n\r\n`group-data` can pass data to a group of components. \r\n\r\n```js\r\nimport Hello from './hello.js';\r\n\r\n\r\nOmi.makeHTML('Hello', Hello);\r\n\r\nclass App extends Omi.Component {\r\n constructor(data) {\r\n super(data);\r\n this.testData = [{name: 'Omi'}, {name: 'dntzhang'}, {name: 'AlloyTeam'}];\r\n }\r\n\r\n render() {\r\n return `\r\n
\r\n \r\n \r\n \r\n
\r\n `;\r\n\r\n }\r\n}\r\n\r\nOmi.render(new App(),\"#container\");\r\n```\r\n\r\nBy declaring a `group-data` tag in the sub-components, it will go to the current instance of the component (that is, `this`) to find the corresponding property. Then according to the current location, the data will pass to the positions one by one.\r\n\r\nThe results are as follows:\r\n\r\n![group-data results](http://images2015.cnblogs.com/blog/105416/201702/105416-20170216110701535-1698390390.png)\r\n\r\nClick me for the group-data example\r\n\r\nSimilarly, `group-data` supports the mapping of complex data types. It should be noted that the end of the group-data mapping must be an array:\r\n\r\n```js\r\nimport Hello from './hello.js';\r\n\r\n\r\nOmi.makeHTML('Hello', Hello);\r\n\r\nclass App extends Omi.Component {\r\n constructor(data) {\r\n super(data);\r\n this.complexData ={\r\n a:{\r\n b:{\r\n c:[\r\n {\r\n e:[{\r\n name:'ComplexData Support1'\r\n },{\r\n name:'ComplexData Support2'\r\n }]\r\n },\r\n {\r\n name: 'ComplexData Support3'\r\n }\r\n ]\r\n }\r\n }\r\n };\r\n }\r\n\r\n render() {\r\n return `\r\n
\r\n \r\n \r\n
\r\n `;\r\n\r\n }\r\n}\r\n\r\nOmi.render(new App(),\"#container\");\r\n```\r\n\r\nClick me for the complex group-data mapping\r\n\r\n### By object instance\r\n\r\n```js\r\n...\r\nclass App extends Omi.Component {\r\n constructor(data) {\r\n super(data);\r\n }\r\n \r\n installed(){\r\n this.hello.data.name = \"Omi\";\r\n this.update()\r\n }\r\n \r\n render() {\r\n return `\r\n
\r\n \r\n
\r\n `;\r\n }\r\n}\r\n\r\nOmi.render(new App(),\"#container\");\r\n```\r\n\r\n### By omi-id\r\n\r\n```js\r\n...\r\nclass App extends Omi.Component {\r\n constructor(data) {\r\n super(data);\r\n }\r\n \r\n installed(){\r\n Omi.get(\"hello\").data.name = \"Omi\";\r\n this.update()\r\n }\r\n \r\n render() {\r\n return `\r\n
\r\n \r\n
\r\n `;\r\n }\r\n}\r\n\r\nOmi.render(new App(),\"#container\");\r\n```\r\n\r\nBy declaring `omi-id` on the component, we can get the instance of the object anywhere in the program. This can be regarded as any component communication artifacts.\r\n\r\n" - -/***/ }, -/* 25 */ -/***/ function(module, exports) { - - module.exports = "## Components\r\n\r\n[Omi](https://github.com/AlloyTeam/omi) is based entirely on component architecture, which allows developers to build web applications like building blocks. Everything is components, components can be nested to create new components.\r\n\r\n![Omi Components System](http://images2015.cnblogs.com/blog/105416/201702/105416-20170210093427338-1536910080.png)\r\n\r\n### Simple Components\r\n\r\nLet's explore a simple Todo example to learn the components system in Omi.\r\n\r\n```js\r\nclass Todo extends Omi.Component {\r\n constructor(data) {\r\n super(data);\r\n }\r\n \r\n add (evt) {\r\n evt.preventDefault();\r\n this.data.items.push(this.data.text);\r\n this.data.text = '';\r\n this.update();\r\n }\r\n\r\n style () {\r\n return `\r\n h3 { color:red; }\r\n button{ color:green;}\r\n `;\r\n }\r\n\r\n handleChange(target){\r\n this.data.text = target.value;\r\n }\r\n\r\n render () {\r\n return `
\r\n

TODO

\r\n
    {{#items}}
  • {{.}}
  • {{/items}}
\r\n
\r\n \r\n \r\n
\r\n
`;\r\n }\r\n}\r\n\r\nOmi.render(new Todo({ items: [] ,text : '' }),\"body\");\r\n```\r\n\r\nThe HTML generated by the component will eventually be inserted into the body. The above example shows some of the features of Omi:\r\n\r\n- Data flow: `data` in `new Todo(data,..)` can be used directly in the template in render method.\r\n- Partial CSS: `h3` in `style()` only effect inside of render. It'll never pollute `h3` outside of this component. The same rule applies to `button`.\r\n- Declarative event binding: `onchange` will call `handleChange` that inside of the component. `this` refers to the current DOM element, `event` refers to the current DOM Event Object.\r\n- You need to manually call the `this.update()` method to update the component\r\n\r\nIt is important to note that, for more freedom and flexibility, Omi does not automatically update DOM while data changes. Developers need to call the `update` method manually.\r\n\r\nYou can also use [oba] (https://github.com/dntzhang/oba) or mobx to implement automatic updates.\r\n\r\nClick me for the live demo\r\n\r\n### Component Nesting\r\n\r\nIt's ok to not use nesting component if your page is super simple. However, for most of webpages and web applications, it is a necessary to define the nesting Components to implement complex features.\r\n\r\nFor instance, we can extract a `List` component form the Todo example. This brings maintainable, scalable and reuseable to our project:\r\n\r\n```js\r\nclass List extends Omi.Component {\r\n constructor(data) {\r\n super(data);\r\n }\r\n\r\n render () {\r\n return `
    {{#items}}
  • {{.}}
  • {{/items}}
`;\r\n }\r\n}\r\n```\r\n\r\nThen how to use this `List`? We need to use `Omi.makeHTML` to make the `List` to a tag which can be used in render method:\r\n\r\n```js\r\nimport List from './list.js';\r\n\r\nOmi.makeHTML('List', List);\r\n\r\nclass Todo extends Omi.Component {\r\n constructor(data) {\r\n super(data);\r\n this.data.length = this.data.items.length;\r\n this.listData = { items : this.data.items };\r\n }\r\n\r\n add (evt) {\r\n evt.preventDefault();\r\n this.list.data.items.push(this.data.text);\r\n this.data.length = this.list.data.items.length;\r\n this.data.text = '';\r\n this.update();\r\n }\r\n\r\n style () {\r\n return `\r\n h3 { color:red; }\r\n button{ color:green;}\r\n `;\r\n }\r\n\r\n handleChange(target){\r\n this.data.text = target.value;\r\n }\r\n\r\n render () {\r\n return `
\r\n

TODO

\r\n \r\n
\r\n \r\n \r\n
\r\n
`;\r\n }\r\n}\r\n```\r\n\r\n- In line 3, we use `makeHTML` to make the component to a tag which can be used in render method. Of course, `Omi.makeHTML('List', List);` can also be written in the end of List component.\r\n- In line 9, the parent component defines the 'listData' property\r\n- In line 34, we use List component in the render method. `name` attribute allows us easily find the instance of the component by using `this`.`data=\"listData\"` attribute allows us easily pass `this.listData` to the sub component from parent component.\r\n\r\nIt should be noted that the `data` passed from `data=\"listData\"` is cloned to the subcomponents by Object.assign(shallow copy) , which means if we want to change the DOM, we recommend that first update the `data` of the instance of subcomponent(not the parent component's `listData` ) and secondly call the `update` method.\r\n\r\nIn fact there are 4 way to communicate between components, it'll be explained later.\r\n\r\nClick me for the live demo\r\n" - -/***/ }, -/* 26 */ -/***/ function(module, exports) { - - module.exports = "## Conditional Rendering\r\n\r\nIn most case, we need to show different layouts according to different states. For example, some users are vip and we need to show vip logo for them. Omi has many ways to meet this kind of requirements.\r\n\r\n### First Option\r\n\r\n```js\r\nclass ConditionTest extends Omi.Component {\r\n constructor(data) {\r\n super(data);\r\n }\r\n\r\n render () {\r\n return `{{#isVip}}\r\n
you are VIP.
\r\n {{/isVip}}\r\n {{^isVip}}\r\n
you are not VIP.
\r\n {{/isVip}}`;\r\n }\r\n}\r\n```\r\n\r\nIn the above case, we use the condition in mustachejs for rendering. Of course Omi does not force you to use mustachejs. You can use omi.lite.js and then override the `Omi.template` method to use any of your favorite template engines.\r\n\r\n### Second Option\r\n\r\n```js\r\nclass ConditionTest extends Omi.Component {\r\n constructor(data) {\r\n super(data);\r\n }\r\n\r\n render () {\r\n if(this.data.isVip){\r\n return '
you are VIP.
';\r\n }else{\r\n return '
you are not VIP.
';\r\n }\r\n }\r\n}\r\n```\r\n\r\n`render` provides a very good programmability, which can write any js code inside. Oh, don't forget that `style` method can also have js code inside it.\r\n\r\n```js\r\nclass ConditionTest extends Omi.Component {\r\n constructor(data) {\r\n super(data);\r\n }\r\n\r\n style (){\r\n if(this.data.isVip){\r\n return 'div{ color : red; }';\r\n }else{\r\n return 'div{ color : green; }';\r\n }\r\n }\r\n\r\n render () {\r\n if(this.data.isVip){\r\n return '
you are VIP.
';\r\n }else{\r\n return '
you are not VIP.
';\r\n }\r\n }\r\n}\r\n```" - -/***/ }, -/* 27 */ -/***/ function(module, exports) { - - module.exports = "## Handling Events\r\n\r\nThere are two types of events in Omi, built-in events and custom events. Built-in events clever use of the browser's own pipeline mechanism, you can easily get events instance and the triggered event elements through `event` and `this`.\r\n\r\n### Built-in events\r\n\r\nWhat is the built-in event? As long as the it can match the following regular expression.\r\n\r\n```js\r\non(abort|blur|cancel|canplay|canplaythrough|change|click|close|contextmenu|cuechange|dblclick|drag|dragend|dragenter|dragleave|dragover|dragstart|drop|durationchange|emptied|ended|error|focus|input|invalid|keydown|keypress|keyup|load|loadeddata|loadedmetadata|loadstart|mousedown|mouseenter|mouseleave|mousemove|mouseout|mouseover|mouseup|mousewheel|pause|play|playing|progress|ratechange|reset|resize|scroll|seeked|seeking|select|show|stalled|submit|suspend|timeupdate|toggle|volumechange|waiting|autocomplete|autocompleteerror|beforecopy|beforecut|beforepaste|copy|cut|paste|search|selectstart|wheel|webkitfullscreenchange|webkitfullscreenerror|touchstart|touchmove|touchend|touchcancel|pointerdown|pointerup|pointercancel|pointermove|pointerover|pointerout|pointerenter|pointerleave)\r\n```\r\n\r\nHow to bind built-in events? As follows:\r\n\r\n```js\r\nclass EventTest extends Omi.Component {\r\n constructor(data) {\r\n super(data);\r\n }\r\n\r\n handleClick(dom, evt){\r\n alert(dom.innerHTML);\r\n }\r\n\r\n render () {\r\n return `
Hello, Omi!
`;\r\n }\r\n}\r\n```\r\n\r\n### Custom events\r\n\r\nEvents that defined by developers is the custom events. Here is the pagination example:\r\n\r\n```js\r\nimport Omi from '../../src/index.js';\r\nimport Pagination from './pagination.js';\r\nimport Content from './content.js';\r\n\r\nOmi.makeHTML('Pagination', Pagination);\r\nOmi.makeHTML('Content', Content);\r\n\r\nclass Main extends Omi.Component {\r\n constructor(data) {\r\n super(data);\r\n }\r\n\r\n installed(){\r\n this.content.goto(this.pagination.data.currentPage+1);\r\n }\r\n \r\n handlePageChange(index){\r\n this.content.goto(index+1);\r\n }\r\n\r\n render () {\r\n return `
\r\n

Pagination Example

\r\n \r\n \r\n
`;\r\n }\r\n}\r\n\r\nOmi.render( new Main(),'body');\r\n```\r\n\r\nAs we can see, the `onPageChange` is a custom event, `handlePageChange` will being executed when `onPageChange` is triggered. The `onPageChange` method is executed in `Pagination`:\r\n\r\n```js\r\nimport Omi from '../../src/index.js';\r\n\r\nclass Pagination extends Omi.Component {\r\n ...\r\n ...\r\n ...\r\n linkTo: \"#\",\r\n prevText: \"Prev\",\r\n nextText: \"Next\",\r\n ellipseText: \"...\",\r\n prevShow: true,\r\n nextShow: true,\r\n onPageChange: function () { return false; }\r\n }, this.data);\r\n\r\n this.pageNum = Math.ceil(this.data.total / this.data.pageSize);\r\n }\r\n \r\n goto (index,evt) {\r\n evt.preventDefault();\r\n this.data.currentPage=index;\r\n this.update();\r\n this.data.onPageChange(index);\r\n }\r\n ...\r\n ...\r\n ...\r\n}\r\n```\r\n\r\nThis is a part of `Pagination` code. Highlight is the place to execute `onPageChange`.\r\n\r\n### Links\r\n\r\n- [Demo](http://alloyteam.github.io/omi/example/pagination/)\r\n- [Source](https://github.com/AlloyTeam/omi/tree/master/example/pagination)" - -/***/ }, -/* 28 */ -/***/ function(module, exports) { - - module.exports = "## Forms\r\n\r\nIt's much more convenient to control forms in Omi, especially `\r\n \r\n \r\n \r\n \r\n\r\n```\r\n\r\nThe third option is selected because it is being set to `selected` attribute. The problem is that developers need to traversed each option. While using Omi, you can write code like this:\r\n\r\n```html\r\n\r\n```\r\n\r\nThis will achieve the same effect. For example, you want to choose the first item:\r\n\r\n```html\r\n\r\n```\r\n\r\nIsn't it very convenient?\r\n\r\n### For Example\r\n\r\n```js\r\nclass FormTest extends Omi.Component {\r\n constructor(data) {\r\n super(data);\r\n \r\n }\r\n\r\n handleChange(target){\r\n console.log(target.value)\r\n this.data.value = target.value;\r\n }\r\n\r\n handleSubmit(evt) {\r\n alert('Your favorite flavor is: ' + this.data.value);\r\n evt.preventDefault();\r\n }\r\n \r\n render () {\r\n return `\r\n
\r\n \r\n \r\n
`;\r\n }\r\n}\r\n\r\nOmi.render(new FormTest({ value: 'mango' }),'#container');\r\n```\r\n\r\nClick me for a live demo" - -/***/ }, -/* 29 */ -/***/ function(module, exports) { - - module.exports = "## Get DOM\r\n\r\nWhile most of the time, developers do not need to find the DOM, but sometimes is a need to get the DOM.\r\n\r\nOmi provides a way to get the DOM node.\r\n\r\n### ref and refs\r\n\r\n```js\r\nclass Hello extends Omi.Component {\r\n constructor(data) {\r\n super(data);\r\n }\r\n \r\n style () {\r\n return `\r\n h1{\r\n cursor:pointer;\r\n }\r\n `;\r\n }\r\n \r\n handleClick(){\r\n alert(this.refs.abc.innerHTML);\r\n }\r\n \r\n render() {\r\n return `\r\n
\r\n

Hello ,{{name}}!

\r\n
\r\n `;\r\n }\r\n}\r\n\r\nOmi.render(new Hello({ name : \"Omi\" }),\"#container\");\r\n```\r\n\r\nAs we can see, by referencing `ref` as `abc` in HTML, the DOM node can be accessed through `this.refs.abc`.\r\n\r\nClick me for the live demo\r\n" - -/***/ }, -/* 30 */ -/***/ function(module, exports) { - - module.exports = "## Hello World\r\n\r\n### Hello World with ES20XX \r\n\r\nWe recommend using a bundler like [webpack](https://webpack.github.io/) or [Browserify](http://browserify.org/) so you can write modular code and bundle it together into small packages to optimize load time.\r\n\r\nThe small Omi example looks like this:\r\n\r\n```js\r\nimport Omi from './omi.js';\r\n\r\nclass Hello extends Omi.Component {\r\n constructor(data) {\r\n super(data);\r\n }\r\n \r\n style () {\r\n return `\r\n h1{\r\n cursor:pointer;\r\n }\r\n `;\r\n }\r\n \r\n handleClick(target){\r\n alert(target.innerHTML);\r\n }\r\n \r\n render() {\r\n return `\r\n
\r\n

Hello ,{{name}}!

\r\n
\r\n `;\r\n }\r\n}\r\n\r\nOmi.render(new Hello({ name : \"Omi\" }),\"body\");\r\n```\r\n\r\nThis code renders into body element. \r\n\r\n### Hello World with ES5\r\n\r\n```html\r\n\r\n```\r\n\r\nthen:\r\n\r\n```js\r\nvar Hello = Omi.create(\"Hello\", {\r\n style: function () {\r\n return \"h1{ cursor:pointer }\";\r\n },\r\n \r\n handleClick: function (dom) {\r\n alert(dom.innerHTML)\r\n },\r\n \r\n render: function () {\r\n return '
\\\r\n

\\\r\n Hello ,{{name}}!\\\r\n

\\\r\n
'\r\n }\r\n});\r\n\r\nvar Test = Omi.create(\"Test\", {\r\n render: function () {\r\n return '
\\\r\n
Test
\\\r\n \\\r\n
'\r\n }\r\n});\r\n\r\nOmi.render(new Test(),'#container');\r\n```" - -/***/ }, -/* 31 */ -/***/ function(module, exports) { - - module.exports = "## Inheritance\r\n\r\nThrough the inheritance mechanism, we can define new classes base on old classes. The new classes not only have newly defined members, but also have old members at the same time.\r\n\r\nWe call the existing class the base class, also known as the parent class. And the new class derived from the existing class is called a derived class, also known as a subclass.\r\n\r\n### For Example\r\n\r\n```js\r\nclass Hello extends Omi.Component {\r\n constructor(data) {\r\n super(data);\r\n }\r\n \r\n style () {\r\n return `\r\n div{\r\n cursor:pointer;\r\n }\r\n `;\r\n }\r\n \r\n handleClick(target, evt){\r\n alert(target.innerHTML);\r\n }\r\n \r\n render() {\r\n return '
Hello {{name}}!
'\r\n }\r\n}\r\n\r\nclass SubHello extends Hello {\r\n constructor(data) {\r\n super(data);\r\n }\r\n}\r\n\r\nOmi.render(new SubHello({ name : 'Omi' }),'#container');\r\n```\r\n\r\nClick me for the live demo\r\n\r\n### inherit in ES5\r\n\r\n```js\r\nvar Hello = Omi.create(\"Hello\",{\r\n render:function(){\r\n return '
Hello {{name}}!
'\r\n }\r\n})\r\n\r\nvar SubHello = Omi.create(\"SubHello\",Hello,{ });\r\n\r\n\r\nOmi.render(new SubHello({ name : 'Omi' }),'#container');\r\n```\r\n\r\nClick me for the live demo" - -/***/ }, -/* 32 */ -/***/ function(module, exports) { - - module.exports = "## Installation\r\n\r\n[Omi](https://github.com/AlloyTeam/omi) is open and modern framework for building user interfaces.\r\n\r\n### Installing Omi\r\n\r\nWe recommend using [npm](https://www.npmjs.com/) for managing front-end dependencies. If you're new to package managers.\r\n\r\nTo install Omi with npm, run:\r\n\r\n``` js\r\n$ npm install omi\r\n```\r\n### omi-cli\r\n\r\n``` js\r\n$ npm install omi-cli -g \r\n$ omi init your_project_name \r\n$ cd your_project_name \r\n$ npm run dev \r\n$ npm run dist \r\n```" - -/***/ }, -/* 33 */ -/***/ function(module, exports) { - - module.exports = "## Lifecycle\r\n\r\n| Name | Meaning | Occasion |\r\n| :-------------: | :-------------: | :-----: |\r\n| constructor | The constructor | When new a constructor |\r\n| install | The installation. We can process the data that user pass | When instantiate |\r\n| installed | Complete the installation. It'll trigger after HTML being inserted to the page. Please note that it'll trigger when component being removed and restored | **Instantiation and existence** |\r\n| uninstall | Uninstall the component. It'll trigger when remove is executed | When destroy |\r\n| beforeUpdate | Before update | When existence |\r\n| afterUpdate | After update | When existence |\r\n\r\n## Illustration\r\n\r\n![lc](http://images2015.cnblogs.com/blog/105416/201703/105416-20170322084234049-1482108845.jpg)\r\n\r\nIt should be noted that the installed will be executed during the instantiation, which is not shown above. For example, it'll executed when a component is removed and restored, or when the new component is being added.\r\n\r\n### Examples\r\n\r\n```js\r\nclass Timer extends Omi.Component {\r\n constructor(data) {\r\n super(data);\r\n }\r\n\r\n install () {\r\n this.data = {secondsElapsed: 0};\r\n }\r\n\r\n tick() {\r\n this.data.secondsElapsed++;\r\n this.update();\r\n }\r\n\r\n installed(){\r\n this.interval = setInterval(() => this.tick(), 1000);\r\n }\r\n\r\n uninstall() {\r\n clearInterval(this.interval);\r\n }\r\n\r\n\r\n style () {\r\n return `\r\n .num { color:red; }\r\n `;\r\n }\r\n\r\n render () {\r\n return `
Seconds Elapsed: {{secondsElapsed}}
`;\r\n }\r\n}\r\n```\r\n\r\nClick me for the live demo" - -/***/ }, -/* 34 */ -/***/ function(module, exports) { - - module.exports = "## Loop\r\n\r\nThe following describes how to traverses in mustache.js and javascript.\r\n\r\n### First Option\r\n\r\n```js\r\nclass List extends Omi.Component {\r\n constructor(data) {\r\n super(data);\r\n }\r\n\r\n render () {\r\n return `
\r\n
    \r\n {{#items}} \r\n
  • {{text}}
  • \r\n {{/items}}\r\n
\r\n
`;\r\n }\r\n}\r\n\r\nOmi.render(new List({\r\n items: [\r\n {id: 1, text: 'Omi'},\r\n {id: 2, text: 'dntzhang'},\r\n {id: 3, text: 'AlloyTeam'}\r\n ]\r\n}),\"body\");\r\n```\r\n\r\nMustache.js more detailed loop traversal use can see \r\n\r\nFor more details for traversal in mustache.js please view [https://github.com/janl/mustache.js#non-empty-lists](https://github.com/janl/mustache.js#non-empty-lists).\r\n\r\nFor example, it also support:\r\n\r\n- If each item of items is a string, you can directly use **{{.}}** to output each item\r\n- Call the defined function when looping\r\n\r\nClick me for the live demo\r\n\r\n### Second Option\r\n\r\nOf course, you can also use template string inside the `map`:\r\n\r\n```js\r\nclass List extends Omi.Component {\r\n constructor(data) {\r\n super(data);\r\n }\r\n\r\n render() {\r\n return `
\r\n
    \r\n ${this.data.items.map(item =>\r\n `
  • ${item.text}
  • `\r\n ).join('')}\r\n
\r\n
`;\r\n }\r\n}\r\n\r\nOmi.render(new List({\r\n items: [\r\n {id: 1, text: 'Omi'},\r\n {id: 2, text: 'dntzhang'},\r\n {id: 3, text: 'AlloyTeam'}\r\n ]\r\n}),\"body\");\r\n```\r\n\r\nYou will see the following page:\r\n\r\n![pv](http://images2015.cnblogs.com/blog/105416/201701/105416-20170122095724129-2059595233.png)\r\n\r\nClick me for the live demo" - -/***/ }, -/* 35 */ -/***/ function(module, exports) { - - module.exports = "## Plugin\r\n\r\n[Omi](https://github.com/AlloyTeam/omi) is a componentized web framework. Then what is plugin?\r\n\r\nIt can be understood that the Omi plugin system can give the dom element some ability and can be associated with the instance of the components.\r\n\r\n### omi-drag\r\n\r\nLet's see this example:\r\n\r\nClick me for the live deme\r\n\r\n```js\r\nimport OmiDrag from './omi-drag.js';\r\n\r\nOmiDrag.init();\r\n\r\nclass App extends Omi.Component {\r\n constructor(data) {\r\n super(data);\r\n }\r\n\r\n render() {\r\n return `\r\n
\r\n
Drag Me
\r\n
\r\n `;\r\n\r\n }\r\n\r\n style(){\r\n return `\r\n .test{\r\n width:100px;\r\n height:100px;\r\n color:white;\r\n line-height:90px;\r\n text-align:center;\r\n background-color:#00BFF3;\r\n }\r\n `\r\n }\r\n}\r\n\r\nOmi.render(new App(),\"#container\");\r\n```\r\n\r\nAs shown above, by adding `omi-drag` attribute to the div, it can be dragged by the user using the mouse. We call omi-drag.js an omi plugin.\r\n\r\nIsn't it very convenient? So how did this omi-drag implement?\r\n\r\n如上面的代码所示,通过在div上标记omi-drag,这个div就能够被用户使用鼠标拖拽。我们称omi-drag.js为omi插件。\r\n是不是非常方便?那么这个omi-drag是怎么实现的?\r\n\r\n## Omi.extendPlugin\r\n\r\nCore method: Omi.extendPlugin( pluginName, handler )\r\n\r\nThe following code shows how to use `Omi.extendPlugin` to give dom the drap and drop ability:\r\n\r\n```js\r\n;(function () {\r\n\r\n var OmiDrag = {};\r\n var Omi = typeof require === 'function'\r\n ? require('omi')\r\n : window.Omi;\r\n\r\n OmiDrag.init = function(){\r\n Omi.extendPlugin('omi-drag',function(dom, instance){\r\n dom.style.cursor='move';\r\n var isMouseDown = false,\r\n preX = null,\r\n preY = null,\r\n currentX = null,\r\n currentY = null,\r\n translateX = 0,\r\n translateY = 0;\r\n\r\n dom.addEventListener('mousedown',function(evt){\r\n isMouseDown = true;\r\n preX = evt.pageX;\r\n preY = evt.pageY;\r\n evt.stopPropagation();\r\n },false);\r\n\r\n window.addEventListener('mousemove',function(evt){\r\n if(isMouseDown){\r\n currentX = evt.pageX;\r\n currentY = evt.pageY;\r\n if(preX != null){\r\n translateX += currentX - preX;\r\n translateY += currentY - preY;\r\n dom.style.transform = 'translateX('+translateX+'px) translateY('+translateY+'px)';\r\n }\r\n preX = currentX;\r\n preY = currentY;\r\n evt.preventDefault();\r\n }\r\n },false);\r\n\r\n window.addEventListener('mouseup',function(){\r\n isMouseDown = false;\r\n preX = preY = currentX = currentY = null;\r\n },false);\r\n });\r\n }\r\n\r\n OmiDrag.destroy = function(){\r\n delete Omi.plugins['omi-drag'];\r\n };\r\n\r\n if (typeof exports == \"object\") {\r\n module.exports = OmiDrag;\r\n } else if (typeof define == \"function\" && define.amd) {\r\n define([], function(){ return OmiDrag });\r\n } else {\r\n window.OmiDrag = OmiDrag;\r\n }\r\n\r\n})();\r\n```\r\n\r\nMethod: Omi.extendPlugin( pluginName, handler )\r\n\r\n`pluginName` is the name of the plugin.\r\n\r\n`handler` is the processor. The handler can get the dom which marked as the `pluginName` and the instance of the component.\r\n\r\nWith `Omi.extendPlugin`, we can give the dom some ability, and can also be associated with the component instance.\r\n\r\nThe above example is not associated with the instance, let's try it:\r\n\r\n## Associated with instance\r\n\r\nWe want to be able to listen to the `move` inside the component and perform a callback. As follows:\r\n\r\n```js\r\n...\r\n...\r\nmoveHandler(){\r\n console.log('moving');\r\n}\r\n\r\nrender() {\r\n return `\r\n
\r\n
Drag Me
\r\n
\r\n `;\r\n}\r\n...\r\n```\r\n\r\nIn this case, the `moveHandler` will be continually executed while dragging. We can modify some code to solve this issue:\r\n\r\n```js\r\n...\r\nwindow.addEventListener('mousemove',function(evt){\r\n if(isMouseDown){\r\n currentX = evt.pageX;\r\n currentY = evt.pageY;\r\n if(preX != null){\r\n translateX += currentX - preX;\r\n translateY += currentY - preY;\r\n dom.style.transform = 'translateX('+translateX+'px) translateY('+translateY+'px)';\r\n }\r\n preX = currentX;\r\n preY = currentY;\r\n evt.preventDefault();\r\n instance.moveHandler(evt);\r\n }\r\n},false);\r\n```\r\n\r\nWe add `instance.moveHandler(evt)` method to execute the `moveHandler` method of component instance.\r\n\r\nThis is how associated with instance works.\r\n\r\nHowever, this may still have an issue if we add `omi-drag` to a list of `div`:\r\n\r\n```js\r\n...\r\nrender() {\r\n return `\r\n
\r\n
Drag Me
\r\n
Drag Me
\r\n
\r\n `;\r\n}\r\n...\r\n```\r\n\r\nUsually each of our `omi-drag` can correspond to a callback function, such as:\r\n\r\n```js\r\n...\r\n...\r\nmoveHandlerA(){\r\n console.log('moving');\r\n}\r\n\r\nmoveHandlerB(){\r\n console.log('moving');\r\n}\r\n\r\nrender() {\r\n return `\r\n
\r\n
Drag Me A
\r\n
Drag Me B
\r\n
\r\n `;\r\n}\r\n...\r\n```\r\n\r\nHow to achieve this? We can pass the data to the plugin via dom.\r\n\r\n## Passing data\r\n\r\nLet's see the final code:\r\n\r\n```js\r\n...\r\n...\r\nmoveHandlerA(){\r\n console.log('moving');\r\n}\r\n\r\nmoveHandlerB(){\r\n console.log('moving');\r\n}\r\n\r\nrender() {\r\n return `\r\n
\r\n
Drag Me A
\r\n
Drag Me B
\r\n
\r\n `;\r\n}\r\n...\r\n```\r\n\r\nWhere `omi-drag` modified:\r\n\r\n```js\r\n...\r\nvar handlerName = dom.getAttribute('dragMove');\r\n\r\nwindow.addEventListener('mousemove',function(evt){\r\n if(isMouseDown){\r\n currentX = evt.pageX;\r\n currentY = evt.pageY;\r\n if(preX != null){\r\n translateX += currentX - preX;\r\n translateY += currentY - preY;\r\n dom.style.transform = 'translateX('+translateX+'px) translateY('+translateY+'px)';\r\n }\r\n preX = currentX;\r\n preY = currentY;\r\n evt.preventDefault();\r\n instance[handlerName](evt);\r\n }\r\n},false);\r\n...\r\n```\r\n\r\n- We use `var handlerName = dom.getAttribute('dragMove')` to get the `dragMove` of dom\r\n- We use `instance[handlerName](evt)` to execute the method\r\n\r\nClick me for the live demo\r\n\r\n## More plugins\r\n\r\n* [omi-finger](https://github.com/AlloyTeam/omi/tree/master/plugins/omi-finger) The [AlloyFinger](https://github.com/AlloyTeam/AlloyFinger) plugin for Omi, which support touch events and gustures\r\n* [omi-transform](https://github.com/AlloyTeam/omi/tree/master/plugins/omi-transform) The [transformjs](http://alloyteam.github.io/AlloyTouch/transformjs/) plugin for Omi, which can easily set CSS3 Transform to DOM\r\n* [omi-touch](https://github.com/AlloyTeam/omi/tree/master/plugins/omi-touch) The [AlloyTouch](https://github.com/AlloyTeam/AlloyTouch) plugin for Omi. The touch movement solution for Omi (support touch scroll, rotate, flip, select, etc.)\r\n* [omi-jquery-date-picker](https://github.com/AlloyTeam/omi/tree/master/plugins/omi-jquery-date-picker) The date picker plugin for Omi, which support choose any time zone\r\n" - -/***/ }, -/* 36 */ -/***/ function(module, exports) { - - module.exports = "## Templates\r\n\r\nThere are three types of Omi. omi.js and omi.lite.js is for web side.\r\n\r\n- omi.js has a built-in [mustache.js](https://github.com/janl/mustache.js) as the template engine\r\n- omi.lite.js doesn't have any template engines\r\n\r\nOmi does not force developers to use mustache.js, you can use any template engine based on business scenarios or do not use any template engines.\r\n\r\nHow to use other template engines? Let's see the [artTemplate](https://github.com/aui/artTemplate) example.\r\n\r\n### Use artTemplate\r\n\r\n```js\r\nOmi.template = function(tpl, data){\r\n return artTemplate.compile(tpl)(data);\r\n}\r\n```\r\n\r\nWe need to rewrite the `Omi.template` method, the `tpl` is the incoming template, the `data` is the required data for the template, and the return value is HTML.\r\n\r\nAfter rewriting, you can use the artTemplate syntax in `render`, such as:\r\n\r\n```js\r\nclass List extends Omi.Component {\r\n constructor(data) {\r\n super(data);\r\n }\r\n\r\n style () {\r\n return `\r\n h1 { color:red; }\r\n li{ color:green;}\r\n `;\r\n }\r\n\r\n render () {\r\n return `

{{title}}

\r\n
    \r\n {{each list as value i}}\r\n
  • # {{i + 1}} :{{value}}
  • \r\n {{/each}}\r\n
`;\r\n }\r\n}\r\n```\r\n\r\n### Links\r\n\r\n* [Demo Link](http://alloyteam.github.io/omi/example/artTemplate/)\r\n* [Source Code](https://github.com/AlloyTeam/omi/tree/master/example/artTemplate)" - -/***/ }, -/* 37 */ -/***/ function(module, exports) { - - module.exports = "## Thinking in Omi\r\n\r\nOmi is based on object-oriented programming, with plugin system.\r\n\r\nThe traditional one-way data flow or the event-throwing component communicating can increase the stability of the system, but it loses it's flexibility. To a certain extent also reduced the component reusing.\r\n\r\nObject-oriented system has an other logical layer, which let you control the instance of components. The logic between instances build the entire program.\r\n\r\nThen the issues like communication, reusing and logics between components are all solved.\r\n\r\n\r\nPlus, the component is also more single duty, more loosely coupled.\r\n\r\nFor functional programming, imperative programming and object-oriented programming, we can sum up the following list:\r\n\r\n- Imperative programming is well understood, we use loop and if-else condition to control processes, it emphasize the process of execution\r\n- Imperative programming is hardware friendly, easy to run, but hard to design complex program\r\n- Functional programming is all about input and output, not the process of execution\r\n- Functional programming advocates multiple simple execution units into complex operations\r\n- Object-oriented programming uses objects as the basic unit of the program, with more reusability, flexibility, and extensibility\r\n\r\nWhat kind of language is JavaScript? We have `class` in ES6+, so is JavaScript object-oriented language?\r\n\r\nJavaScript can pass a function as a argumant, so is JavaScript a functional language?\r\n\r\nThere are no right answer, it depands on how you use JavaScript.\r\n\r\nIt's free to chooce, you can use functional programming framework like React, or object-oriented framework like Omi. \r\n\r\n### Functional Programming VS Object-Oriented Programming\r\n\r\nIn the UI component framework scope, functional programming is represented by React, while Omi belongs to object-oriented programming.\r\n\r\nSo what are their strengths and weaknesses? The following is a comparison (in fact, functional programming and object-oriented programming comparison):\r\n\r\n| | React | Omi |\r\n| ------------- |:-------------:|:-----:|\r\n| Component communication | ★★★★☆| ★★★★★ |\r\n| Stability | ★★★★★ | ★★★★☆ |\r\n| Flexibility | ★★★★☆| ★★★★★ |\r\n| Scalability | ★★★★☆ | ★★★★★ |\r\n| Testability | ★★★★★ | ★★★★☆ |\r\n| File size | ★★★☆☆ | ★★★★★ |\r\n| Features | ★★★☆☆ | ★★★★☆ |\r\n| DOM performance | ★★★★★ | ★★★★☆ |\r\n| Animation performance | ★★★★☆ | ★★★★★ |\r\n| Abstract complexity | ★★★★☆ | ★★★★★ |\r\n| Asynchronous programming | ★★★★★ | ★★★★☆ |\r\n\r\nAs we can see, we can not have it both ways. Object-oriented programming is more reusable, flexible and scalable, the problem is more difficult to test.\r\n\r\nSpecifically, if the functional programming, the test area is state1 + state2 + ... + stateN; in object-oriented programming, the test area is state1 × event1 + state2 × event2 + ... + stateN × eventN.\r\n\r\nIn summary, it is more recommended to use the object-oriented programming to build UI component framework.\r\n\r\n
\r\n\r\n### The end. Thanks for reading. [Let's start the Omi journey](https://github.com/AlloyTeam/omi)!\r\n" - -/***/ }, -/* 38 */ -/***/ function(module, exports, __webpack_require__) { - - 'use strict'; - - Object.defineProperty(exports, "__esModule", { - value: true - }); - - var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); - - var _omi = __webpack_require__(2); - - var _omi2 = _interopRequireDefault(_omi); - - var _index = __webpack_require__(39); - - var _index2 = _interopRequireDefault(_index); - - var _config = __webpack_require__(4); - - var _config2 = _interopRequireDefault(_config); - - function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - - function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } - - function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; } - - function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } - - _omi2.default.makeHTML('List', _index2.default); - - var Sidebar = function (_Omi$Component) { - _inherits(Sidebar, _Omi$Component); - - function Sidebar(data) { - _classCallCheck(this, Sidebar); - - return _possibleConstructorReturn(this, (Sidebar.__proto__ || Object.getPrototypeOf(Sidebar)).call(this, data)); - } - - _createClass(Sidebar, [{ - key: 'install', - value: function install() { - this.data.items = _config2.default['menus'][this.data.lan]; - this.data.height = window.innerHeight - 45; - } - }, { - key: 'style', - value: function style() { - return __webpack_require__(42); - } - }, { - key: 'render', - value: function render() { - return __webpack_require__(43); - } - }]); - - return Sidebar; - }(_omi2.default.Component); - - exports.default = Sidebar; - -/***/ }, -/* 39 */ -/***/ function(module, exports, __webpack_require__) { - - 'use strict'; - - Object.defineProperty(exports, "__esModule", { - value: true - }); - - var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); - - var _omi = __webpack_require__(2); - - var _omi2 = _interopRequireDefault(_omi); - - function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - - function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } - - function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; } - - function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } - - var tpl = __webpack_require__(40); - var css = __webpack_require__(41); - - var List = function (_Omi$Component) { - _inherits(List, _Omi$Component); - - function List(data) { - _classCallCheck(this, List); - - var _this = _possibleConstructorReturn(this, (List.__proto__ || Object.getPrototypeOf(List)).call(this, data)); - - _omi2.default.mixIndexToArray(_this.data.list); - _this.data.currentIndex = 0; - var self = _this; - _this.data.isCurrent = function () { - return this.index === self.data.currentIndex && self.data.active; - }; - return _this; - } - - _createClass(List, [{ - key: 'goto', - value: function goto(name, index) { - var _this2 = this; - - _omi2.default.get('content').data.name = name; - _omi2.default.get('content').update(); - this.data.currentIndex = index; - this.parent.children.forEach(function (child, index) { - child.data.active = false; - if (child.id === _this2.id) { - _omi2.default.get('pager').activeIndex = index; - child.data.active = true; - } - child.update(); - }); - _omi2.default.get('pager').currentIndex = index; - _omi2.default.get('pager').update(); - document.body.scrollTop = 0; - } - }, { - key: 'render', - value: function render() { - return tpl; - } - }, { - key: 'style', - value: function style() { - return css; - } - }]); - - return List; - }(_omi2.default.Component); - - exports.default = List; - -/***/ }, -/* 40 */ -/***/ function(module, exports) { - - module.exports = "" - -/***/ }, -/* 41 */ -/***/ function(module, exports) { - - module.exports = "li.title{ font-size: 16px; font-weight: bold; margin-bottom:10px; margin-top:10px; text-indent: 23px;}li{ margin-bottom:3px; text-indent: 33px;}li a{ display:block; font-size:14px; height:20px; line-height:20px; color: #666;}li a.current{ background-color:#c3d4fc; color:white;}li a:hover{ background-color:#b3d4fc; color:white;}" - -/***/ }, -/* 42 */ -/***/ function(module, exports) { - - module.exports = "@media only screen and (max-width: 768px) { .list{ transform: translateX(-100%); background-color:white; -moz-transition: all .6s ease; -o-transition: all .6s ease; -webkit-transition: all .6s ease; transition: all .6s ease; } .list.show { -moz-transform: translateX(0%) translateZ(0); -ms-transform: translateX(0%) translateZ(0); -o-transform: translateX(0%) translateZ(0); -webkit-transform: translateX(0%) translateZ(0); transform: translateX(0%) translateZ(0); }}.list{ width:200px; text-indent: 20px; border-right: 1px solid #eee; overflow-x: hidden; overflow-y: auto; position:fixed; top:45px;}.version{ height:20px;}" - -/***/ }, -/* 43 */ -/***/ function(module, exports) { - - module.exports = "
{{#items}} {{/items}}
" - -/***/ }, -/* 44 */ -/***/ function(module, exports, __webpack_require__) { - - 'use strict'; - - Object.defineProperty(exports, "__esModule", { - value: true - }); - - var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); - - var _omi = __webpack_require__(2); - - var _omi2 = _interopRequireDefault(_omi); - - var _omiFinger = __webpack_require__(45); - - var _omiFinger2 = _interopRequireDefault(_omiFinger); - - function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - - function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } - - function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; } - - function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } - - var tpl = __webpack_require__(47); - var css = __webpack_require__(48); - - _omiFinger2.default.init(); - - var Head = function (_Omi$Component) { - _inherits(Head, _Omi$Component); - - function Head(data) { - _classCallCheck(this, Head); - - return _possibleConstructorReturn(this, (Head.__proto__ || Object.getPrototypeOf(Head)).call(this, data)); - } - - _createClass(Head, [{ - key: 'install', - value: function install() { - var _this2 = this; - - this.data.isEnLan = this.data.lan === 'en'; - document.body.addEventListener('touchend', function () { - setTimeout(function () { - _this2.removeClass(_omi2.default.get('sidebar').node, 'show'); - }, 300); - }, false); - } - }, { - key: 'toggleMenus', - value: function toggleMenus(evt) { - this.toggleClass(_omi2.default.get('sidebar').node, 'show'); - evt.stopPropagation(); - } - }, { - key: 'handleTouchEnd', - value: function handleTouchEnd(evt) { - evt.stopPropagation(); - } - }, { - key: 'toggleClass', - value: function toggleClass(element, className) { - if (!element || !className) { - return; - } - - var classString = element.className, - nameIndex = classString.indexOf(className); - if (nameIndex == -1) { - classString += ' ' + className; - } else { - classString = classString.substr(0, nameIndex) + classString.substr(nameIndex + className.length); - } - element.className = classString; - } - }, { - key: 'removeClass', - value: function removeClass(element, className) { - var classString = element.className, - nameIndex = classString.indexOf(className); - if (nameIndex !== -1) { - classString = classString.substr(0, nameIndex) + classString.substr(nameIndex + className.length); - } - element.className = classString; - } - }, { - key: 'style', - value: function style() { - return css; - } - }, { - key: 'render', - value: function render() { - return tpl; - } - }]); - - return Head; - }(_omi2.default.Component); - - exports.default = Head; - -/***/ }, -/* 45 */ -/***/ function(module, exports, __webpack_require__) { - - /*! - * omi-finger v0.1.3 by dntzhang - * Omi / AlloyFinger integration. Support touch and gesture events in your Omi project. - * Github: https://github.com/AlloyTeam/omi - * MIT Licensed. - */ - - ;(function () { - - var OmiFinger = {}; - var AlloyFinger = true - ? __webpack_require__(46) - : window.AlloyFinger; - var Omi = true - ? __webpack_require__(2) - : window.Omi; - - var noop = function(){ - - }; - - var getHandler = function(name, dom, instance) { - var value = dom.getAttribute(name); - if (value === null) { - return noop; - }else{ - return instance[value].bind(instance); - } - }; - - - OmiFinger.init = function(){ - Omi.extendPlugin('omi-finger',function(dom, instance){ - if(!instance.alloyFingerInstances)instance.alloyFingerInstances = []; - var len = instance.alloyFingerInstances.length; - var i = 0 ; - for(;i 1) r = 1; - return Math.acos(r); - } - - function cross(v1, v2) { - return v1.x * v2.y - v2.x * v1.y; - } - - function getRotateAngle(v1, v2) { - var angle = getAngle(v1, v2); - if (cross(v1, v2) > 0) { - angle *= -1; - } - - return angle * 180 / Math.PI; - } - - var HandlerAdmin = function(el) { - this.handlers = []; - this.el = el; - }; - - HandlerAdmin.prototype.add = function(handler) { - this.handlers.push(handler); - } - - HandlerAdmin.prototype.del = function(handler) { - if(!handler) this.handlers = []; - - for(var i=this.handlers.length; i>=0; i--) { - if(this.handlers[i] === handler) { - this.handlers.splice(i, 1); - } - } - } - - HandlerAdmin.prototype.dispatch = function() { - for(var i=0,len=this.handlers.length; i 0 && this.delta <= 250 && Math.abs(this.preTapPosition.x - this.x1) < 30 && Math.abs(this.preTapPosition.y - this.y1) < 30); - } - this.preTapPosition.x = this.x1; - this.preTapPosition.y = this.y1; - this.last = this.now; - var preV = this.preV, - len = evt.touches.length; - if (len > 1) { - this._cancelLongTap(); - this._cancelSingleTap(); - var v = { x: evt.touches[1].pageX - this.x1, y: evt.touches[1].pageY - this.y1 }; - preV.x = v.x; - preV.y = v.y; - this.pinchStartLen = getLen(preV); - this.multipointStart.dispatch(evt); - } - this.longTapTimeout = setTimeout(function () { - this.longTap.dispatch(evt); - }.bind(this), 750); - }, - move: function (evt) { - if (!evt.touches) return; - var preV = this.preV, - len = evt.touches.length, - currentX = evt.touches[0].pageX, - currentY = evt.touches[0].pageY; - this.isDoubleTap = false; - if (len > 1) { - var v = { x: evt.touches[1].pageX - currentX, y: evt.touches[1].pageY - currentY }; - - if (preV.x !== null) { - if (this.pinchStartLen > 0) { - evt.scale = getLen(v) / this.pinchStartLen; - this.pinch.dispatch(evt); - } - - evt.angle = getRotateAngle(v, preV); - this.rotate.dispatch(evt); - } - preV.x = v.x; - preV.y = v.y; - } else { - if (this.x2 !== null) { - evt.deltaX = currentX - this.x2; - evt.deltaY = currentY - this.y2; - - } else { - evt.deltaX = 0; - evt.deltaY = 0; - } - this.pressMove.dispatch(evt); - } - - this.touchMove.dispatch(evt); - - this._cancelLongTap(); - this.x2 = currentX; - this.y2 = currentY; - if (len > 1) { - evt.preventDefault(); - } - }, - end: function (evt) { - if (!evt.changedTouches) return; - this._cancelLongTap(); - var self = this; - if (evt.touches.length < 2) { - this.multipointEnd.dispatch(evt); - } - this.touchEnd.dispatch(evt); - //swipe - if ((this.x2 && Math.abs(this.x1 - this.x2) > 30) || - (this.y2 && Math.abs(this.y1 - this.y2) > 30)) { - evt.direction = this._swipeDirection(this.x1, this.x2, this.y1, this.y2); - this.swipeTimeout = setTimeout(function () { - self.swipe.dispatch(evt); - - }, 0) - } else { - this.tapTimeout = setTimeout(function () { - self.tap.dispatch(evt); - // trigger double tap immediately - if (self.isDoubleTap) { - self.doubleTap.dispatch(evt); - clearTimeout(self.singleTapTimeout); - self.isDoubleTap = false; - } - }, 0) - - if (!self.isDoubleTap) { - self.singleTapTimeout = setTimeout(function () { - self.singleTap.dispatch(evt); - }, 250); - } - } - - this.preV.x = 0; - this.preV.y = 0; - this.scale = 1; - this.pinchStartLen = null; - this.x1 = this.x2 = this.y1 = this.y2 = null; - }, - cancel: function (evt) { - clearTimeout(this.singleTapTimeout); - clearTimeout(this.tapTimeout); - clearTimeout(this.longTapTimeout); - clearTimeout(this.swipeTimeout); - this.touchCancel.dispatch(evt); - }, - _cancelLongTap: function () { - clearTimeout(this.longTapTimeout); - }, - _cancelSingleTap: function () { - clearTimeout(this.singleTapTimeout); - }, - _swipeDirection: function (x1, x2, y1, y2) { - return Math.abs(x1 - x2) >= Math.abs(y1 - y2) ? (x1 - x2 > 0 ? 'Left' : 'Right') : (y1 - y2 > 0 ? 'Up' : 'Down') - }, - - on: function(evt, handler) { - if(this[evt]) { - this[evt].add(handler); - } - }, - - off: function(evt, handler) { - if(this[evt]) { - this[evt].del(handler); - } - }, - - destroy: function() { - if(this.singleTapTimeout) clearTimeout(this.singleTapTimeout); - if(this.tapTimeout) clearTimeout(this.tapTimeout); - if(this.longTapTimeout) clearTimeout(this.longTapTimeout); - if(this.swipeTimeout) clearTimeout(this.swipeTimeout); - - this.element.removeEventListener("touchstart", this.start); - this.element.removeEventListener("touchmove", this.move); - this.element.removeEventListener("touchend", this.end); - this.element.removeEventListener("touchcancel", this.cancel); - - this.rotate.del(); - this.touchStart.del(); - this.multipointStart.del(); - this.multipointEnd.del(); - this.pinch.del(); - this.swipe.del(); - this.tap.del(); - this.doubleTap.del(); - this.longTap.del(); - this.singleTap.del(); - this.pressMove.del(); - this.touchMove.del(); - this.touchEnd.del(); - this.touchCancel.del(); - - this.preV = this.pinchStartLen = this.scale = this.isDoubleTap = this.delta = this.last = this.now = this.tapTimeout = this.singleTapTimeout = this.longTapTimeout = this.swipeTimeout = this.x1 = this.x2 = this.y1 = this.y2 = this.preTapPosition = this.rotate = this.touchStart = this.multipointStart = this.multipointEnd = this.pinch = this.swipe = this.tap = this.doubleTap = this.longTap = this.singleTap = this.pressMove = this.touchMove = this.touchEnd = this.touchCancel = null; - - return null; - } - }; - - if (true) { - module.exports = AlloyFinger; - } else { - window.AlloyFinger = AlloyFinger; - } - })(); - - -/***/ }, -/* 47 */ -/***/ function(module, exports) { - - module.exports = "
\"\"
Omi
" - -/***/ }, -/* 48 */ -/***/ function(module, exports) { - - module.exports = ".head{ position:fixed; height:45px; line-height: 45px; border-bottom: 1px solid #eee; width:100%; background-color:#303030; z-index:100;}ul,li{ display: inline-block;}.logo_box{ width:100px; display: inline-block; text-align:center; line-height: 60px;}.menu a,.logo_box a{ display: inline-block; height:45px; color:#ddd;}.menu{ position: absolute; right:20px;}.menu li{ margin-left:15px;}.logo_box a{ font-size: 34px; font-weight: bold; color: #00bff3; padding: 0px 15px; line-height: 45px; cursor: pointer;}.menu a:hover{ color: white;}.m_menu{ position:fixed; display:none;}@media only screen and (max-width: 768px) { .menu li{ display:none; } .menu .m_show{ display:block; } .logo_box{ display:inline-block; } .head{ text-align:center; } .m_menu{ top:0; left:0; display:block; width:50px; height:50px; padding-top: 6px; } .m_menu img{ width:30px; }}" - -/***/ }, -/* 49 */ -/***/ function(module, exports, __webpack_require__) { - - 'use strict'; - - Object.defineProperty(exports, "__esModule", { - value: true - }); - - var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); - - var _omi = __webpack_require__(2); - - var _omi2 = _interopRequireDefault(_omi); - - var _config = __webpack_require__(4); - - var _config2 = _interopRequireDefault(_config); - - var _omiFinger = __webpack_require__(45); - - var _omiFinger2 = _interopRequireDefault(_omiFinger); - - function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - - function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } - - function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; } - - function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } - - _omiFinger2.default.init(); - - var Pager = function (_Omi$Component) { - _inherits(Pager, _Omi$Component); - - function Pager(data) { - _classCallCheck(this, Pager); - - var _this = _possibleConstructorReturn(this, (Pager.__proto__ || Object.getPrototypeOf(Pager)).call(this, data)); - - _this.activeIndex = 0; - _this.currentIndex = 0; - return _this; - } - - _createClass(Pager, [{ - key: 'updatePager', - value: function updatePager() { - this.data.preMd = null; - this.data.preName = null; - this.data.nextMd = null; - this.data.nextName = null; - var item = _config2.default.menus[this.data.lan][this.activeIndex]; - - var pre = item.list[this.currentIndex - 1]; - if (pre) { - this.data.preMd = pre.md; - this.data.preName = pre.name; - } - var next = item.list[this.currentIndex + 1]; - if (next) { - this.data.nextMd = next.md; - this.data.nextName = next.name; - } - } - }, { - key: 'goto', - value: function goto(name, dir) { - var sidebar = _omi2.default.get('sidebar'); - if (dir === 'next') { - sidebar.children[this.activeIndex].goto(name, ++this.currentIndex); - } else { - sidebar.children[this.activeIndex].goto(name, --this.currentIndex); - } - this.update(); - } - }, { - key: 'handleTap', - value: function handleTap(evt) { - var dir = evt.target.getAttribute('data-dir'); - var name = evt.target.getAttribute('data-name'); - this.goto(name, dir); - } - }, { - key: 'isMobile', - value: function isMobile() { - var browser = { - versions: function () { - var u = navigator.userAgent, - app = navigator.appVersion; - return { //移动终端浏览器版本信息 - trident: u.indexOf('Trident') > -1, //IE内核 - presto: u.indexOf('Presto') > -1, //opera内核 - webKit: u.indexOf('AppleWebKit') > -1, //苹果、谷歌内核 - gecko: u.indexOf('Gecko') > -1 && u.indexOf('KHTML') == -1, //火狐内核 - mobile: !!u.match(/AppleWebKit.*Mobile.*/), //是否为移动终端 - ios: !!u.match(/\(i[^;]+;( U;)? CPU.+Mac OS X/), //ios终端 - android: u.indexOf('Android') > -1 || u.indexOf('Linux') > -1, //android终端或者uc浏览器 - iPhone: u.indexOf('iPhone') > -1, //是否为iPhone或者QQHD浏览器 - iPad: u.indexOf('iPad') > -1, //是否iPad - webApp: u.indexOf('Safari') == -1 //是否web应该程序,没有头部与底部 - }; - }(), - language: (navigator.browserLanguage || navigator.language).toLowerCase() - }; - - if (browser.versions.mobile || browser.versions.ios || browser.versions.android || browser.versions.iPhone || browser.versions.iPad) { - return true; - } - return false; - } - }, { - key: 'render', - value: function render() { - this.updatePager(); - if (this.isMobile()) { - return '\n
\n {{#preName}} \u2190{{preName}}{{/preName}}\n {{#nextName}} {{/nextName}}\n
'; - } else { - return '\n
\n {{#preName}} \u2190{{preName}}{{/preName}}\n {{#nextName}} {{/nextName}}\n
'; - } - } - }, { - key: 'style', - value: function style() { - return __webpack_require__(50); - } - }]); - - return Pager; - }(_omi2.default.Component); - - exports.default = Pager; - -/***/ }, -/* 50 */ -/***/ function(module, exports) { - - module.exports = ".pager { width:85%; height:80px; line-height:80px; position: relative; font-size:16px;}@media only screen and (max-width: 768px) { .pager { width:100%; }}.pre{ position: absolute; left:10px; top:10px;}.next{ position: absolute; right:10px; top:10px;}" - -/***/ } -]); \ No newline at end of file diff --git a/website/js/docs-cn.51cfc83d.js b/website/js/docs-cn.d9e1e610.js similarity index 95% rename from website/js/docs-cn.51cfc83d.js rename to website/js/docs-cn.d9e1e610.js index 00b5d27ef..98f5cd70f 100644 --- a/website/js/docs-cn.51cfc83d.js +++ b/website/js/docs-cn.d9e1e610.js @@ -488,7 +488,7 @@ window.Root ={}; Root.isDev = false;webpackJsonp([0],[ /* 21 */ /***/ function(module, exports) { - module.exports = "## Store 体系\r\n\r\n先说说Store系统是干什么的!为什么要造这样一个东西?能够给系统架构带来什么?\r\n\r\n当我们组件之间,拥有共享的数据的时候,经常需要进行组件通讯。在Omi框架里,父组件传递数据给子组件非常方便:\r\n\r\n* 通过在组件上声明 data-* 或者 :data-* 传递给子节点\r\n* 通过在组件上声明 data 或者 :data 传递给子节点 (支持复杂数据类型的映射)\r\n* 声明 group-data 把数组里的data传给一堆组件传递(支持复杂数据类型的映射)\r\n\r\n注:上面带有冒号的是[传递javascript表达式](https://github.com/AlloyTeam/omi/blob/master/tutorial/js-expression.md)\r\n\r\n通过声明onXxx=\"xxxx\"可以让子组件内执行父组件的方法。具体的如下图所示:\r\n\r\n![](http://images2015.cnblogs.com/blog/105416/201703/105416-20170323100946955-1938506287.jpg)\r\n\r\n\r\n如果还不明白的话,那... 我就直接上代码了:\r\n\r\n```js\r\nclass Main extends Omi.Component {\r\n\r\n handlePageChange(index){\r\n this.content.goto(index+1)\r\n this.update()\r\n }\r\n\r\n render () {\r\n return `
\r\n

Pagination Example

\r\n \r\n \r\n
`;\r\n }\r\n}\r\n```\r\n\r\n上面的例子中,\r\n\r\n* 父组件的render方法里,通过 data-✽ 传递数据给子组件 Pagination\r\n* 通过onPageChange=\"handlePageChange\"实现子组件与父组件通讯\r\n\r\n详细代码可以点击: [分页例子地址](https://github.com/AlloyTeam/omi/tree/master/example/pagination)\r\n\r\n当然你也可以使用event emitter / pubsub库在组件之间通讯,比如这个只有 200b 的超小库[mitt](https://github.com/developit/mitt) 。但是需要注意mitt兼容到IE9+,Omi兼容IE8。但是,使用event emitter / pubsub库会对组件代码进行入侵,所以非常不建议在基础非业务组件使用这类代码库。\r\n\r\n虽然组件通讯非常方便,但是在真实的业务场景中,不仅仅是父子、爷孙、爷爷和堂兄、嫂子和堂弟...\r\nonXxx=\"xxxx\"就显得无能为力,力不从心了,各种数据传递、组件实例互操作、 emitter/pubsub或者循环依赖,让代码非常难看且难以维护。所以:\r\n\r\n\tOmi.Store是用来管理共享数据以及共享数据的逻辑 。\r\n\t\r\nOmi Store使用足够简便,对架构入侵性极极极小(3个极代表比极小还要小)。下面一步一步从todo的例子看下Store体系怎么使用。\r\n\t\r\n### 定义 Omi.Store\r\n\r\nOmi.Store是基类,我们可以继承Omi.Store来定义自己的Store,比如下面的TodoStore。\r\n\r\n```js\r\nimport Omi from 'omi'\r\n\r\nclass TodoStore extends Omi.Store {\r\n constructor(data , isReady) {\r\n super(isReady)\r\n\r\n this.data = Object.assign({\r\n items:[],\r\n length:0\r\n },data)\r\n\r\n this.data.length = this.data.items.length\r\n }\r\n\r\n add(value){\r\n this.data.items.push(value)\r\n this.data.length = this.data.items.length\r\n this.update()\r\n }\r\n\r\n clear(){\r\n this.data.items.length = 0\r\n this.data.length = 0\r\n this.update()\r\n }\r\n}\r\n\r\nexport default TodoStore\r\n```\r\n\r\nTodoStore定义了数据的基本格式和数据模型的逻辑。\r\n比如 this.data 就是数据的基本格式:\r\n\r\n```js\r\n{\r\n items:[],\r\n length:0\r\n}\r\n```\r\n\r\nadd和clear就是共享数据相关的逻辑。\r\n\r\n值得注意的是,在add和clear方法里都有调用this.update();这个是用来更新组件的,this.update并不会更新所有组件。但是他到底会更新哪些组件呢?等讲到store的addView方法你就明白了。\r\n\r\n### 创建 Omi.Store\r\n\r\n通过 new 关键字来使用TodoStore对象的实例。\r\n\r\n```js\r\nlet store = new TodoStore({ /* 初始化数据 */ ,/* 数据是否准备好 */ })\r\n```\r\n\r\n上面可以传入一些初始化配置信息,store里面便包含了整个应用程序共享的状态数据以及贡献数据逻辑方法(add,clear)。\r\n\r\n当然,这些初始化配置信息可能是异步拉取的。所以,有两种方法解决异步拉取store配置的问题:\r\n\r\n* 拉取数据,然后new TodoStore(),再Omi.render\r\n* 先let store = new TodoStore(),再Omi.render,组件内部监听store.ready,拉取数据更改store的data信息,然后执行store.beReady()\r\n\r\n\r\n### 根组件注入 store\r\n\r\n为了让组件树能够使用到 store,可以通过Omi.render的第三个参数给根组件注入 store:\r\n\r\n```js\r\nOmi.render(new Todo(),'body',{\r\n store: store\r\n});\r\n```\r\n\r\n当然ES2015已经允许你这样写了:\r\n\r\n```js\r\nOmi.render(new Todo(),'body',{\r\n store\r\n});\r\n```\r\n\r\n两份代码同样的效果。\r\n\r\n通过Omi.render注入之后,在组件树的**所有组件**都可以通过 this.$store 访问到 store。\r\n\r\n### 利用 beforeRender\r\n\r\n为什么要说beforeRender这个函数? 因为通过beforeRender转换store的data到组件的data,这样store的数据和组件的数据就解耦开了。\r\n\r\nbeforeRender是生命周期的一部分。且看下面这张图:\r\n\r\n![beforeRender](http://images2015.cnblogs.com/blog/105416/201703/105416-20170322083548924-1871234168.jpg)\r\n\r\n不管是实例化或者存在期间,在render之前,会去执行beforeRender方法。所以可以利用该方法写store的data到组件data的转换逻辑。比如:\r\n\r\n```js\r\nimport Omi from '../../src/index.js';\r\nimport List from './list.js';\r\n\r\nOmi.makeHTML('List', List);\r\n\r\nclass Todo extends Omi.Component {\r\n constructor(data) {\r\n super(data)\r\n }\r\n\r\n install(){\r\n this.$store.addView(this)\r\n }\r\n\r\n beforeRender(){\r\n this.data.length = this.$store.data.items.length\r\n }\r\n\r\n add (evt) {\r\n evt.preventDefault()\r\n let value = this.data.text\r\n this.data.text = ''\r\n this.$store.add(value)\r\n }\r\n\r\n style () {\r\n return `\r\n h3 { color:red; }\r\n button{ color:green;}\r\n `;\r\n }\r\n\r\n clear(){\r\n this.data.text = ''\r\n this.$store.clear()\r\n }\r\n\r\n handleChange(evt){\r\n this.data.text = evt.target.value\r\n }\r\n\r\n render () {\r\n return `
\r\n

TODO

\r\n \r\n \r\n
\r\n \r\n \r\n
\r\n\r\n
`;\r\n }\r\n}\r\n\r\nexport default Todo;\r\n```\r\n\r\n为什么要去写beforeRender方法?因为render只会使用this.data去渲染页面而不会去使用this.$store.data,所以需要把数据转移到组件的this.data下。这样组件既能使用自身的data,也能使用全局放this.$store.data了,不会耦合在一起。\r\n\r\n注意看上面的:\r\n\r\n```js\r\n install(){\r\n this.$store.addView(this)\r\n }\r\n```\r\n\r\n通过 addView 可以让 store 和 view(也就是组件的实例) 关联起来,以后store执行update方法的时候,关联的view都会自动更新!\r\n\r\n再看上面的子组件声明:\r\n\r\n```js\r\n\r\n```\r\n\r\n这样相当于把this.$store.data传递给了List组件。所以在List内部,就不再需要写beforeRender方法转换了。\r\n\r\n```js\r\nclass List extends Omi.Component {\r\n constructor(data) {\r\n super(data)\r\n }\r\n\r\n render () {\r\n return `
    {{#items}}
  • {{.}}
  • {{/items}}
`\r\n }\r\n}\r\n```\r\n\r\n\t这里需要特别强调,不需要把所有的数据提取到store里,只提取共享数据就好了,组件自身的数据还是放在组件自己进行管理。\r\n\r\n\r\n## 异步数据\r\n\r\n通常,在真实的业务需求中,数据并不是马上能够拿到。所以这里模拟的异步拉取的todo数据:\r\n\r\n```js\r\nlet todoStore = new TodoStore()\r\nsetTimeout(()=>{\r\n todoStore.data.items = [\"omi\",\"store\"];\r\n todoStore.data.length = todoStore.data.items.length\r\n todoStore.beReady();\r\n},2000)\r\n```\r\n\r\n上面的beReady就是代码已经准备就绪,在组件内部可以监听ready方法:\r\n\r\n```js\r\nclass Todo extends Omi.Component {\r\n constructor(data) {\r\n super(data)\r\n }\r\n\r\n install(){\r\n this.$store.addView(this)\r\n }\r\n\r\n installed(){\r\n this.$store.ready(()=>this.$store.update())\r\n }\r\n \r\n add (evt) {\r\n evt.preventDefault()\r\n if(!this.$store.isReady){\r\n return\r\n }\r\n let value = this.data.text\r\n this.data.text = ''\r\n this.$store.add(value)\r\n }\r\n```\r\n\r\n可以看到上面的add方法可以通过this.$store.isReady获取组件store是否准备就绪。\r\n\r\n## 补充(20170323)\r\n\r\n在omi v1.1.0及以后的版本中,已经支持Omi.createStore快捷创建store。如:\r\n\r\n```js\r\nexport default Omi.createStore({\r\n data: {\r\n items: [\"omi\", \"store\"]\r\n },\r\n methods: {\r\n add: function (value) {\r\n this.data.items.push(value)\r\n this.data.length = this.data.items.length\r\n this.update()\r\n },\r\n\r\n clear: function () {\r\n this.data.items.length = 0\r\n this.data.length = 0\r\n this.update()\r\n }\r\n }\r\n});\r\n```\r\n\r\n## 源码地址\r\n\r\n* 更为详细的代码可以[点击这里](https://github.com/AlloyTeam/omi/tree/master/example/todo-store)\r\n* 异步拉取的代码可以[点击这里](https://github.com/AlloyTeam/omi/tree/master/example/todo-store-async)" + module.exports = "## Store 体系\r\n\r\n先说说Store系统是干什么的!为什么要造这样一个东西?能够给系统架构带来什么?\r\n\r\n当我们组件之间,拥有共享的数据的时候,经常需要进行组件通讯。在Omi框架里,父组件传递数据给子组件非常方便:\r\n\r\n* 通过在组件上声明 data-* 或者 :data-* 传递给子节点\r\n* 通过在组件上声明 data 或者 :data 传递给子节点 (支持复杂数据类型的映射)\r\n* 声明 group-data 把数组里的data传给一堆组件传递(支持复杂数据类型的映射)\r\n\r\n注:上面带有冒号的是[传递javascript表达式](https://github.com/AlloyTeam/omi/blob/master/tutorial/js-expression.md)\r\n\r\n通过声明onXxx=\"xxxx\"可以让子组件内执行父组件的方法。具体的如下图所示:\r\n\r\n![](http://images2015.cnblogs.com/blog/105416/201703/105416-20170323100946955-1938506287.jpg)\r\n\r\n\r\n如果还不明白的话,那... 我就直接上代码了:\r\n\r\n```js\r\nclass Main extends Omi.Component {\r\n\r\n handlePageChange(index){\r\n this.content.goto(index+1)\r\n this.update()\r\n }\r\n\r\n render () {\r\n return `
\r\n

Pagination Example

\r\n \r\n \r\n
`;\r\n }\r\n}\r\n```\r\n\r\n上面的例子中,\r\n\r\n* 父组件的render方法里,通过 data-✽ 传递数据给子组件 Pagination\r\n* 通过onPageChange=\"handlePageChange\"实现子组件与父组件通讯\r\n\r\n详细代码可以点击: [分页例子地址](https://github.com/AlloyTeam/omi/tree/master/example/pagination)\r\n\r\n当然你也可以使用event emitter / pubsub库在组件之间通讯,比如这个只有 200b 的超小库[mitt](https://github.com/developit/mitt) 。但是需要注意mitt兼容到IE9+,Omi兼容IE8。但是,使用event emitter / pubsub库会对组件代码进行入侵,所以非常不建议在基础非业务组件使用这类代码库。\r\n\r\n虽然组件通讯非常方便,但是在真实的业务场景中,不仅仅是父子、爷孙、爷爷和堂兄、嫂子和堂弟...\r\nonXxx=\"xxxx\"就显得无能为力,力不从心了,各种数据传递、组件实例互操作、 emitter/pubsub或者循环依赖,让代码非常难看且难以维护。所以:\r\n\r\n\tOmi.Store是用来管理共享数据以及共享数据的逻辑 。\r\n\t\r\nOmi Store使用足够简便,对架构入侵性极极极小(3个极代表比极小还要小)。下面一步一步从todo的例子看下Store体系怎么使用。\r\n\t\r\n### 定义 Omi.Store\r\n\r\nOmi.Store是基类,我们可以继承Omi.Store来定义自己的Store,比如下面的TodoStore。\r\n\r\n```js\r\nimport Omi from 'omi'\r\n\r\nclass TodoStore extends Omi.Store {\r\n constructor(data , isReady) {\r\n super(isReady)\r\n\r\n this.data = Object.assign({\r\n items:[],\r\n length:0\r\n },data)\r\n\r\n this.data.length = this.data.items.length\r\n }\r\n\r\n add(value){\r\n this.data.items.push(value)\r\n this.data.length = this.data.items.length\r\n this.update()\r\n }\r\n\r\n clear(){\r\n this.data.items.length = 0\r\n this.data.length = 0\r\n this.update()\r\n }\r\n}\r\n\r\nexport default TodoStore\r\n```\r\n\r\nTodoStore定义了数据的基本格式和数据模型的逻辑。\r\n比如 this.data 就是数据的基本格式:\r\n\r\n```js\r\n{\r\n items:[],\r\n length:0\r\n}\r\n```\r\n\r\nadd和clear就是共享数据相关的逻辑。\r\n\r\n值得注意的是,在add和clear方法里都有调用this.update();这个是用来更新组件的,this.update并不会更新所有组件。但是他到底会更新哪些组件呢?等讲到store的addView方法你就明白了。\r\n\r\n### 创建 Omi.Store\r\n\r\n通过 new 关键字来使用TodoStore对象的实例。\r\n\r\n```js\r\nlet store = new TodoStore({ /* 初始化数据 */ ,/* 数据是否准备好 */ })\r\n```\r\n\r\n上面可以传入一些初始化配置信息,store里面便包含了整个应用程序共享的状态数据以及贡献数据逻辑方法(add,clear)。\r\n\r\n当然,这些初始化配置信息可能是异步拉取的。所以,有两种方法解决异步拉取store配置的问题:\r\n\r\n* 拉取数据,然后new TodoStore(),再Omi.render\r\n* 先let store = new TodoStore(),再Omi.render,组件内部监听store.ready,拉取数据更改store的data信息,然后执行store.beReady()\r\n\r\n\r\n### 根组件注入 store\r\n\r\n为了让组件树能够使用到 store,可以通过Omi.render的第三个参数给根组件注入 store:\r\n\r\n```js\r\nOmi.render(new Todo(),'body',{\r\n store: store\r\n});\r\n```\r\n\r\n当然ES2015已经允许你这样写了:\r\n\r\n```js\r\nOmi.render(new Todo(),'body',{\r\n store\r\n});\r\n```\r\n\r\n两份代码同样的效果。\r\n\r\n通过Omi.render注入之后,在组件树的**所有组件**都可以通过 this.$store 访问到 store。\r\n\r\n### 利用 beforeRender\r\n\r\n为什么要说beforeRender这个函数? 因为通过beforeRender转换store的data到组件的data,这样store的数据和组件的数据就解耦开了。\r\n\r\nbeforeRender是生命周期的一部分。且看下面这张图:\r\n\r\n![beforeRender](http://images2015.cnblogs.com/blog/105416/201703/105416-20170322083548924-1871234168.jpg)\r\n\r\n不管是实例化或者存在期间,在render之前,会去执行beforeRender方法。所以可以利用该方法写store的data到组件data的转换逻辑。比如:\r\n\r\n```js\r\nimport Omi from '../../src/index.js';\r\nimport List from './list.js';\r\n\r\nOmi.makeHTML('List', List);\r\n\r\nclass Todo extends Omi.Component {\r\n constructor(data) {\r\n super(data)\r\n }\r\n\r\n install(){\r\n this.$store.addView(this)\r\n }\r\n\r\n beforeRender(){\r\n this.data.length = this.$store.data.items.length\r\n }\r\n\r\n add (evt) {\r\n evt.preventDefault()\r\n let value = this.data.text\r\n this.data.text = ''\r\n this.$store.add(value)\r\n }\r\n\r\n style () {\r\n return `\r\n h3 { color:red; }\r\n button{ color:green;}\r\n `;\r\n }\r\n\r\n clear(){\r\n this.data.text = ''\r\n this.$store.clear()\r\n }\r\n\r\n handleChange(evt){\r\n this.data.text = evt.target.value\r\n }\r\n\r\n render () {\r\n return `
\r\n

TODO

\r\n \r\n \r\n
\r\n \r\n \r\n
\r\n\r\n
`;\r\n }\r\n}\r\n\r\nexport default Todo;\r\n```\r\n\r\n为什么要去写beforeRender方法?因为render只会使用this.data去渲染页面而不会去使用this.$store.data,所以需要把数据转移到组件的this.data下。这样组件既能使用自身的data,也能使用全局放this.$store.data了,不会耦合在一起。\r\n\r\n注意看上面的:\r\n\r\n```js\r\n install(){\r\n this.$store.addView(this)\r\n }\r\n```\r\n\r\n通过 addView 可以让 store 和 view(也就是组件的实例) 关联起来,以后store执行update方法的时候,关联的view都会自动更新!\r\n\r\n再看上面的子组件声明:\r\n\r\n```js\r\n\r\n```\r\n\r\n这样相当于把this.$store.data传递给了List组件。所以在List内部,就不再需要写beforeRender方法转换了。\r\n\r\n```js\r\nclass List extends Omi.Component {\r\n constructor(data) {\r\n super(data)\r\n }\r\n\r\n render () {\r\n return `
    {{#items}}
  • {{.}}
  • {{/items}}
`\r\n }\r\n}\r\n```\r\n\r\n\t这里需要特别强调,不需要把所有的数据提取到store里,只提取共享数据就好了,组件自身的数据还是放在组件自己进行管理。\r\n\r\n\r\n## 异步数据\r\n\r\n通常,在真实的业务需求中,数据并不是马上能够拿到。所以这里模拟的异步拉取的todo数据:\r\n\r\n```js\r\nlet todoStore = new TodoStore()\r\nsetTimeout(()=>{\r\n todoStore.data.items = [\"omi\",\"store\"];\r\n todoStore.data.length = todoStore.data.items.length\r\n todoStore.beReady();\r\n},2000)\r\n```\r\n\r\n上面的beReady就是代码已经准备就绪,在组件内部可以监听ready方法:\r\n\r\n```js\r\nclass Todo extends Omi.Component {\r\n constructor(data) {\r\n super(data)\r\n }\r\n\r\n install(){\r\n this.$store.addView(this)\r\n }\r\n\r\n installed(){\r\n this.$store.ready(()=>this.$store.update())\r\n }\r\n \r\n add (evt) {\r\n evt.preventDefault()\r\n if(!this.$store.isReady){\r\n return\r\n }\r\n let value = this.data.text\r\n this.data.text = ''\r\n this.$store.add(value)\r\n }\r\n```\r\n\r\n可以看到上面的add方法可以通过this.$store.isReady获取组件store是否准备就绪。\r\n\r\n## 补充(20170323)\r\n\r\n在omi v1.1.0及以后的版本中,已经支持Omi.createStore快捷创建store。如:\r\n\r\n```js\r\nexport default Omi.createStore({\r\n data: {\r\n items: [\"omi\", \"store\"]\r\n },\r\n methods: {\r\n add: function (value) {\r\n this.data.items.push(value)\r\n this.data.length = this.data.items.length\r\n this.update()\r\n },\r\n\r\n clear: function () {\r\n this.data.items.length = 0\r\n this.data.length = 0\r\n this.update()\r\n }\r\n }\r\n})\r\n```\r\n\r\n## 补充(20170324)\r\n\r\n在omi v1.1.1及以后的版本中,也支持省略Omi.createStore的形式创建store。如:\r\n\r\n```js\r\nexport default {\r\n data: {\r\n items: [\"omi\", \"store\"]\r\n },\r\n methods: {\r\n add: function (value) {\r\n this.data.items.push(value)\r\n this.data.length = this.data.items.length\r\n this.update()\r\n },\r\n\r\n clear: function () {\r\n this.data.items.length = 0\r\n this.data.length = 0\r\n this.update()\r\n }\r\n }\r\n}\r\n```\r\n\r\n## 源码地址\r\n\r\n* 更为详细的代码可以[点击这里](https://github.com/AlloyTeam/omi/tree/master/example/todo-store)\r\n* 异步拉取的代码可以[点击这里](https://github.com/AlloyTeam/omi/tree/master/example/todo-store-async)" /***/ }, /* 22 */ @@ -500,7 +500,7 @@ window.Root ={}; Root.isDev = false;webpackJsonp([0],[ /* 23 */ /***/ function(module, exports) { - module.exports = "## Omi的理念\n\nOmi的理念是基于面向对象编程体系,内建积木系统。\n 传统的单向数据流或者抛出event的组件通讯方式增加了系统的稳定性,但是丧失了灵活性。一定程度上也降低了组件的复用。所谓鱼和熊掌不可兼得。\n 面向对象体系需要多一个逻辑层,可以自由操作所有组件的instance,instance之间的逻辑关系构建出了整个程序。这样组件间的逻辑,通信,复用就全部迎刃而解。组件也更加单一职责,更松耦合。\n\n对比函数式编程、命令式编程与面向对象编程,可以归纳总结出下面几条:\n\n- 命令式编程干脆直接,利用循环条件等控制流程,强调执行过程\n- 命令式编程对硬件执行友好,运行更容易,却阻碍了复杂程序的设计\n- 函数式强调输入和输出,并非执行过程\n- 函数式倡导多个简单执行单元组合成复杂运算程序\n- 面向对象编程将对象作为程序的基本单元,更具有重用性、灵活性和扩展性\n\nJavascript是哪种类型的语言?现在ES6+已经有了class。那么他是面向对象语言?\n但是JS可以在任意地方定义函数并且当作把函数当作值来传递。那么他是函数式编程语言?\n所以,没有精准的定义,取决于你的用法和姿势。其次,Web组件化架构层面编程模型和语言层面编程模型是非常自由的关系。意思就是,你可以用Javascript构建函数式编程框架如React,也可以基于面向对象体系搭建Omi。\n\n### 函数式编程 VS 面向对象编程\n\n在UI组件框架层面,函数式编程的代表有React,Omi属于面向对象编程体系。那么他们各有什么优缺点?下面做了个对比(其实也是函数式编程与面向对象编程的对比):\n\n| | React | Omi |\n| ------------- |:-------------:|:-----:|\n| 组件通信 | ★★★★☆| ★★★★★ |\n| 稳定性 | ★★★★★ | ★★★★☆ |\n| 灵活性 | ★★★★☆| ★★★★★ |\n| 扩展性 | ★★★★☆ | ★★★★★ |\n| 测试性 | ★★★★★ | ★★★★☆ |\n| 文件大小 | ★★★☆☆ | ★★★★★ |\n| 功能特性 | ★★★☆☆ | ★★★★☆ |\n| DOM性能 | ★★★★★ | ★★★★☆ |\n| 动画性能 | ★★★★☆ | ★★★★★ |\n| 抽象复杂度 | ★★★★☆ | ★★★★★ |\n| 异步编程 | ★★★★★ | ★★★★☆ |\n\n可以看得出,鱼和熊掌不可兼得。面向对象编程更具有重用性、灵活性和扩展性,带来的问题就是更加难测试。\n具体来说,如函数式编程,其测试面积是state1 + state2 + ... + stateN;在面向对象编程中,其测试面积是state1×event1 + state2×event2 + ... + stateN×eventN。\n\n总结来说,更加推荐使用面向对象的方式去搭建UI组件化框架。\n\n
\n\n### 全文结束,感谢阅读。[开始Omi之旅吧!](https://github.com/AlloyTeam/omi) \n\n" + module.exports = "## Omi的理念\n\nOmi的理念是基于面向对象编程体系,内建积木系统和Store体系,支持局部dom diff和update(这也是为什么没有使用虚拟dom)。\n\n对比函数式编程、命令式编程与面向对象编程,可以归纳总结出下面几条:\n\n- 命令式编程干脆直接,利用循环条件等控制流程,强调执行过程\n- 命令式编程对硬件执行友好,运行更容易,却阻碍了复杂程序的设计\n- 函数式强调输入和输出,并非执行过程\n- 函数式倡导多个简单执行单元组合成复杂运算程序\n- 面向对象编程将对象作为程序的基本单元,更具有重用性、灵活性和扩展性\n\nJavascript是哪种类型的语言?现在ES6+已经有了class。那么他是面向对象语言?\n但是JS可以在任意地方定义函数并且当作把函数当作值来传递。那么他是函数式编程语言?\n所以,没有精准的定义,取决于你的用法和姿势。其次,Web组件化架构层面编程模型和语言层面编程模型是非常自由的关系。意思就是,你可以用Javascript构建函数式编程框架如React,也可以基于面向对象体系搭建Omi。\n\n### 函数式编程 VS 面向对象编程\n\n在UI组件框架层面,函数式编程的代表有React,Omi属于面向对象编程体系。那么他们各有什么优缺点?下面做了个对比(其实也是函数式编程与面向对象编程的对比):\n\n| | React | Omi |\n| ------------- |:-------------:|:-----:|\n| 组件通信 | ★★★★☆| ★★★★★ |\n| 稳定性 | ★★★★★ | ★★★★☆ |\n| 灵活性 | ★★★★☆| ★★★★★ |\n| 扩展性 | ★★★★☆ | ★★★★★ |\n| 测试性 | ★★★★★ | ★★★★☆ |\n| 文件大小 | ★★★☆☆ | ★★★★★ |\n| 功能特性 | ★★★☆☆ | ★★★★☆ |\n| DOM性能 | ★★★★★ | ★★★★☆ |\n| 动画性能 | ★★★★☆ | ★★★★★ |\n| 抽象复杂度 | ★★★★☆ | ★★★★★ |\n| 异步编程 | ★★★★★ | ★★★★☆ |\n\n总结来说,更加推荐使用面向对象的方式去搭建UI组件化框架。\n\n
\n\n### 全文结束,感谢阅读。[开始Omi之旅吧!](https://github.com/AlloyTeam/omi) \n\n" /***/ }, /* 24 */ @@ -584,7 +584,7 @@ window.Root ={}; Root.isDev = false;webpackJsonp([0],[ /* 37 */ /***/ function(module, exports) { - module.exports = "## Thinking in Omi\r\n\r\nOmi is based on object-oriented programming, with plugin system.\r\n\r\nThe traditional one-way data flow or the event-throwing component communicating can increase the stability of the system, but it loses it's flexibility. To a certain extent also reduced the component reusing.\r\n\r\nObject-oriented system has an other logical layer, which let you control the instance of components. The logic between instances build the entire program.\r\n\r\nThen the issues like communication, reusing and logics between components are all solved.\r\n\r\n\r\nPlus, the component is also more single duty, more loosely coupled.\r\n\r\nFor functional programming, imperative programming and object-oriented programming, we can sum up the following list:\r\n\r\n- Imperative programming is well understood, we use loop and if-else condition to control processes, it emphasize the process of execution\r\n- Imperative programming is hardware friendly, easy to run, but hard to design complex program\r\n- Functional programming is all about input and output, not the process of execution\r\n- Functional programming advocates multiple simple execution units into complex operations\r\n- Object-oriented programming uses objects as the basic unit of the program, with more reusability, flexibility, and extensibility\r\n\r\nWhat kind of language is JavaScript? We have `class` in ES6+, so is JavaScript object-oriented language?\r\n\r\nJavaScript can pass a function as a argumant, so is JavaScript a functional language?\r\n\r\nThere are no right answer, it depands on how you use JavaScript.\r\n\r\nIt's free to chooce, you can use functional programming framework like React, or object-oriented framework like Omi. \r\n\r\n### Functional Programming VS Object-Oriented Programming\r\n\r\nIn the UI component framework scope, functional programming is represented by React, while Omi belongs to object-oriented programming.\r\n\r\nSo what are their strengths and weaknesses? The following is a comparison (in fact, functional programming and object-oriented programming comparison):\r\n\r\n| | React | Omi |\r\n| ------------- |:-------------:|:-----:|\r\n| Component communication | ★★★★☆| ★★★★★ |\r\n| Stability | ★★★★★ | ★★★★☆ |\r\n| Flexibility | ★★★★☆| ★★★★★ |\r\n| Scalability | ★★★★☆ | ★★★★★ |\r\n| Testability | ★★★★★ | ★★★★☆ |\r\n| File size | ★★★☆☆ | ★★★★★ |\r\n| Features | ★★★☆☆ | ★★★★☆ |\r\n| DOM performance | ★★★★★ | ★★★★☆ |\r\n| Animation performance | ★★★★☆ | ★★★★★ |\r\n| Abstract complexity | ★★★★☆ | ★★★★★ |\r\n| Asynchronous programming | ★★★★★ | ★★★★☆ |\r\n\r\nAs we can see, we can not have it both ways. Object-oriented programming is more reusable, flexible and scalable, the problem is more difficult to test.\r\n\r\nSpecifically, if the functional programming, the test area is state1 + state2 + ... + stateN; in object-oriented programming, the test area is state1 × event1 + state2 × event2 + ... + stateN × eventN.\r\n\r\nIn summary, it is more recommended to use the object-oriented programming to build UI component framework.\r\n\r\n
\r\n\r\n### The end. Thanks for reading. [Let's start the Omi journey](https://github.com/AlloyTeam/omi)!\r\n" + module.exports = "## Thinking in Omi\r\n\r\nOmi is based on object-oriented programming, with plugin system and store system, support partial dom diff and update.\r\n\r\nPlus, the component is also more single duty, more loosely coupled.\r\n\r\nFor functional programming, imperative programming and object-oriented programming, we can sum up the following list:\r\n\r\n- Imperative programming is well understood, we use loop and if-else condition to control processes, it emphasize the process of execution\r\n- Imperative programming is hardware friendly, easy to run, but hard to design complex program\r\n- Functional programming is all about input and output, not the process of execution\r\n- Functional programming advocates multiple simple execution units into complex operations\r\n- Object-oriented programming uses objects as the basic unit of the program, with more reusability, flexibility, and extensibility\r\n\r\nWhat kind of language is JavaScript? We have `class` in ES6+, so is JavaScript object-oriented language?\r\n\r\nJavaScript can pass a function as a argumant, so is JavaScript a functional language?\r\n\r\nThere are no right answer, it depands on how you use JavaScript.\r\n\r\nIt's free to chooce, you can use functional programming framework like React, or object-oriented framework like Omi. \r\n\r\n### Functional Programming VS Object-Oriented Programming\r\n\r\nIn the UI component framework scope, functional programming is represented by React, while Omi belongs to object-oriented programming.\r\n\r\nSo what are their strengths and weaknesses? The following is a comparison (in fact, functional programming and object-oriented programming comparison):\r\n\r\n| | React | Omi |\r\n| ------------- |:-------------:|:-----:|\r\n| Component communication | ★★★★☆| ★★★★★ |\r\n| Stability | ★★★★★ | ★★★★☆ |\r\n| Flexibility | ★★★★☆| ★★★★★ |\r\n| Scalability | ★★★★☆ | ★★★★★ |\r\n| Testability | ★★★★★ | ★★★★☆ |\r\n| File size | ★★★☆☆ | ★★★★★ |\r\n| Features | ★★★☆☆ | ★★★★☆ |\r\n| DOM performance | ★★★★★ | ★★★★☆ |\r\n| Animation performance | ★★★★☆ | ★★★★★ |\r\n| Abstract complexity | ★★★★☆ | ★★★★★ |\r\n| Asynchronous programming | ★★★★★ | ★★★★☆ |\r\n\r\nIn summary, it is more recommended to use the object-oriented programming to build UI component framework.\r\n\r\n
\r\n\r\n### The end. Thanks for reading. [Let's start the Omi journey](https://github.com/AlloyTeam/omi)!\r\n" /***/ }, /* 38 */ diff --git a/website/js/docs-en.2c91bed5.js b/website/js/docs-en.6a3d3922.js similarity index 95% rename from website/js/docs-en.2c91bed5.js rename to website/js/docs-en.6a3d3922.js index 1c329198f..0de8b0d4d 100644 --- a/website/js/docs-en.2c91bed5.js +++ b/website/js/docs-en.6a3d3922.js @@ -488,7 +488,7 @@ window.Root ={}; Root.isDev = false;webpackJsonp([1],[ /* 21 */ /***/ function(module, exports) { - module.exports = "## Store 体系\r\n\r\n先说说Store系统是干什么的!为什么要造这样一个东西?能够给系统架构带来什么?\r\n\r\n当我们组件之间,拥有共享的数据的时候,经常需要进行组件通讯。在Omi框架里,父组件传递数据给子组件非常方便:\r\n\r\n* 通过在组件上声明 data-* 或者 :data-* 传递给子节点\r\n* 通过在组件上声明 data 或者 :data 传递给子节点 (支持复杂数据类型的映射)\r\n* 声明 group-data 把数组里的data传给一堆组件传递(支持复杂数据类型的映射)\r\n\r\n注:上面带有冒号的是[传递javascript表达式](https://github.com/AlloyTeam/omi/blob/master/tutorial/js-expression.md)\r\n\r\n通过声明onXxx=\"xxxx\"可以让子组件内执行父组件的方法。具体的如下图所示:\r\n\r\n![](http://images2015.cnblogs.com/blog/105416/201703/105416-20170323100946955-1938506287.jpg)\r\n\r\n\r\n如果还不明白的话,那... 我就直接上代码了:\r\n\r\n```js\r\nclass Main extends Omi.Component {\r\n\r\n handlePageChange(index){\r\n this.content.goto(index+1)\r\n this.update()\r\n }\r\n\r\n render () {\r\n return `
\r\n

Pagination Example

\r\n \r\n \r\n
`;\r\n }\r\n}\r\n```\r\n\r\n上面的例子中,\r\n\r\n* 父组件的render方法里,通过 data-✽ 传递数据给子组件 Pagination\r\n* 通过onPageChange=\"handlePageChange\"实现子组件与父组件通讯\r\n\r\n详细代码可以点击: [分页例子地址](https://github.com/AlloyTeam/omi/tree/master/example/pagination)\r\n\r\n当然你也可以使用event emitter / pubsub库在组件之间通讯,比如这个只有 200b 的超小库[mitt](https://github.com/developit/mitt) 。但是需要注意mitt兼容到IE9+,Omi兼容IE8。但是,使用event emitter / pubsub库会对组件代码进行入侵,所以非常不建议在基础非业务组件使用这类代码库。\r\n\r\n虽然组件通讯非常方便,但是在真实的业务场景中,不仅仅是父子、爷孙、爷爷和堂兄、嫂子和堂弟...\r\nonXxx=\"xxxx\"就显得无能为力,力不从心了,各种数据传递、组件实例互操作、 emitter/pubsub或者循环依赖,让代码非常难看且难以维护。所以:\r\n\r\n\tOmi.Store是用来管理共享数据以及共享数据的逻辑 。\r\n\t\r\nOmi Store使用足够简便,对架构入侵性极极极小(3个极代表比极小还要小)。下面一步一步从todo的例子看下Store体系怎么使用。\r\n\t\r\n### 定义 Omi.Store\r\n\r\nOmi.Store是基类,我们可以继承Omi.Store来定义自己的Store,比如下面的TodoStore。\r\n\r\n```js\r\nimport Omi from 'omi'\r\n\r\nclass TodoStore extends Omi.Store {\r\n constructor(data , isReady) {\r\n super(isReady)\r\n\r\n this.data = Object.assign({\r\n items:[],\r\n length:0\r\n },data)\r\n\r\n this.data.length = this.data.items.length\r\n }\r\n\r\n add(value){\r\n this.data.items.push(value)\r\n this.data.length = this.data.items.length\r\n this.update()\r\n }\r\n\r\n clear(){\r\n this.data.items.length = 0\r\n this.data.length = 0\r\n this.update()\r\n }\r\n}\r\n\r\nexport default TodoStore\r\n```\r\n\r\nTodoStore定义了数据的基本格式和数据模型的逻辑。\r\n比如 this.data 就是数据的基本格式:\r\n\r\n```js\r\n{\r\n items:[],\r\n length:0\r\n}\r\n```\r\n\r\nadd和clear就是共享数据相关的逻辑。\r\n\r\n值得注意的是,在add和clear方法里都有调用this.update();这个是用来更新组件的,this.update并不会更新所有组件。但是他到底会更新哪些组件呢?等讲到store的addView方法你就明白了。\r\n\r\n### 创建 Omi.Store\r\n\r\n通过 new 关键字来使用TodoStore对象的实例。\r\n\r\n```js\r\nlet store = new TodoStore({ /* 初始化数据 */ ,/* 数据是否准备好 */ })\r\n```\r\n\r\n上面可以传入一些初始化配置信息,store里面便包含了整个应用程序共享的状态数据以及贡献数据逻辑方法(add,clear)。\r\n\r\n当然,这些初始化配置信息可能是异步拉取的。所以,有两种方法解决异步拉取store配置的问题:\r\n\r\n* 拉取数据,然后new TodoStore(),再Omi.render\r\n* 先let store = new TodoStore(),再Omi.render,组件内部监听store.ready,拉取数据更改store的data信息,然后执行store.beReady()\r\n\r\n\r\n### 根组件注入 store\r\n\r\n为了让组件树能够使用到 store,可以通过Omi.render的第三个参数给根组件注入 store:\r\n\r\n```js\r\nOmi.render(new Todo(),'body',{\r\n store: store\r\n});\r\n```\r\n\r\n当然ES2015已经允许你这样写了:\r\n\r\n```js\r\nOmi.render(new Todo(),'body',{\r\n store\r\n});\r\n```\r\n\r\n两份代码同样的效果。\r\n\r\n通过Omi.render注入之后,在组件树的**所有组件**都可以通过 this.$store 访问到 store。\r\n\r\n### 利用 beforeRender\r\n\r\n为什么要说beforeRender这个函数? 因为通过beforeRender转换store的data到组件的data,这样store的数据和组件的数据就解耦开了。\r\n\r\nbeforeRender是生命周期的一部分。且看下面这张图:\r\n\r\n![beforeRender](http://images2015.cnblogs.com/blog/105416/201703/105416-20170322083548924-1871234168.jpg)\r\n\r\n不管是实例化或者存在期间,在render之前,会去执行beforeRender方法。所以可以利用该方法写store的data到组件data的转换逻辑。比如:\r\n\r\n```js\r\nimport Omi from '../../src/index.js';\r\nimport List from './list.js';\r\n\r\nOmi.makeHTML('List', List);\r\n\r\nclass Todo extends Omi.Component {\r\n constructor(data) {\r\n super(data)\r\n }\r\n\r\n install(){\r\n this.$store.addView(this)\r\n }\r\n\r\n beforeRender(){\r\n this.data.length = this.$store.data.items.length\r\n }\r\n\r\n add (evt) {\r\n evt.preventDefault()\r\n let value = this.data.text\r\n this.data.text = ''\r\n this.$store.add(value)\r\n }\r\n\r\n style () {\r\n return `\r\n h3 { color:red; }\r\n button{ color:green;}\r\n `;\r\n }\r\n\r\n clear(){\r\n this.data.text = ''\r\n this.$store.clear()\r\n }\r\n\r\n handleChange(evt){\r\n this.data.text = evt.target.value\r\n }\r\n\r\n render () {\r\n return `
\r\n

TODO

\r\n \r\n \r\n
\r\n \r\n \r\n
\r\n\r\n
`;\r\n }\r\n}\r\n\r\nexport default Todo;\r\n```\r\n\r\n为什么要去写beforeRender方法?因为render只会使用this.data去渲染页面而不会去使用this.$store.data,所以需要把数据转移到组件的this.data下。这样组件既能使用自身的data,也能使用全局放this.$store.data了,不会耦合在一起。\r\n\r\n注意看上面的:\r\n\r\n```js\r\n install(){\r\n this.$store.addView(this)\r\n }\r\n```\r\n\r\n通过 addView 可以让 store 和 view(也就是组件的实例) 关联起来,以后store执行update方法的时候,关联的view都会自动更新!\r\n\r\n再看上面的子组件声明:\r\n\r\n```js\r\n\r\n```\r\n\r\n这样相当于把this.$store.data传递给了List组件。所以在List内部,就不再需要写beforeRender方法转换了。\r\n\r\n```js\r\nclass List extends Omi.Component {\r\n constructor(data) {\r\n super(data)\r\n }\r\n\r\n render () {\r\n return `
    {{#items}}
  • {{.}}
  • {{/items}}
`\r\n }\r\n}\r\n```\r\n\r\n\t这里需要特别强调,不需要把所有的数据提取到store里,只提取共享数据就好了,组件自身的数据还是放在组件自己进行管理。\r\n\r\n\r\n## 异步数据\r\n\r\n通常,在真实的业务需求中,数据并不是马上能够拿到。所以这里模拟的异步拉取的todo数据:\r\n\r\n```js\r\nlet todoStore = new TodoStore()\r\nsetTimeout(()=>{\r\n todoStore.data.items = [\"omi\",\"store\"];\r\n todoStore.data.length = todoStore.data.items.length\r\n todoStore.beReady();\r\n},2000)\r\n```\r\n\r\n上面的beReady就是代码已经准备就绪,在组件内部可以监听ready方法:\r\n\r\n```js\r\nclass Todo extends Omi.Component {\r\n constructor(data) {\r\n super(data)\r\n }\r\n\r\n install(){\r\n this.$store.addView(this)\r\n }\r\n\r\n installed(){\r\n this.$store.ready(()=>this.$store.update())\r\n }\r\n \r\n add (evt) {\r\n evt.preventDefault()\r\n if(!this.$store.isReady){\r\n return\r\n }\r\n let value = this.data.text\r\n this.data.text = ''\r\n this.$store.add(value)\r\n }\r\n```\r\n\r\n可以看到上面的add方法可以通过this.$store.isReady获取组件store是否准备就绪。\r\n\r\n## 补充(20170323)\r\n\r\n在omi v1.1.0及以后的版本中,已经支持Omi.createStore快捷创建store。如:\r\n\r\n```js\r\nexport default Omi.createStore({\r\n data: {\r\n items: [\"omi\", \"store\"]\r\n },\r\n methods: {\r\n add: function (value) {\r\n this.data.items.push(value)\r\n this.data.length = this.data.items.length\r\n this.update()\r\n },\r\n\r\n clear: function () {\r\n this.data.items.length = 0\r\n this.data.length = 0\r\n this.update()\r\n }\r\n }\r\n});\r\n```\r\n\r\n## 源码地址\r\n\r\n* 更为详细的代码可以[点击这里](https://github.com/AlloyTeam/omi/tree/master/example/todo-store)\r\n* 异步拉取的代码可以[点击这里](https://github.com/AlloyTeam/omi/tree/master/example/todo-store-async)" + module.exports = "## Store 体系\r\n\r\n先说说Store系统是干什么的!为什么要造这样一个东西?能够给系统架构带来什么?\r\n\r\n当我们组件之间,拥有共享的数据的时候,经常需要进行组件通讯。在Omi框架里,父组件传递数据给子组件非常方便:\r\n\r\n* 通过在组件上声明 data-* 或者 :data-* 传递给子节点\r\n* 通过在组件上声明 data 或者 :data 传递给子节点 (支持复杂数据类型的映射)\r\n* 声明 group-data 把数组里的data传给一堆组件传递(支持复杂数据类型的映射)\r\n\r\n注:上面带有冒号的是[传递javascript表达式](https://github.com/AlloyTeam/omi/blob/master/tutorial/js-expression.md)\r\n\r\n通过声明onXxx=\"xxxx\"可以让子组件内执行父组件的方法。具体的如下图所示:\r\n\r\n![](http://images2015.cnblogs.com/blog/105416/201703/105416-20170323100946955-1938506287.jpg)\r\n\r\n\r\n如果还不明白的话,那... 我就直接上代码了:\r\n\r\n```js\r\nclass Main extends Omi.Component {\r\n\r\n handlePageChange(index){\r\n this.content.goto(index+1)\r\n this.update()\r\n }\r\n\r\n render () {\r\n return `
\r\n

Pagination Example

\r\n \r\n \r\n
`;\r\n }\r\n}\r\n```\r\n\r\n上面的例子中,\r\n\r\n* 父组件的render方法里,通过 data-✽ 传递数据给子组件 Pagination\r\n* 通过onPageChange=\"handlePageChange\"实现子组件与父组件通讯\r\n\r\n详细代码可以点击: [分页例子地址](https://github.com/AlloyTeam/omi/tree/master/example/pagination)\r\n\r\n当然你也可以使用event emitter / pubsub库在组件之间通讯,比如这个只有 200b 的超小库[mitt](https://github.com/developit/mitt) 。但是需要注意mitt兼容到IE9+,Omi兼容IE8。但是,使用event emitter / pubsub库会对组件代码进行入侵,所以非常不建议在基础非业务组件使用这类代码库。\r\n\r\n虽然组件通讯非常方便,但是在真实的业务场景中,不仅仅是父子、爷孙、爷爷和堂兄、嫂子和堂弟...\r\nonXxx=\"xxxx\"就显得无能为力,力不从心了,各种数据传递、组件实例互操作、 emitter/pubsub或者循环依赖,让代码非常难看且难以维护。所以:\r\n\r\n\tOmi.Store是用来管理共享数据以及共享数据的逻辑 。\r\n\t\r\nOmi Store使用足够简便,对架构入侵性极极极小(3个极代表比极小还要小)。下面一步一步从todo的例子看下Store体系怎么使用。\r\n\t\r\n### 定义 Omi.Store\r\n\r\nOmi.Store是基类,我们可以继承Omi.Store来定义自己的Store,比如下面的TodoStore。\r\n\r\n```js\r\nimport Omi from 'omi'\r\n\r\nclass TodoStore extends Omi.Store {\r\n constructor(data , isReady) {\r\n super(isReady)\r\n\r\n this.data = Object.assign({\r\n items:[],\r\n length:0\r\n },data)\r\n\r\n this.data.length = this.data.items.length\r\n }\r\n\r\n add(value){\r\n this.data.items.push(value)\r\n this.data.length = this.data.items.length\r\n this.update()\r\n }\r\n\r\n clear(){\r\n this.data.items.length = 0\r\n this.data.length = 0\r\n this.update()\r\n }\r\n}\r\n\r\nexport default TodoStore\r\n```\r\n\r\nTodoStore定义了数据的基本格式和数据模型的逻辑。\r\n比如 this.data 就是数据的基本格式:\r\n\r\n```js\r\n{\r\n items:[],\r\n length:0\r\n}\r\n```\r\n\r\nadd和clear就是共享数据相关的逻辑。\r\n\r\n值得注意的是,在add和clear方法里都有调用this.update();这个是用来更新组件的,this.update并不会更新所有组件。但是他到底会更新哪些组件呢?等讲到store的addView方法你就明白了。\r\n\r\n### 创建 Omi.Store\r\n\r\n通过 new 关键字来使用TodoStore对象的实例。\r\n\r\n```js\r\nlet store = new TodoStore({ /* 初始化数据 */ ,/* 数据是否准备好 */ })\r\n```\r\n\r\n上面可以传入一些初始化配置信息,store里面便包含了整个应用程序共享的状态数据以及贡献数据逻辑方法(add,clear)。\r\n\r\n当然,这些初始化配置信息可能是异步拉取的。所以,有两种方法解决异步拉取store配置的问题:\r\n\r\n* 拉取数据,然后new TodoStore(),再Omi.render\r\n* 先let store = new TodoStore(),再Omi.render,组件内部监听store.ready,拉取数据更改store的data信息,然后执行store.beReady()\r\n\r\n\r\n### 根组件注入 store\r\n\r\n为了让组件树能够使用到 store,可以通过Omi.render的第三个参数给根组件注入 store:\r\n\r\n```js\r\nOmi.render(new Todo(),'body',{\r\n store: store\r\n});\r\n```\r\n\r\n当然ES2015已经允许你这样写了:\r\n\r\n```js\r\nOmi.render(new Todo(),'body',{\r\n store\r\n});\r\n```\r\n\r\n两份代码同样的效果。\r\n\r\n通过Omi.render注入之后,在组件树的**所有组件**都可以通过 this.$store 访问到 store。\r\n\r\n### 利用 beforeRender\r\n\r\n为什么要说beforeRender这个函数? 因为通过beforeRender转换store的data到组件的data,这样store的数据和组件的数据就解耦开了。\r\n\r\nbeforeRender是生命周期的一部分。且看下面这张图:\r\n\r\n![beforeRender](http://images2015.cnblogs.com/blog/105416/201703/105416-20170322083548924-1871234168.jpg)\r\n\r\n不管是实例化或者存在期间,在render之前,会去执行beforeRender方法。所以可以利用该方法写store的data到组件data的转换逻辑。比如:\r\n\r\n```js\r\nimport Omi from '../../src/index.js';\r\nimport List from './list.js';\r\n\r\nOmi.makeHTML('List', List);\r\n\r\nclass Todo extends Omi.Component {\r\n constructor(data) {\r\n super(data)\r\n }\r\n\r\n install(){\r\n this.$store.addView(this)\r\n }\r\n\r\n beforeRender(){\r\n this.data.length = this.$store.data.items.length\r\n }\r\n\r\n add (evt) {\r\n evt.preventDefault()\r\n let value = this.data.text\r\n this.data.text = ''\r\n this.$store.add(value)\r\n }\r\n\r\n style () {\r\n return `\r\n h3 { color:red; }\r\n button{ color:green;}\r\n `;\r\n }\r\n\r\n clear(){\r\n this.data.text = ''\r\n this.$store.clear()\r\n }\r\n\r\n handleChange(evt){\r\n this.data.text = evt.target.value\r\n }\r\n\r\n render () {\r\n return `
\r\n

TODO

\r\n \r\n \r\n
\r\n \r\n \r\n
\r\n\r\n
`;\r\n }\r\n}\r\n\r\nexport default Todo;\r\n```\r\n\r\n为什么要去写beforeRender方法?因为render只会使用this.data去渲染页面而不会去使用this.$store.data,所以需要把数据转移到组件的this.data下。这样组件既能使用自身的data,也能使用全局放this.$store.data了,不会耦合在一起。\r\n\r\n注意看上面的:\r\n\r\n```js\r\n install(){\r\n this.$store.addView(this)\r\n }\r\n```\r\n\r\n通过 addView 可以让 store 和 view(也就是组件的实例) 关联起来,以后store执行update方法的时候,关联的view都会自动更新!\r\n\r\n再看上面的子组件声明:\r\n\r\n```js\r\n\r\n```\r\n\r\n这样相当于把this.$store.data传递给了List组件。所以在List内部,就不再需要写beforeRender方法转换了。\r\n\r\n```js\r\nclass List extends Omi.Component {\r\n constructor(data) {\r\n super(data)\r\n }\r\n\r\n render () {\r\n return `
    {{#items}}
  • {{.}}
  • {{/items}}
`\r\n }\r\n}\r\n```\r\n\r\n\t这里需要特别强调,不需要把所有的数据提取到store里,只提取共享数据就好了,组件自身的数据还是放在组件自己进行管理。\r\n\r\n\r\n## 异步数据\r\n\r\n通常,在真实的业务需求中,数据并不是马上能够拿到。所以这里模拟的异步拉取的todo数据:\r\n\r\n```js\r\nlet todoStore = new TodoStore()\r\nsetTimeout(()=>{\r\n todoStore.data.items = [\"omi\",\"store\"];\r\n todoStore.data.length = todoStore.data.items.length\r\n todoStore.beReady();\r\n},2000)\r\n```\r\n\r\n上面的beReady就是代码已经准备就绪,在组件内部可以监听ready方法:\r\n\r\n```js\r\nclass Todo extends Omi.Component {\r\n constructor(data) {\r\n super(data)\r\n }\r\n\r\n install(){\r\n this.$store.addView(this)\r\n }\r\n\r\n installed(){\r\n this.$store.ready(()=>this.$store.update())\r\n }\r\n \r\n add (evt) {\r\n evt.preventDefault()\r\n if(!this.$store.isReady){\r\n return\r\n }\r\n let value = this.data.text\r\n this.data.text = ''\r\n this.$store.add(value)\r\n }\r\n```\r\n\r\n可以看到上面的add方法可以通过this.$store.isReady获取组件store是否准备就绪。\r\n\r\n## 补充(20170323)\r\n\r\n在omi v1.1.0及以后的版本中,已经支持Omi.createStore快捷创建store。如:\r\n\r\n```js\r\nexport default Omi.createStore({\r\n data: {\r\n items: [\"omi\", \"store\"]\r\n },\r\n methods: {\r\n add: function (value) {\r\n this.data.items.push(value)\r\n this.data.length = this.data.items.length\r\n this.update()\r\n },\r\n\r\n clear: function () {\r\n this.data.items.length = 0\r\n this.data.length = 0\r\n this.update()\r\n }\r\n }\r\n})\r\n```\r\n\r\n## 补充(20170324)\r\n\r\n在omi v1.1.1及以后的版本中,也支持省略Omi.createStore的形式创建store。如:\r\n\r\n```js\r\nexport default {\r\n data: {\r\n items: [\"omi\", \"store\"]\r\n },\r\n methods: {\r\n add: function (value) {\r\n this.data.items.push(value)\r\n this.data.length = this.data.items.length\r\n this.update()\r\n },\r\n\r\n clear: function () {\r\n this.data.items.length = 0\r\n this.data.length = 0\r\n this.update()\r\n }\r\n }\r\n}\r\n```\r\n\r\n## 源码地址\r\n\r\n* 更为详细的代码可以[点击这里](https://github.com/AlloyTeam/omi/tree/master/example/todo-store)\r\n* 异步拉取的代码可以[点击这里](https://github.com/AlloyTeam/omi/tree/master/example/todo-store-async)" /***/ }, /* 22 */ @@ -500,7 +500,7 @@ window.Root ={}; Root.isDev = false;webpackJsonp([1],[ /* 23 */ /***/ function(module, exports) { - module.exports = "## Omi的理念\n\nOmi的理念是基于面向对象编程体系,内建积木系统。\n 传统的单向数据流或者抛出event的组件通讯方式增加了系统的稳定性,但是丧失了灵活性。一定程度上也降低了组件的复用。所谓鱼和熊掌不可兼得。\n 面向对象体系需要多一个逻辑层,可以自由操作所有组件的instance,instance之间的逻辑关系构建出了整个程序。这样组件间的逻辑,通信,复用就全部迎刃而解。组件也更加单一职责,更松耦合。\n\n对比函数式编程、命令式编程与面向对象编程,可以归纳总结出下面几条:\n\n- 命令式编程干脆直接,利用循环条件等控制流程,强调执行过程\n- 命令式编程对硬件执行友好,运行更容易,却阻碍了复杂程序的设计\n- 函数式强调输入和输出,并非执行过程\n- 函数式倡导多个简单执行单元组合成复杂运算程序\n- 面向对象编程将对象作为程序的基本单元,更具有重用性、灵活性和扩展性\n\nJavascript是哪种类型的语言?现在ES6+已经有了class。那么他是面向对象语言?\n但是JS可以在任意地方定义函数并且当作把函数当作值来传递。那么他是函数式编程语言?\n所以,没有精准的定义,取决于你的用法和姿势。其次,Web组件化架构层面编程模型和语言层面编程模型是非常自由的关系。意思就是,你可以用Javascript构建函数式编程框架如React,也可以基于面向对象体系搭建Omi。\n\n### 函数式编程 VS 面向对象编程\n\n在UI组件框架层面,函数式编程的代表有React,Omi属于面向对象编程体系。那么他们各有什么优缺点?下面做了个对比(其实也是函数式编程与面向对象编程的对比):\n\n| | React | Omi |\n| ------------- |:-------------:|:-----:|\n| 组件通信 | ★★★★☆| ★★★★★ |\n| 稳定性 | ★★★★★ | ★★★★☆ |\n| 灵活性 | ★★★★☆| ★★★★★ |\n| 扩展性 | ★★★★☆ | ★★★★★ |\n| 测试性 | ★★★★★ | ★★★★☆ |\n| 文件大小 | ★★★☆☆ | ★★★★★ |\n| 功能特性 | ★★★☆☆ | ★★★★☆ |\n| DOM性能 | ★★★★★ | ★★★★☆ |\n| 动画性能 | ★★★★☆ | ★★★★★ |\n| 抽象复杂度 | ★★★★☆ | ★★★★★ |\n| 异步编程 | ★★★★★ | ★★★★☆ |\n\n可以看得出,鱼和熊掌不可兼得。面向对象编程更具有重用性、灵活性和扩展性,带来的问题就是更加难测试。\n具体来说,如函数式编程,其测试面积是state1 + state2 + ... + stateN;在面向对象编程中,其测试面积是state1×event1 + state2×event2 + ... + stateN×eventN。\n\n总结来说,更加推荐使用面向对象的方式去搭建UI组件化框架。\n\n
\n\n### 全文结束,感谢阅读。[开始Omi之旅吧!](https://github.com/AlloyTeam/omi) \n\n" + module.exports = "## Omi的理念\n\nOmi的理念是基于面向对象编程体系,内建积木系统和Store体系,支持局部dom diff和update(这也是为什么没有使用虚拟dom)。\n\n对比函数式编程、命令式编程与面向对象编程,可以归纳总结出下面几条:\n\n- 命令式编程干脆直接,利用循环条件等控制流程,强调执行过程\n- 命令式编程对硬件执行友好,运行更容易,却阻碍了复杂程序的设计\n- 函数式强调输入和输出,并非执行过程\n- 函数式倡导多个简单执行单元组合成复杂运算程序\n- 面向对象编程将对象作为程序的基本单元,更具有重用性、灵活性和扩展性\n\nJavascript是哪种类型的语言?现在ES6+已经有了class。那么他是面向对象语言?\n但是JS可以在任意地方定义函数并且当作把函数当作值来传递。那么他是函数式编程语言?\n所以,没有精准的定义,取决于你的用法和姿势。其次,Web组件化架构层面编程模型和语言层面编程模型是非常自由的关系。意思就是,你可以用Javascript构建函数式编程框架如React,也可以基于面向对象体系搭建Omi。\n\n### 函数式编程 VS 面向对象编程\n\n在UI组件框架层面,函数式编程的代表有React,Omi属于面向对象编程体系。那么他们各有什么优缺点?下面做了个对比(其实也是函数式编程与面向对象编程的对比):\n\n| | React | Omi |\n| ------------- |:-------------:|:-----:|\n| 组件通信 | ★★★★☆| ★★★★★ |\n| 稳定性 | ★★★★★ | ★★★★☆ |\n| 灵活性 | ★★★★☆| ★★★★★ |\n| 扩展性 | ★★★★☆ | ★★★★★ |\n| 测试性 | ★★★★★ | ★★★★☆ |\n| 文件大小 | ★★★☆☆ | ★★★★★ |\n| 功能特性 | ★★★☆☆ | ★★★★☆ |\n| DOM性能 | ★★★★★ | ★★★★☆ |\n| 动画性能 | ★★★★☆ | ★★★★★ |\n| 抽象复杂度 | ★★★★☆ | ★★★★★ |\n| 异步编程 | ★★★★★ | ★★★★☆ |\n\n总结来说,更加推荐使用面向对象的方式去搭建UI组件化框架。\n\n
\n\n### 全文结束,感谢阅读。[开始Omi之旅吧!](https://github.com/AlloyTeam/omi) \n\n" /***/ }, /* 24 */ @@ -584,7 +584,7 @@ window.Root ={}; Root.isDev = false;webpackJsonp([1],[ /* 37 */ /***/ function(module, exports) { - module.exports = "## Thinking in Omi\r\n\r\nOmi is based on object-oriented programming, with plugin system.\r\n\r\nThe traditional one-way data flow or the event-throwing component communicating can increase the stability of the system, but it loses it's flexibility. To a certain extent also reduced the component reusing.\r\n\r\nObject-oriented system has an other logical layer, which let you control the instance of components. The logic between instances build the entire program.\r\n\r\nThen the issues like communication, reusing and logics between components are all solved.\r\n\r\n\r\nPlus, the component is also more single duty, more loosely coupled.\r\n\r\nFor functional programming, imperative programming and object-oriented programming, we can sum up the following list:\r\n\r\n- Imperative programming is well understood, we use loop and if-else condition to control processes, it emphasize the process of execution\r\n- Imperative programming is hardware friendly, easy to run, but hard to design complex program\r\n- Functional programming is all about input and output, not the process of execution\r\n- Functional programming advocates multiple simple execution units into complex operations\r\n- Object-oriented programming uses objects as the basic unit of the program, with more reusability, flexibility, and extensibility\r\n\r\nWhat kind of language is JavaScript? We have `class` in ES6+, so is JavaScript object-oriented language?\r\n\r\nJavaScript can pass a function as a argumant, so is JavaScript a functional language?\r\n\r\nThere are no right answer, it depands on how you use JavaScript.\r\n\r\nIt's free to chooce, you can use functional programming framework like React, or object-oriented framework like Omi. \r\n\r\n### Functional Programming VS Object-Oriented Programming\r\n\r\nIn the UI component framework scope, functional programming is represented by React, while Omi belongs to object-oriented programming.\r\n\r\nSo what are their strengths and weaknesses? The following is a comparison (in fact, functional programming and object-oriented programming comparison):\r\n\r\n| | React | Omi |\r\n| ------------- |:-------------:|:-----:|\r\n| Component communication | ★★★★☆| ★★★★★ |\r\n| Stability | ★★★★★ | ★★★★☆ |\r\n| Flexibility | ★★★★☆| ★★★★★ |\r\n| Scalability | ★★★★☆ | ★★★★★ |\r\n| Testability | ★★★★★ | ★★★★☆ |\r\n| File size | ★★★☆☆ | ★★★★★ |\r\n| Features | ★★★☆☆ | ★★★★☆ |\r\n| DOM performance | ★★★★★ | ★★★★☆ |\r\n| Animation performance | ★★★★☆ | ★★★★★ |\r\n| Abstract complexity | ★★★★☆ | ★★★★★ |\r\n| Asynchronous programming | ★★★★★ | ★★★★☆ |\r\n\r\nAs we can see, we can not have it both ways. Object-oriented programming is more reusable, flexible and scalable, the problem is more difficult to test.\r\n\r\nSpecifically, if the functional programming, the test area is state1 + state2 + ... + stateN; in object-oriented programming, the test area is state1 × event1 + state2 × event2 + ... + stateN × eventN.\r\n\r\nIn summary, it is more recommended to use the object-oriented programming to build UI component framework.\r\n\r\n
\r\n\r\n### The end. Thanks for reading. [Let's start the Omi journey](https://github.com/AlloyTeam/omi)!\r\n" + module.exports = "## Thinking in Omi\r\n\r\nOmi is based on object-oriented programming, with plugin system and store system, support partial dom diff and update.\r\n\r\nPlus, the component is also more single duty, more loosely coupled.\r\n\r\nFor functional programming, imperative programming and object-oriented programming, we can sum up the following list:\r\n\r\n- Imperative programming is well understood, we use loop and if-else condition to control processes, it emphasize the process of execution\r\n- Imperative programming is hardware friendly, easy to run, but hard to design complex program\r\n- Functional programming is all about input and output, not the process of execution\r\n- Functional programming advocates multiple simple execution units into complex operations\r\n- Object-oriented programming uses objects as the basic unit of the program, with more reusability, flexibility, and extensibility\r\n\r\nWhat kind of language is JavaScript? We have `class` in ES6+, so is JavaScript object-oriented language?\r\n\r\nJavaScript can pass a function as a argumant, so is JavaScript a functional language?\r\n\r\nThere are no right answer, it depands on how you use JavaScript.\r\n\r\nIt's free to chooce, you can use functional programming framework like React, or object-oriented framework like Omi. \r\n\r\n### Functional Programming VS Object-Oriented Programming\r\n\r\nIn the UI component framework scope, functional programming is represented by React, while Omi belongs to object-oriented programming.\r\n\r\nSo what are their strengths and weaknesses? The following is a comparison (in fact, functional programming and object-oriented programming comparison):\r\n\r\n| | React | Omi |\r\n| ------------- |:-------------:|:-----:|\r\n| Component communication | ★★★★☆| ★★★★★ |\r\n| Stability | ★★★★★ | ★★★★☆ |\r\n| Flexibility | ★★★★☆| ★★★★★ |\r\n| Scalability | ★★★★☆ | ★★★★★ |\r\n| Testability | ★★★★★ | ★★★★☆ |\r\n| File size | ★★★☆☆ | ★★★★★ |\r\n| Features | ★★★☆☆ | ★★★★☆ |\r\n| DOM performance | ★★★★★ | ★★★★☆ |\r\n| Animation performance | ★★★★☆ | ★★★★★ |\r\n| Abstract complexity | ★★★★☆ | ★★★★★ |\r\n| Asynchronous programming | ★★★★★ | ★★★★☆ |\r\n\r\nIn summary, it is more recommended to use the object-oriented programming to build UI component framework.\r\n\r\n
\r\n\r\n### The end. Thanks for reading. [Let's start the Omi journey](https://github.com/AlloyTeam/omi)!\r\n" /***/ }, /* 38 */ diff --git a/website/js/docs-en.78edfa73.js b/website/js/docs-en.78edfa73.js deleted file mode 100644 index d433e97f6..000000000 --- a/website/js/docs-en.78edfa73.js +++ /dev/null @@ -1,1401 +0,0 @@ -window.Root ={}; Root.isDev = false;webpackJsonp([1],[ -/* 0 */ -/***/ function(module, exports, __webpack_require__) { - - 'use strict'; - - var _frame = __webpack_require__(1); - - var _frame2 = _interopRequireDefault(_frame); - - function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - - Omi.render(new _frame2.default({ lan: 'en' }), 'body', true); - -/***/ }, -/* 1 */ -/***/ function(module, exports, __webpack_require__) { - - 'use strict'; - - Object.defineProperty(exports, "__esModule", { - value: true - }); - - var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); - - var _omi = __webpack_require__(2); - - var _omi2 = _interopRequireDefault(_omi); - - var _index = __webpack_require__(3); - - var _index2 = _interopRequireDefault(_index); - - var _index3 = __webpack_require__(38); - - var _index4 = _interopRequireDefault(_index3); - - var _index5 = __webpack_require__(44); - - var _index6 = _interopRequireDefault(_index5); - - var _config = __webpack_require__(4); - - var _config2 = _interopRequireDefault(_config); - - var _index7 = __webpack_require__(49); - - var _index8 = _interopRequireDefault(_index7); - - function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - - function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } - - function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; } - - function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } - - _omi2.default.makeHTML('Content', _index2.default); - _omi2.default.makeHTML('Sidebar', _index4.default); - _omi2.default.makeHTML('Head', _index6.default); - _omi2.default.makeHTML('Pager', _index8.default); - - var Frame = function (_Omi$Component) { - _inherits(Frame, _Omi$Component); - - function Frame(data) { - _classCallCheck(this, Frame); - - return _possibleConstructorReturn(this, (Frame.__proto__ || Object.getPrototypeOf(Frame)).call(this, data)); - } - - _createClass(Frame, [{ - key: 'install', - value: function install() { - var _this2 = this; - - this.setViewport(); - window.onresize = function () { - if (window.innerWidth < 768) { - _this2.refs.main.style.width = '100%'; - } else { - _this2.refs.main.style.width = window.innerWidth - 220 + 'px'; - } - }; - } - }, { - key: 'setViewport', - value: function setViewport() { - if (window.innerWidth < 768) { - this.data.width = '100%'; - } else { - this.data.width = window.innerWidth - 220 + 'px'; - } - } - }, { - key: 'style', - value: function style() { - return '\n \n '; - } - }, { - key: 'render', - value: function render() { - return '
\n \n
\n \n \n
\n \n
'; - } - }]); - - return Frame; - }(_omi2.default.Component); - - exports.default = Frame; - -/***/ }, -/* 2 */, -/* 3 */ -/***/ function(module, exports, __webpack_require__) { - - 'use strict'; - - Object.defineProperty(exports, "__esModule", { - value: true - }); - - var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); - - var _omi = __webpack_require__(2); - - var _omi2 = _interopRequireDefault(_omi); - - var _config = __webpack_require__(4); - - var _config2 = _interopRequireDefault(_config); - - var _highlightLines = __webpack_require__(5); - - var _highlightLines2 = _interopRequireDefault(_highlightLines); - - function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - - function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } - - function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; } - - function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } - - var tpl = __webpack_require__(6); - var css = __webpack_require__(7); - - var Content = function (_Omi$Component) { - _inherits(Content, _Omi$Component); - - function Content(data) { - _classCallCheck(this, Content); - - data = Object.assign({ - lan: 'cn', - name: 'installation' - }, data); - - var _this = _possibleConstructorReturn(this, (Content.__proto__ || Object.getPrototypeOf(Content)).call(this, data)); - - _this.md = new Remarkable({ html: true }); - return _this; - } - - _createClass(Content, [{ - key: 'getMarkDown', - value: function getMarkDown(name, lan) { - return __webpack_require__(8)("./" + lan + "/" + name + ".md"); - } - }, { - key: 'installed', - value: function installed() { - this.initCodeStyle(); - } - }, { - key: 'afterUpdate', - value: function afterUpdate() { - this.initCodeStyle(); - } - }, { - key: 'initCodeStyle', - value: function initCodeStyle() { - var _this2 = this; - - var codes = _omi2.default.$$("code"); - var codeHlNumArr = []; - codes.forEach(function (code) { - hljs.highlightBlock(code); - var arr = code.className.match(/{\S*}/); - var hllNums = null; - if (arr) { - var numArr = arr[0].replace(/[{|}]/g, '').split(','); - hllNums = _this2._arrToNumber(numArr); - } - codeHlNumArr.push(hllNums); - }); - - (0, _highlightLines2.default)(); - - codes.forEach(function (code, index) { - _this2._hll(code, codeHlNumArr[index]); - }); - } - }, { - key: '_arrToNumber', - value: function _arrToNumber(numArr) { - var arr = []; - numArr.forEach(function (item) { - if (item.indexOf('-') !== -1) { - var tempArr = item.split('-'); - var begin = Number(tempArr[0]); - var end = Number(tempArr[1]); - for (var i = begin; i < end + 1; i++) { - arr.push(i); - } - } else { - arr.push(Number(item)); - } - }); - return arr; - } - }, { - key: '_hll', - value: function _hll(code, hllNums) { - var spans = _omi2.default.$$('.line', code); - hllNums && hllNums.forEach(function (num) { - spans[num] && spans[num].classList.add('highlight'); - }); - } - }, { - key: 'render', - value: function render() { - this.data.html = this.md.render(this.getMarkDown(this.data.name, this.data.lan)); - return tpl; - } - }, { - key: 'style', - value: function style() { - return css; - } - }]); - - return Content; - }(_omi2.default.Component); - - exports.default = Content; - -/***/ }, -/* 4 */ -/***/ function(module, exports) { - - 'use strict'; - - Object.defineProperty(exports, "__esModule", { - value: true - }); - var config = { - menus: { - cn: [{ - active: true, - title: '快速开始', - currentIndex: 0, - list: [{ 'name': '安装', md: 'installation' }, { 'name': 'Hello World', md: 'hello_world' }, { 'name': '组件', md: 'components' }, { 'name': '组件通讯', md: 'communication' }, { 'name': '生命周期', md: 'lifecycle' }, { 'name': '事件处理', md: 'events' }, { 'name': '条件判断', md: 'condition' }, { 'name': '循环遍历', md: 'loop' }, { 'name': 'Store体系', md: 'store' }, { 'name': '表单', md: 'form' }, { 'name': '继承', md: 'inherit' }, { 'name': '模板切换', md: 'template' }, { 'name': '获取DOM节点', md: 'get_dom' }, { 'name': '插件体系', md: 'plugin' }, { 'name': 'Omi的理念', md: 'thinking_in_omi' }] - }], - en: [{ - title: 'QUICK START', - active: true, - currentIndex: 0, - list: [{ 'name': 'Installation', md: 'installation' }, { 'name': 'Hello World', md: 'hello_world' }, { 'name': 'Components', md: 'components' }, { 'name': 'Communication', md: 'communication' }, { 'name': 'Lifecycle', md: 'lifecycle' }, { 'name': 'Handling Events', md: 'events' }, { 'name': 'Conditional Rendering', md: 'condition' }, { 'name': 'Loop', md: 'loop' }, { 'name': 'Forms', md: 'form' }, { 'name': 'Inheritance', md: 'inherit' }, { 'name': 'Templates', md: 'template' }, { 'name': 'Get DOM', md: 'get_dom' }, { 'name': 'Plugin', md: 'plugin' }, { 'name': 'Thinking in Omi', md: 'thinking_in_omi' }] - }] - } - }; - - exports.default = config; - -/***/ }, -/* 5 */ -/***/ function(module, exports) { - - 'use strict'; - - Object.defineProperty(exports, "__esModule", { - value: true - }); - - // Iterates through `array`, running `callback` for each `array` element. - function forEach(array, callback) { - var i = -1, - length = array ? array.length : 0; - while (++i < length) { - callback(array[i]); - } - } - - function indexOf(array, elem) { - var i = -1, - length = array ? array.length : 0; - while (++i < length) { - if (array[i] === elem) { - return i; - } - } - } - function highlightLines() { - // TODO: mark as parsed. - forEach(document.querySelectorAll('pre code'), function (element) { - // Trim whitespace if the `data-trim` attribute is present. - if (element.hasAttribute('data-trim') && typeof element.innerHTML.trim == 'function') { - element.innerHTML = element.innerHTML.trim(); - } - - // Highlight code using highlight.js. - hljs.highlightBlock(element); - - // Split highlighted code into lines. - var openTags = [], - reHtmlTag = /<(\/?)span(?:\s+(?:class=(['"])hljs-.*?\2)?\s*|\s*)>/g; - element.innerHTML = element.innerHTML.replace(/(.*?)\r?\n/g, function (_, string) { - if (!string) { - return ' '; - } - var openTag, stringPrepend; - // Re-open all tags that were previously closed. - if (openTags.length) { - stringPrepend = openTags.join(''); - } - // Match all HTML `` tags. - reHtmlTag.lastIndex = 0; - while (openTag = reHtmlTag.exec(string)) { - // If it is a closing tag, remove the opening tag from the list. - if (openTag[1]) { - openTags.pop(); - } - // Otherwise if it is an opening tag, push it to the list. - else { - openTags.push(openTag[0]); - } - } - // Close all opened tags, so that strings can be wrapped with `span.line`. - if (openTags.length) { - string += Array(openTags.length + 1).join(''); - } - if (stringPrepend) { - string = stringPrepend + string; - } - return '' + string + ''; - }); - }); - } - - exports.default = highlightLines; - -/***/ }, -/* 6 */ -/***/ function(module, exports) { - - module.exports = "
{{{html}}}
" - -/***/ }, -/* 7 */ -/***/ function(module, exports) { - - module.exports = ".content{ width: 80%;}h3{ color:#444444;}pre{ border: 1px solid #eee; width: 100%;}li{ text-indent: 20px; list-style:disc inside ;}@media only screen and (max-width: 768px) { .content{ width: 100%; }}" - -/***/ }, -/* 8 */ -/***/ function(module, exports, __webpack_require__) { - - var map = { - "./cn/communication.md": 9, - "./cn/components.md": 10, - "./cn/condition.md": 11, - "./cn/events.md": 12, - "./cn/form.md": 13, - "./cn/get_dom.md": 14, - "./cn/hello_world.md": 15, - "./cn/inherit.md": 16, - "./cn/installation.md": 17, - "./cn/lifecycle.md": 18, - "./cn/loop.md": 19, - "./cn/plugin.md": 20, - "./cn/store.md": 21, - "./cn/template.md": 22, - "./cn/thinking_in_omi.md": 23, - "./en/communication.md": 24, - "./en/components.md": 25, - "./en/condition.md": 26, - "./en/events.md": 27, - "./en/form.md": 28, - "./en/get_dom.md": 29, - "./en/hello_world.md": 30, - "./en/inherit.md": 31, - "./en/installation.md": 32, - "./en/lifecycle.md": 33, - "./en/loop.md": 34, - "./en/plugin.md": 35, - "./en/template.md": 36, - "./en/thinking_in_omi.md": 37 - }; - function webpackContext(req) { - return __webpack_require__(webpackContextResolve(req)); - }; - function webpackContextResolve(req) { - return map[req] || (function() { throw new Error("Cannot find module '" + req + "'.") }()); - }; - webpackContext.keys = function webpackContextKeys() { - return Object.keys(map); - }; - webpackContext.resolve = webpackContextResolve; - module.exports = webpackContext; - webpackContext.id = 8; - - -/***/ }, -/* 9 */ -/***/ function(module, exports) { - - module.exports = "## 组件通讯\r\n\r\n[Omi框架](https://github.com/AlloyTeam/omi)组建间的通讯非常遍历灵活,因为有许多可选方案进行通讯:\r\n\r\n* 通过在组件上声明 data-* 传递给子节点 \r\n* 通过在组件上声明 data 传递给子节点 (支持复杂数据类型的映射)\r\n* 声明 group-data 传递(支持复杂数据类型的映射)\r\n* 完全面向对象,可以非常容易地拿到对象的实例,之后可以设置实例属性和调用实例的方法\r\n\r\n所以通讯变得畅通无阻,下面一一来举例说明。\r\n\r\n### data-*通讯 \r\n\r\n```js {36}\r\nclass Hello extends Omi.Component {\r\n constructor(data) {\r\n super(data);\r\n }\r\n \r\n style () {\r\n return `\r\n h1{\r\n \tcursor:pointer;\r\n }\r\n `;\r\n }\r\n \r\n handleClick(target, evt){\r\n alert(target.innerHTML);\r\n }\r\n \r\n render() {\r\n return `\r\n
\r\n \t

Hello ,{{name}}!

\r\n
\r\n \t\t`;\r\n }\r\n}\r\n\r\nOmi.makeHTML('Hello', Hello);\r\n\r\nclass App extends Omi.Component {\r\n constructor(data) {\r\n super(data);\r\n }\r\n \r\n render() {\r\n return `\r\n
\r\n \r\n
\r\n `;\r\n }\r\n}\r\n\r\nOmi.render(new App(),\"#container\");\r\n```\r\n\r\n一般data-*用来传递值类型,如string、number。值得注意的是,通过data-*接收到的数据类型都是string,需要自行转成number类型。\r\n通常情况下,data-*能满足我们的要求,但是遇到复杂的数据类型是没有办法通过大量data-*去表达,所以可以通过data通讯,请往下看。\r\n\r\n### data通讯 \r\n\r\n如上面代码所示,通过 data-name=\"Omi\"可以把name传递给子组件。下面的代码也可以达到同样的效果。\r\n\r\n```js {4,10}\r\n...\r\nclass App extends Omi.Component {\r\n constructor(data) {\r\n super(data);\r\n this.helloData = { name : 'Omi' };\r\n }\r\n \r\n render() {\r\n return `\r\n
\r\n \r\n
\r\n `;\r\n }\r\n}\r\n\r\nOmi.render(new App(),\"#container\");\r\n```\r\n\r\n使用data声明,会去组件的instance(也就是this)下找对应的属性,this下可以挂载任意复杂的对象。所以这也就突破了data-*的局限性。\r\n\r\n如果instance下面的某个属性下面的某个属性下面的某个数组的第一个元素的某个属性要作为data传递Hello怎么办?\r\n没关系,data声明是支持复杂类型的,使用方式如下:\r\n\r\n```js\r\n...\r\nclass App extends Omi.Component {\r\n constructor(data) {\r\n super(data);\r\n this.complexData ={\r\n a:{\r\n b:{\r\n c:[\r\n {\r\n e:[{\r\n name:'ComplexData Support1'\r\n },{\r\n name:'ComplexData Support2'\r\n }]\r\n },\r\n {\r\n name: 'ComplexData Support3'\r\n }\r\n ]\r\n }\r\n }\r\n };\r\n }\r\n \r\n render() {\r\n return `\r\n
\r\n \r\n
\r\n `;\r\n }\r\n}\r\n...\r\n```\r\n\r\n点击这里→data映射复杂数据\r\n\r\n### group-data通讯\r\n\r\ngroup-data专门是为了给一组组件批量传递data而设计。\r\n\r\n```js\r\nimport Hello from './hello.js';\r\n\r\n\r\nOmi.makeHTML('Hello', Hello);\r\n\r\nclass App extends Omi.Component {\r\n constructor(data) {\r\n super(data);\r\n this.testData = [{name: 'Omi'}, {name: 'dntzhang'}, {name: 'AlloyTeam'}];\r\n }\r\n\r\n render() {\r\n return `\r\n
\r\n \r\n \r\n \r\n
\r\n `;\r\n\r\n }\r\n}\r\n\r\nOmi.render(new App(),\"#container\");\r\n```\r\n\r\n只需要在声明的子组件上标记group-data,就会去当前组件的instance(也就是this)下面找对应的属性,然后根据当前的位置,和对应数组的位置会一一对应起来。\r\n\r\n运行结果如下:\r\n![](http://images2015.cnblogs.com/blog/105416/201702/105416-20170216110701535-1698390390.png)\r\n\r\n点击这里→group-data\r\n\r\n同样group-data支持复杂数据类型的映射,需要注意的是,group-data映射的终点必须是一个数组:\r\n\r\n```js\r\nimport Hello from './hello.js';\r\n\r\n\r\nOmi.makeHTML('Hello', Hello);\r\n\r\nclass App extends Omi.Component {\r\n constructor(data) {\r\n super(data);\r\n this.complexData ={\r\n a:{\r\n b:{\r\n c:[\r\n {\r\n e:[{\r\n name:'ComplexData Support1'\r\n },{\r\n name:'ComplexData Support2'\r\n }]\r\n },\r\n {\r\n name: 'ComplexData Support3'\r\n }\r\n ]\r\n }\r\n }\r\n };\r\n }\r\n\r\n render() {\r\n return `\r\n
\r\n \r\n \r\n
\r\n `;\r\n\r\n }\r\n}\r\n\r\nOmi.render(new App(),\"#container\");\r\n```\r\n\r\n点击这里→group-data映射复杂数据\r\n\r\n### 通过对象实例\r\n\r\n```js {7}\r\n...\r\nclass App extends Omi.Component {\r\n constructor(data) {\r\n super(data);\r\n }\r\n \r\n installed(){\r\n this.hello.data.name = \"Omi\";\r\n this.update()\r\n }\r\n \r\n render() {\r\n return `\r\n
\r\n \r\n
\r\n `;\r\n }\r\n}\r\n\r\nOmi.render(new App(),\"#container\");\r\n```\r\n\r\n### 通过omi-id\r\n\r\n```js {7,14}\r\n...\r\nclass App extends Omi.Component {\r\n constructor(data) {\r\n super(data);\r\n }\r\n \r\n installed(){\r\n Omi.get(\"hello\").data.name = \"Omi\";\r\n this.update()\r\n }\r\n \r\n render() {\r\n return `\r\n
\r\n \r\n
\r\n `;\r\n }\r\n}\r\n\r\nOmi.render(new App(),\"#container\");\r\n```\r\n\r\n通过在组件上声明omi-id,在程序任何地方拿到该对象的实例。这个可以算是跨任意组件通讯神器。\r\n\r\n" - -/***/ }, -/* 10 */ -/***/ function(module, exports) { - - module.exports = "## 组件\r\n\r\n[Omi框架](https://github.com/AlloyTeam/omi)完全基于组件体系设计,我们希望开发者可以像搭积木一样制作Web程序,一切皆是组件,组件也可以嵌套子组件形成新的组件,新的组件又可以当作子组件嵌套至任意组件形成新的组件...\r\n\r\n![](http://images2015.cnblogs.com/blog/105416/201702/105416-20170210093427338-1536910080.png)\r\n\r\n## 简单组件\r\n\r\n这里使用Todo的例子来讲解Omi组件体系的使用。\r\n\r\n```js\r\nclass Todo extends Omi.Component {\r\n constructor(data) {\r\n super(data);\r\n }\r\n \r\n add (evt) {\r\n evt.preventDefault();\r\n this.data.items.push(this.data.text);\r\n this.data.text = '';\r\n this.update();\r\n }\r\n\r\n style () {\r\n return `\r\n h3 { color:red; }\r\n button{ color:green;}\r\n `;\r\n }\r\n\r\n handleChange(target){\r\n this.data.text = target.value;\r\n }\r\n\r\n render () {\r\n return `
\r\n

TODO

\r\n
    {{#items}}
  • {{.}}
  • {{/items}}
\r\n
\r\n \r\n \r\n
\r\n
`;\r\n }\r\n}\r\n\r\nOmi.render(new Todo({ items: [] ,text : '' }),\"body\");\r\n```\r\n\r\n组件生成的HTML最终会插入到body中。上面的例子展示了Omi的部分特性:\r\n\r\n- data传递: new Todo(data,..)的data可以直接提供给render方法里的模板\r\n- 局部CSS: h3只对render里的h3生效,不会污染外面的h3;button也是同样的\r\n- 声明式事件绑定: onchange调用的就是组件内的handleChange,this可以拿到当然的DOM元素,还可以拿到当前的event\r\n- 需要手动调用update方法才能更新组件\r\n\r\n这里需要特别强调的是,为了更加的自由和灵活度。Omi没有内置数据变更的自动更新,需要开发者自己调用update方法。\r\n\r\n点击这里→在线试试\r\n\r\n## 组件嵌套\r\n\r\n如果页面超级简单的话,可以没有组件嵌套。但是绝大部分Web网页或者Web应用,需要嵌套定义的组件来完成所有的功能和展示。比如上面的Todo,我们也是可以抽取出List。\r\n这样让程序易维护、可扩展、方便复用。如,我们抽取出List:\r\n\r\n```js\r\nclass List extends Omi.Component {\r\n constructor(data) {\r\n super(data);\r\n }\r\n\r\n render () {\r\n return `
    {{#items}}
  • {{.}}
  • {{/items}}
`;\r\n }\r\n}\r\n```\r\n\r\n怎么使用这个List?我们需要使用Omi.makeHTML把List制作成可以声明式的标签,在render方法中就能直接使用该标签。如下所示:\r\n\r\n```js\r\nimport List from './list.js';\r\n\r\nOmi.makeHTML('List', List);\r\n\r\nclass Todo extends Omi.Component {\r\n constructor(data) {\r\n super(data);\r\n this.data.length = this.data.items.length;\r\n this.listData = { items : this.data.items };\r\n }\r\n\r\n add (evt) {\r\n evt.preventDefault();\r\n this.list.data.items.push(this.data.text);\r\n this.data.length = this.list.data.items.length;\r\n this.data.text = '';\r\n this.update();\r\n }\r\n\r\n style () {\r\n return `\r\n h3 { color:red; }\r\n button{ color:green;}\r\n `;\r\n }\r\n\r\n handleChange(target){\r\n this.data.text = target.value;\r\n }\r\n\r\n render () {\r\n return `
\r\n

TODO

\r\n \r\n
\r\n \r\n \r\n
\r\n
`;\r\n }\r\n}\r\n```\r\n\r\n* 第3行,通过makeHTML方法把组件制作成可以在render中使用的标签。当然Omi.makeHTML('List', List);也可以写在List组件的代码下面。\r\n* 第9行,在父组件上定义listData属性用来传递给子组件。\r\n* 第34行,在render方法中使用List组件。其中name方法可以让你在代码里通过this快速方法到该组件的实例。data=\"listData\"可以让你把this.listData传递给子组件。\r\n\r\n需要注意的是,父组件的this.listData会被通过Object.assign浅拷贝到子组件。\r\n这样做的目的主要是希望以后DOM的变更都尽量修改子组件自身的data,然后再调用其update方法,而不是去更改父组件的listData。\r\n\r\n关于Omi组件通讯其实有4种方案,这个后续教程会专门来讲。\r\n\r\n点击这里→在线试试\r\n" - -/***/ }, -/* 11 */ -/***/ function(module, exports) { - - module.exports = "## 条件判断\r\n\r\n我们经常需要根据不同的状态呈现不同的界面,比如有的用户是vip要显示vip的Logo。Omi有许多种方式满足你的要求。\r\n\r\n### 方式一\r\n\r\n```js\r\nclass ConditionTest extends Omi.Component {\r\n constructor(data) {\r\n super(data);\r\n }\r\n\r\n render () {\r\n return `{{#isVip}}\r\n
you are VIP.
\r\n {{/isVip}}\r\n {{^isVip}}\r\n
you are not VIP.
\r\n {{/isVip}}`;\r\n }\r\n}\r\n```\r\n\r\n上面完全使用mustachejs的条件判断的语法。当然Omi不强制你使用mustachejs。你可以是omi.lite.js,然后重写Omi.template方法去使用任意你喜爱的模板引擎。\r\n\r\n### 方式二\r\n\r\n```js\r\nclass ConditionTest extends Omi.Component {\r\n constructor(data) {\r\n super(data);\r\n }\r\n\r\n render () {\r\n if(this.data.isVip){\r\n return '
you are VIP.
';\r\n }else{\r\n return '
you are not VIP.
';\r\n }\r\n }\r\n}\r\n```\r\n\r\nrender就是提供了很好的可编程性,里面可以写任意js逻辑代码。对了,差点忘了,style方法里面也可以写js逻辑的。\r\n\r\n```js\r\nclass ConditionTest extends Omi.Component {\r\n constructor(data) {\r\n super(data);\r\n }\r\n\r\n style (){\r\n if(this.data.isVip){\r\n return 'div{ color : red; }';\r\n }else{\r\n return 'div{ color : green; }';\r\n }\r\n }\r\n\r\n render () {\r\n if(this.data.isVip){\r\n return '
you are VIP.
';\r\n }else{\r\n return '
you are not VIP.
';\r\n }\r\n }\r\n}\r\n```\r\n\r\n### 方式三\r\n\r\n```js\r\nclass ConditionTest extends Omi.Component {\r\n constructor(data) {\r\n super(data);\r\n }\r\n\r\n render() {\r\n return `\r\n ${this.data.isVip\r\n ?\"
you are VIP.
\"\r\n :\"
you are not VIP.
\"\r\n \t\t}\r\n `;\r\n }\r\n}\r\n```\r\n\r\n当然可以使用${ }里面写javascript代码进行输出。" - -/***/ }, -/* 12 */ -/***/ function(module, exports) { - - module.exports = "## 事件处理\r\n\r\nOmi的事件分内置事件和自定义事件。在内置事件处理方面巧妙地利用了浏览器自身的管线机制,可以通过event和this轻松拿到事件实例和触发该事件的元素。\r\n\r\n### 内置事件\r\n\r\n什么算内置事件?只要下面正则能匹配到就算内置事件。\r\n\r\n```js\r\non(abort|blur|cancel|canplay|canplaythrough|change|click|close|contextmenu|cuechange|dblclick|drag|dragend|dragenter|dragleave|dragover|dragstart|drop|durationchange|emptied|ended|error|focus|input|invalid|keydown|keypress|keyup|load|loadeddata|loadedmetadata|loadstart|mousedown|mouseenter|mouseleave|mousemove|mouseout|mouseover|mouseup|mousewheel|pause|play|playing|progress|ratechange|reset|resize|scroll|seeked|seeking|select|show|stalled|submit|suspend|timeupdate|toggle|volumechange|waiting|autocomplete|autocompleteerror|beforecopy|beforecut|beforepaste|copy|cut|paste|search|selectstart|wheel|webkitfullscreenchange|webkitfullscreenerror|touchstart|touchmove|touchend|touchcancel|pointerdown|pointerup|pointercancel|pointermove|pointerover|pointerout|pointerenter|pointerleave)\r\n```\r\n\r\n内置事件怎么绑定?如下所示:\r\n\r\n```js\r\nclass EventTest extends Omi.Component {\r\n constructor(data) {\r\n super(data);\r\n }\r\n\r\n handleClick(dom, evt){\r\n alert(dom.innerHTML);\r\n }\r\n\r\n render () {\r\n return `
Hello, Omi!
`;\r\n }\r\n}\r\n```\r\n\r\n### 自定义事件\r\n\r\n开发者自己定义的组件的事件,称为自定义事件,自定义事件必须以on开头,即onXXXX的格式,不然Omi识别不到。这里拿分页作为例子:\r\n\r\n```js\r\nimport Omi from '../../src/index.js';\r\nimport Pagination from './pagination.js';\r\nimport Content from './content.js';\r\n\r\nOmi.makeHTML('Pagination', Pagination);\r\nOmi.makeHTML('Content', Content);\r\n\r\nclass Main extends Omi.Component {\r\n constructor(data) {\r\n super(data);\r\n }\r\n\r\n installed(){\r\n this.content.goto(this.pagination.data.currentPage+1);\r\n }\r\n \r\n handlePageChange(index){\r\n this.content.goto(index+1);\r\n }\r\n\r\n render () {\r\n return `
\r\n

Pagination Example

\r\n \r\n \r\n
`;\r\n }\r\n}\r\n\r\nOmi.render( new Main(),'body');\r\n```\r\n\r\n如上面的onPageChange就是自定义事件,触发会执行handlePageChange。onPageChange方法是在Pagination中执行:\r\n\r\n```js\r\nimport Omi from '../../src/index.js';\r\n\r\nclass Pagination extends Omi.Component {\r\n ...\r\n ...\r\n ...\r\n linkTo: \"#\",\r\n prevText: \"Prev\",\r\n nextText: \"Next\",\r\n ellipseText: \"...\",\r\n prevShow: true,\r\n nextShow: true,\r\n onPageChange: function () { return false; }\r\n }, this.data);\r\n\r\n this.pageNum = Math.ceil(this.data.total / this.data.pageSize);\r\n }\r\n \r\n goto (index,evt) {\r\n evt.preventDefault();\r\n this.data.currentPage=index;\r\n this.update();\r\n this.data.onPageChange(index);\r\n }\r\n ...\r\n ...\r\n ...\r\n}\r\n```\r\n\r\n这里取了Pagination组件的部分代码。高亮的就是执行onPageChange的地方。\r\n\r\n### 相关地址\r\n\r\n* [演示地址](http://alloyteam.github.io/omi/example/pagination/)\r\n* [源码地址](https://github.com/AlloyTeam/omi/tree/master/example/pagination)\r\n" - -/***/ }, -/* 13 */ -/***/ function(module, exports) { - - module.exports = "## 表单\r\n\r\nOmi让一些表单操控起来更加方便,特别是select!\r\n\r\n### select标签\r\n\r\n以前,我们需要像如下的方式选中一个选项:\r\n\r\n```html\r\n\r\n```\r\n\r\n第三个option由于加上了selected,所有会被选中。这样带来的问题就是,开发者写的程序可能要操遍历每个option。而使用Omi,你只需要这样子:\r\n\r\n```html\r\n\r\n```\r\n\r\n这样就能达到同样的效果。比如你想选择第一项:\r\n\r\n```html\r\n\r\n```\r\n\r\n是不是非常方便?\r\n\r\n### 举个例子\r\n\r\n```js\r\nclass FormTest extends Omi.Component {\r\n constructor(data) {\r\n super(data);\r\n \r\n }\r\n\r\n handleChange(target){\r\n console.log(target.value)\r\n this.data.value = target.value;\r\n }\r\n\r\n handleSubmit(evt) {\r\n alert('Your favorite flavor is: ' + this.data.value);\r\n evt.preventDefault();\r\n }\r\n \r\n render () {\r\n return `\r\n
\r\n \r\n \r\n
`;\r\n }\r\n}\r\n\r\nOmi.render(new FormTest({ value: 'mango' }),'#container');\r\n```\r\n\r\n点击这里→在线试试" - -/***/ }, -/* 14 */ -/***/ function(module, exports) { - - module.exports = "## 获取DOM节点\r\n\r\n虽然绝大部分情况下,开发者不需要去查找获取DOM,但是还是有需要获取DOM的场景,所以Omi提供了方便获取DOM节点的方式。\r\n\r\n### ref和refs\r\n\r\n```js\r\nclass Hello extends Omi.Component {\r\n constructor(data) {\r\n super(data);\r\n }\r\n \r\n style () {\r\n return `\r\n h1{\r\n cursor:pointer;\r\n }\r\n `;\r\n }\r\n \r\n handleClick(){\r\n alert(this.refs.abc.innerHTML);\r\n }\r\n \r\n render() {\r\n return `\r\n
\r\n

Hello ,{{name}}!

\r\n
\r\n `;\r\n }\r\n}\r\n\r\nOmi.render(new Hello({ name : \"Omi\" }),\"#container\");\r\n```\r\n\r\n可以看到通过在HTML中标记ref为abc,那么就通过this.refs.abc访问到该DOM节点。\r\n\r\n点击这里→在线试试" - -/***/ }, -/* 15 */ -/***/ function(module, exports) { - - module.exports = "## Hello World\r\n\r\n你可以使用ES6+或者ES5的方式编写Omi程序来搭建你的Web程序。\r\n\r\n### Hello World with ES6+\r\n\r\n你可以使用 [webpack](https://webpack.github.io/) 打包工具,webpack会把你的模块代码打成一个很小的包,优化加载时间。使用[babel](http://babeljs.io/),让你立刻马上使用ES6+来编写你的web程序。你只需要在webpack配置的module设置好[babel-loader](https://github.com/babel/babel-loader)便可。\r\n\r\n一个Omi的简短的例子如下所示:\r\n\r\n```js\r\nimport Omi from './omi.js';\r\n\r\nclass Hello extends Omi.Component {\r\n constructor(data) {\r\n super(data);\r\n }\r\n \r\n style () {\r\n //注意,return中的包裹是可选的。主要是为了识别为JSX文件可以有CSS高亮。\r\n return `\r\n \r\n `;\r\n }\r\n \r\n handleClick(target, evt){\r\n alert(target.innerHTML);\r\n }\r\n \r\n render() {\r\n return `\r\n
\r\n

Hello ,{{name}}!

\r\n
\r\n `;\r\n }\r\n}\r\n\r\nOmi.render(new Hello({ name : \"Omi\" }),\"#container\");\r\n```\r\n\r\n组件生成的HTML最终会插入到#container中。上面的例子展示了Omi的部分特性:\r\n\r\n- data传递: new Hello(data,..)的data可以直接提供给render方法里的模板\r\n- 局部CSS: h1只对render里的h1生效,不会污染外面的h1\r\n- 声明式事件绑定: onclick调用的就是组件内的handleClick,this可以拿到当前的DOM元素,还可以拿到当前的event\r\n\r\n点击这里→在线试试\r\n\r\n你可以使用Omi.makeHTML来生成组件标签用于嵌套。\r\n```js\r\n Omi.makeHTML('Hello', Hello);\r\n```\r\n那么你就在其他组件中使用,如\r\n```js\r\n ...\r\n render() {\r\n return `\r\n
\r\n
Test
\r\n \r\n
\r\n `;\r\n }\r\n ...\r\n```\r\n\r\n点击这里→在线试试\r\n\r\n### Hello World with ES5\r\n\r\n当然Omi没有抛弃ES5的用户。你可以使用ES5的方式编写Omi。如,在你的HTML中引用omi.js:\r\n\r\n```html\r\n\r\n```\r\n\r\n然后:\r\n\r\n```js\r\nvar Hello = Omi.create(\"Hello\", {\r\n style: function () {\r\n return \"h1{ cursor:pointer }\";\r\n },\r\n \r\n handleClick: function (dom) {\r\n alert(dom.innerHTML)\r\n },\r\n \r\n render: function () {\r\n return '
\\\r\n

\\\r\n Hello ,{{name}}!\\\r\n

\\\r\n
'\r\n }\r\n});\r\n\r\nvar Test = Omi.create(\"Test\", {\r\n render: function () {\r\n return '
\\\r\n
Test
\\\r\n \\\r\n
'\r\n }\r\n});\r\n\r\nOmi.render(new Test(),'#container');\r\n```\r\n当然除了在HTML引入脚本,你还可以使用AMD、CMD或者CommonJS的方式引入Omi,这里就不再一一列举。\r\n\r\n需要注意的是,Omi.create的第一个参数Hello是用来生成Tag Name的。你可以在其他地方嵌入你的组件。如:\r\n\r\n```js\r\n ...\r\n render:function() {\r\n return '
\\\r\n \\\r\n
Test XXXX
\\\r\n \\\r\n
';\r\n }\r\n ...\r\n```\r\n\r\n点击这里→在线试试\r\n" - -/***/ }, -/* 16 */ -/***/ function(module, exports) { - - module.exports = "## 继承\r\n\r\n通过继承机制,可以利用已有的数据类型来定义新的数据类型。所定义的新的数据类型不仅拥有新定义的成员,而且还同时拥有旧的成员。我们称已存在的用来派生新类的类为基类,又称为父类。由已存在的类派生出的新类称为派生类,又称为子类。\r\n\r\n### 举个例子\r\n\r\n```js\r\nclass Hello extends Omi.Component {\r\n constructor(data) {\r\n super(data);\r\n }\r\n \r\n style () {\r\n return `\r\n div{\r\n cursor:pointer;\r\n }\r\n `;\r\n }\r\n \r\n handleClick(target, evt){\r\n alert(target.innerHTML);\r\n }\r\n \r\n render() {\r\n return '
Hello {{name}}!
'\r\n }\r\n}\r\n\r\nclass SubHello extends Hello {\r\n constructor(data) {\r\n super(data);\r\n }\r\n}\r\n\r\nOmi.render(new SubHello({ name : 'Omi' }),'#container');\r\n```\r\n\r\n点击这里→在线试试\r\n\r\n### ES5下的继承\r\n\r\n```js\r\nvar Hello = Omi.create(\"Hello\",{\r\n render:function(){\r\n return '
Hello {{name}}!
'\r\n }\r\n})\r\n\r\nvar SubHello = Omi.create(\"SubHello\",Hello,{ });\r\n\r\n\r\nOmi.render(new SubHello({ name : 'Omi' }),'#container');\r\n```\r\n\r\n点击这里→在线试试" - -/***/ }, -/* 17 */ -/***/ function(module, exports) { - - module.exports = "## 安装\n\n[Omi](https://github.com/AlloyTeam/omi)(读音 / [ˈomɪ] /, 汉字类似于 欧米) 是一款用于创建用户界面的组件化框架,开放并且现代,故得名:Omi。\n\n### 安装 Omi\n\n我们推荐使用 [npm](https://www.npmjs.com/) 来管理你的前端依赖.\n\n通过npm安装Omi,你只需要执行下面的命令:\n\n``` js\n$ npm install omi\n```\n\n## omi-cli\n\n你也可以通过omi-cli去初始化你的项目:\n\n``` js\n$ npm install omi-cli -g //安装cli\n$ omi init your_project_name //初始化项目,你也可以在一个空的文件夹下执行 omi init\n$ cd your_project_name //如果你是在空文件夹下执行的 omi init。请无视这条命令\n$ npm run dev //开发\n$ npm run dist //部署发布\n```" - -/***/ }, -/* 18 */ -/***/ function(module, exports) { - - module.exports = "## 生命周期\r\n\r\n|name |avatars |company | \r\n|---|---|---|\r\n| constructor | 构造函数 | new的时候 |\r\n| install | 初始化安装,这可以拿到用户传进的data进行处理 | 实例化 |\r\n| installed | 安装完成,HTML已经插入页面之后执行 | 实例化 |\r\n| uninstall | 卸载组件。执行remove方法会触发该事件 | 销毁时 |\r\n| beforeUpdate | 更新前 | 存在期 |\r\n| afterUpdate | 更新后 | 存在期 |\r\n\r\n## 示意图\r\n\r\n![lc](http://images2015.cnblogs.com/blog/105416/201703/105416-20170322083548924-1871234168.jpg)\r\n \r\n### 举个例子\r\n\r\n```js\r\nclass Timer extends Omi.Component {\r\n constructor(data) {\r\n super(data);\r\n }\r\n\r\n install () {\r\n this.data = {secondsElapsed: 0};\r\n }\r\n\r\n tick() {\r\n this.data.secondsElapsed++;\r\n this.update();\r\n }\r\n\r\n installed(){\r\n this.interval = setInterval(() => this.tick(), 1000);\r\n }\r\n\r\n uninstall() {\r\n clearInterval(this.interval);\r\n }\r\n\r\n\r\n style () {\r\n return `\r\n .num { color:red; }\r\n `;\r\n }\r\n\r\n render () {\r\n return `
Seconds Elapsed: {{secondsElapsed}}
`;\r\n }\r\n}\r\n```\r\n\r\n点击这里→在线试试\r\n" - -/***/ }, -/* 19 */ -/***/ function(module, exports) { - - module.exports = "## 循环遍历\r\n\r\n下面介绍mustache.js的方式和javascript遍历的方式。\r\n\r\n### 方式一\r\n\r\n```js\r\nclass List extends Omi.Component {\r\n constructor(data) {\r\n super(data);\r\n }\r\n\r\n render () {\r\n return `
\r\n
    \r\n {{#items}} \r\n
  • {{text}}
  • \r\n {{/items}}\r\n
\r\n
`;\r\n }\r\n}\r\n\r\nOmi.render(new List({\r\n items: [\r\n {id: 1, text: 'Omi'},\r\n {id: 2, text: 'dntzhang'},\r\n {id: 3, text: 'AlloyTeam'}\r\n ]\r\n}),\"body\");\r\n```\r\n\r\nmustache.js更详细的循环遍历使用可看[https://github.com/janl/mustache.js#non-empty-lists](https://github.com/janl/mustache.js#non-empty-lists)。 比如还支持:\r\n\r\n* 如果items的每一项是字符串,可以直接**{{.}}**的方式来输出每一项\r\n* 循环的时候调用定义好的函数\r\n\r\n点击这里→在线试试\r\n\r\n### 方式二\r\n\r\n既然ES6+了,当然可以使用${ }以及Array的map方法: \r\n\r\n```js\r\nclass List extends Omi.Component {\r\n constructor(data) {\r\n super(data);\r\n }\r\n\r\n render() {\r\n return `
\r\n
    \r\n ${this.data.items.map(item =>\r\n `
  • ${item.text}
  • `\r\n ).join('')}\r\n
\r\n
`;\r\n }\r\n}\r\n\r\nOmi.render(new List({\r\n items: [\r\n {id: 1, text: 'Omi'},\r\n {id: 2, text: 'dntzhang'},\r\n {id: 3, text: 'AlloyTeam'}\r\n ]\r\n}),\"body\");\r\n```\r\n\r\n你将在页面看到如下效果:\r\n\r\n![pv](http://images2015.cnblogs.com/blog/105416/201701/105416-20170122095724129-2059595233.png)\r\n\r\n点击这里→在线试试\r\n\r\n如果想在循环里加些判断呢?比如需要把id为偶数的隐藏起来:\r\n\r\n```js\r\nrender() {\r\n return `
\r\n
    \r\n ${this.data.items.map(item =>\r\n `
  • ${item.text}
  • `\r\n ).join('')}\r\n
\r\n
`;\r\n}\r\n```\r\n\r\n所以模板字符串还是非常方便,随着ES继续发展下去,模板引擎估计会慢慢消失。所以omi提供了 omi.lite.js 版本不包含任何模板引擎。" - -/***/ }, -/* 20 */ -/***/ function(module, exports) { - - module.exports = "## 插件体系\r\n\r\n[Omi](https://github.com/AlloyTeam/omi)是Web组件化框架,怎么又来了个插件的概念?\r\n\r\n可以这么理解: Omi插件体系可以赋予dom元素一些能力,并且可以和组件的实例产生关联。\r\n\r\n### omi-drag\r\n\r\n且看这个例子:\r\n\r\n点击这里→在线试试\r\n\r\n```js\r\nimport OmiDrag from './omi-drag.js';\r\n\r\nOmiDrag.init();\r\n\r\nclass App extends Omi.Component {\r\n constructor(data) {\r\n super(data);\r\n }\r\n\r\n render() {\r\n return `\r\n
\r\n
Drag Me
\r\n
\r\n `;\r\n\r\n }\r\n\r\n style(){\r\n return `\r\n .test{\r\n width:100px;\r\n height:100px;\r\n color:white;\r\n line-height:90px;\r\n text-align:center;\r\n background-color:#00BFF3;\r\n }\r\n `\r\n }\r\n}\r\n\r\nOmi.render(new App(),\"#container\");\r\n```\r\n\r\n如上面的代码所示,通过在div上标记omi-drag,这个div就能够被用户使用鼠标拖拽。我们称omi-drag.js为omi插件。\r\n是不是非常方便?那么这个omi-drag是怎么实现的?\r\n\r\n## Omi.extendPlugin\r\n\r\n核心方法: Omi.extendPlugin( pluginName, handler )\r\n\r\n下面的代码就是展示了如何通过 Omi.extendPlugin 赋予dom拖拽的能力:\r\n\r\n```js\r\n;(function () {\r\n\r\n var OmiDrag = {};\r\n var Omi = typeof require === 'function'\r\n ? require('omi')\r\n : window.Omi;\r\n\r\n OmiDrag.init = function(){\r\n Omi.extendPlugin('omi-drag',function(dom, instance){\r\n dom.style.cursor='move';\r\n var isMouseDown = false,\r\n preX = null,\r\n preY = null,\r\n currentX = null,\r\n currentY = null,\r\n translateX = 0,\r\n translateY = 0;\r\n\r\n dom.addEventListener('mousedown',function(evt){\r\n isMouseDown = true;\r\n preX = evt.pageX;\r\n preY = evt.pageY;\r\n evt.stopPropagation();\r\n },false);\r\n\r\n window.addEventListener('mousemove',function(evt){\r\n if(isMouseDown){\r\n currentX = evt.pageX;\r\n currentY = evt.pageY;\r\n if(preX != null){\r\n translateX += currentX - preX;\r\n translateY += currentY - preY;\r\n dom.style.transform = 'translateX('+translateX+'px) translateY('+translateY+'px)';\r\n }\r\n preX = currentX;\r\n preY = currentY;\r\n evt.preventDefault();\r\n }\r\n },false);\r\n\r\n window.addEventListener('mouseup',function(){\r\n isMouseDown = false;\r\n preX = preY = currentX = currentY = null;\r\n },false);\r\n });\r\n }\r\n\r\n OmiDrag.destroy = function(){\r\n delete Omi.plugins['omi-drag'];\r\n };\r\n\r\n if (typeof exports == \"object\") {\r\n module.exports = OmiDrag;\r\n } else if (typeof define == \"function\" && define.amd) {\r\n define([], function(){ return OmiDrag });\r\n } else {\r\n window.OmiDrag = OmiDrag;\r\n }\r\n\r\n})();\r\n```\r\n\r\n方法: Omi.extendPlugin( pluginName, handler )\r\n\r\n其中pluginName为插件的名称\r\n其中handler为处理器。handler可以拿到标记了pluginName的dom以及dom所在的组件的实例,即 dom 和 instance。\r\n\r\n通过 Omi.extendPlugin,可以赋予dom元素一些能力,也可以和组件的实例(instance)产生关联。\r\n但是上面的例子没有和instance产生关联,我们接下来试试:\r\n\r\n## 关联instance\r\n\r\n我们想在组件里面能够监听到move并且执行回调。如下:\r\n\r\n```js\r\n...\r\n...\r\nmoveHandler(){\r\n console.log('moving');\r\n}\r\n\r\nrender() {\r\n return `\r\n
\r\n
Drag Me
\r\n
\r\n `;\r\n}\r\n...\r\n```\r\n\r\n主要被拖动过程中,moveHandler就不断地被执行。插件代码需要修改:\r\n\r\n```js\r\n...\r\nwindow.addEventListener('mousemove',function(evt){\r\n if(isMouseDown){\r\n currentX = evt.pageX;\r\n currentY = evt.pageY;\r\n if(preX != null){\r\n translateX += currentX - preX;\r\n translateY += currentY - preY;\r\n dom.style.transform = 'translateX('+translateX+'px) translateY('+translateY+'px)';\r\n }\r\n preX = currentX;\r\n preY = currentY;\r\n evt.preventDefault();\r\n instance.moveHandler(evt);\r\n }\r\n},false);\r\n```\r\n\r\n我们在里面增加了instance.moveHandler(evt);方法,用来执行组件实例上的moveHandler方法。\r\n这样的话:就是组件的实例(instance)产生关联。但是还是有问题?如果标记了多个omi-drag 就会有问题!如:\r\n\r\n```js\r\n...\r\nrender() {\r\n return `\r\n
\r\n
Drag Me
\r\n
Drag Me
\r\n
\r\n `;\r\n}\r\n...\r\n```\r\n\r\n通常我们系统每个omi-drag都能对应一个回调函数,如:\r\n\r\n```js\r\n...\r\n...\r\nmoveHandlerA(){\r\n console.log('moving');\r\n}\r\n\r\nmoveHandlerB(){\r\n console.log('moving');\r\n}\r\n\r\nrender() {\r\n return `\r\n
\r\n
Drag Me A
\r\n
Drag Me B
\r\n
\r\n `;\r\n}\r\n...\r\n```\r\n\r\n怎么办?怎么实现?有办法!通过dom传递数据给插件。\r\n\r\n## 传递数据\r\n\r\n先来看最后实现的效果:\r\n\r\n```js\r\n...\r\n...\r\nmoveHandlerA(){\r\n console.log('moving');\r\n}\r\n\r\nmoveHandlerB(){\r\n console.log('moving');\r\n}\r\n\r\nrender() {\r\n return `\r\n
\r\n
Drag Me A
\r\n
Drag Me B
\r\n
\r\n `;\r\n}\r\n...\r\n```\r\n\r\nomi-drag修改的地方:\r\n\r\n```js\r\n...\r\nvar handlerName = dom.getAttribute('dragMove');\r\n\r\nwindow.addEventListener('mousemove',function(evt){\r\n if(isMouseDown){\r\n currentX = evt.pageX;\r\n currentY = evt.pageY;\r\n if(preX != null){\r\n translateX += currentX - preX;\r\n translateY += currentY - preY;\r\n dom.style.transform = 'translateX('+translateX+'px) translateY('+translateY+'px)';\r\n }\r\n preX = currentX;\r\n preY = currentY;\r\n evt.preventDefault();\r\n instance[handlerName](evt);\r\n }\r\n},false);\r\n...\r\n```\r\n\r\n* 通过 var handlerName = dom.getAttribute('dragMove') 拿到dom上声明的dragMove\r\n* 通过 instance[handlerName](evt) 去执行对应的方法\r\n\r\n点击这里→在线试试\r\n\r\n## 更多插件\r\n\r\n* [omi-finger](https://github.com/AlloyTeam/omi/tree/master/plugins/omi-finger) Omi的[AlloyFinger](https://github.com/AlloyTeam/AlloyFinger)插件,支持各种触摸事件和手势\r\n* [omi-transform](https://github.com/AlloyTeam/omi/tree/master/plugins/omi-transform) Omi的[transformjs](http://alloyteam.github.io/AlloyTouch/transformjs/)插件,快速方便地设置DOM的CSS3 Transform属性\r\n* [omi-touch](https://github.com/AlloyTeam/omi/tree/master/plugins/omi-touch) Omi的[AlloyTouch](https://github.com/AlloyTeam/AlloyTouch)插件,Omi项目的触摸运动解决方案(支持触摸滚动、旋转、翻页、选择等等)\r\n* [omi-jquery-date-picker](https://github.com/AlloyTeam/omi/tree/master/plugins/omi-jquery-date-picker) Omi的时间选择插件,支持各种时间或者时间区域选择\r\n" - -/***/ }, -/* 21 */ -/***/ function(module, exports) { - - module.exports = "## Store 体系\r\n\r\n先说说Store系统是干什么的!\r\n\r\n当我们组件之间,拥有共享的数据的时候,经常需要进行组件通讯。在Omi框架里,组件通讯非常方便:\r\n\r\n* 通过在组件上声明 data-* 传递给子节点\r\n* 通过在组件上声明 data 传递给子节点 (支持复杂数据类型的映射)\r\n* 声明 group-data 把数组里的data传给一堆组件传递(支持复杂数据类型的映射)\r\n* 完全面向对象,可以非常容易地拿到对象的实例,之后可以设置实例属性和调用实例的方法。比如(标记name、标记omi-id)\r\n\r\n当然你也可以使用event emitter / pubsub库在组件之间通讯,比如这个只有 200b 的超小库[mitt](https://github.com/developit/mitt) 。但是需要注意mitt兼容到IE9+,Omi兼容IE8。\r\n\r\n虽然组件通讯非常方便,但是各种数据传递、组件实例互操作或者循环依赖,让代码非常难看且难以维护。所以:\r\n\r\nOmi.Store是为了让 组件通讯几乎绝迹 。虽然:\r\n\r\n\tRedux 的作者 Dan Abramov 说过:Flux 架构就像眼镜:您自会知道什么时候需要它。\r\n\t\r\n但是,我不会告诉你\r\n\r\n\tOmi Store 系统就像眼镜:您自会知道什么时候需要它。\r\n\t\r\n因为,Omi Store使用足够简便,对架构入侵性极极极小(3个极代表比极小还要小),让数据、数据逻辑和UI展现彻底分离,所以我的观点是:\r\n\r\n\t如果使用Omi,请使用Omi.Store架构。\r\n\t\r\n比如连这个[Todo例子](https://github.com/AlloyTeam/omi/tree/master/example/todo-store)都能使用Omi.Store架构。如果连复杂度都达不到Todo,那么Omi其实都没有必要使用,你可能只需要一个模板引擎便可。\r\n\r\n\r\n### 定义 Omi.Store\r\n\r\nOmi.Store是基类,我们可以继承Omi.Store来定义自己的Store,比如下面的TodoStore。\r\n\r\n```js\r\nimport Omi from 'omi'\r\n\r\nclass TodoStore extends Omi.Store {\r\n constructor(data , isReady) {\r\n super(isReady)\r\n\r\n this.data = Object.assign({\r\n items:[],\r\n text:'',\r\n length:0\r\n },data)\r\n\r\n this.data.length = this.data.items.length\r\n }\r\n\r\n add(){\r\n this.data.items.push(this.data.text)\r\n this.data.text = \"\"\r\n this.data.length = this.data.items.length\r\n this.update()\r\n }\r\n\r\n updateText(text){\r\n this.data.text = text\r\n }\r\n\r\n clear(){\r\n this.data.items.length = 0\r\n this.data.length = 0\r\n this.data.text = \"\"\r\n this.update()\r\n }\r\n}\r\n\r\nexport default TodoStore\r\n```\r\n\r\nTodoStore定义类数据的基本格式和数据模型的逻辑。\r\n比如 this.data 就是数据的基本格式, \r\n\r\n```js\r\n{\r\n items:[],\r\n text:'',\r\n length:0\r\n}\r\n```\r\n\r\nadd,updateText和clear就是数据模型的逻辑。\r\n\r\n### 使用 Omi.Store\r\n\r\n通过 new 关键字来使用TodoStore对象的实例。\r\n\r\n```js\r\nlet store = new TodoStore({ /* 初始化配置 */ })\r\n```\r\n\r\n上面可以传入一些初始化配置信息,store里面便包含了整个应用程序共享的状态数据以及相关数据逻辑方法(add,updateText,clear)。\r\n\r\n当然,这些初始化配置信息可能是异步拉取的。所以,有两种方法解决异步拉取store配置的问题:\r\n\r\n* 先let store = new TodoStore(),再Omi.render,组件内部监听store.ready,拉取数据更改store的data信息,然后执行store.beReady()\r\n* 拉取数据,然后new TodoStore(),再Omi.render\r\n\r\n### 根组件注入 store\r\n\r\n为了让组件树能够使用到 store,可以通过Omi.render的第三个参数给根组件注入 store:\r\n\r\n```js\r\nOmi.render(new Todo(),'body',{\r\n store: store\r\n});\r\n```\r\n\r\n当然ES2015已经允许你这样写了:\r\n\r\n```js\r\nOmi.render(new Todo(),'body',{\r\n store\r\n});\r\n```\r\n\r\n两份代码同样的效果。\r\n\r\n通过Omi.render注入之后,在组件树的所有组件都可以通过 this.$store 访问到 store。\r\n\r\n### 简便的 beforeRender\r\n\r\nbeforeRender这个函数,是生命周期的一部分。且看下面这张图:\r\n\r\n![beforeRender](http://images2015.cnblogs.com/blog/105416/201703/105416-20170322083548924-1871234168.jpg)\r\n\r\n在render之前,会去执行beforeRender方法。所以可以利用该方法写store的data到组件data的转换逻辑。比如:\r\n\r\n```js\r\nclass List extends Omi.Component {\r\n beforeRender(){\r\n this.data.items = this.$store.data.items\r\n }\r\n\r\n render () {\r\n return `
    {{#items}}
  • {{.}}
  • {{/items}}
`\r\n }\r\n}\r\n```\r\n\r\n再比如todo使用length和text:\r\n\r\n```js\r\nimport Omi from '../../src/index.js';\r\nimport List from './list.js';\r\n\r\nOmi.makeHTML('List', List);\r\n\r\nclass Todo extends Omi.Component {\r\n\r\n install(){\r\n this.$store.ready(()=>this.update())\r\n }\r\n\r\n beforeRender(){\r\n this.data.length = this.$store.data.items.length\r\n this.data.text = this.$store.text\r\n }\r\n\r\n add (evt) {\r\n evt.preventDefault();\r\n this.$store.add();\r\n }\r\n\r\n handleChange(target){\r\n this.$store.updateText(target.value);\r\n }\r\n\r\n render () {\r\n return `
\r\n

TODO

\r\n \r\n
\r\n \r\n \r\n
\r\n
`;\r\n }\r\n}\r\n\r\nexport default Todo;\r\n```\r\n\r\n为什么要去写beforeRender方法?因为render只会使用this.data去渲染页面而不会去使用this.$store.data,所以需要把数据转移到组件的this.data下。这样组件既能使用自身的data,也能使用全局放this.$store.data了。\r\n\r\n更为详细的代码可以[点击这里](https://github.com/AlloyTeam/omi/tree/master/example/todo-store)。" - -/***/ }, -/* 22 */ -/***/ function(module, exports) { - - module.exports = "## 模板切换\r\n\r\nOmi有三个版本。其中的omi.js和omi.lite.js属于Web端使用的版本。\r\n\r\n* omi.js内置了[mustache.js](https://github.com/janl/mustache.js)作为模版引擎\r\n* omi.lite.js不包含任何模版引擎\r\n\r\nOmi不强制开发者使用mustache.js,你可以根据业务场景使用任意模板引擎或者不使用模板引擎。\r\n\r\n那么怎么使用别的模板引擎?下面拿[artTemplate](https://github.com/aui/artTemplate)作为例子。\r\n\r\n### 使用artTemplate\r\n\r\n```js\r\nOmi.template = function(tpl, data){\r\n return artTemplate.compile(tpl)(data);\r\n}\r\n```\r\n重写Omi.template方法,tpl为传入的模板,data为模板所需的数据,返回值为HTML。\r\n重写完毕后就能在render使用artTemplate的语法,如:\r\n\r\n```js\r\nclass List extends Omi.Component {\r\n constructor(data) {\r\n super(data);\r\n }\r\n\r\n style () {\r\n return `\r\n h1 { color:red; }\r\n li{ color:green;}\r\n `;\r\n }\r\n\r\n render () {\r\n return `

{{title}}

\r\n
    \r\n {{each list as value i}}\r\n
  • 索引 {{i + 1}} :{{value}}
  • \r\n {{/each}}\r\n
`;\r\n }\r\n}\r\n```\r\n\r\n### 相关地址\r\n\r\n* [演示地址](http://alloyteam.github.io/omi/example/artTemplate/)\r\n* [源码地址](https://github.com/AlloyTeam/omi/tree/master/example/artTemplate)" - -/***/ }, -/* 23 */ -/***/ function(module, exports) { - - module.exports = "## Omi的理念\n\nOmi的理念是基于面向对象编程体系,内建积木系统。\n 传统的单向数据流或者抛出event的组件通讯方式增加了系统的稳定性,但是丧失了灵活性。一定程度上也降低了组件的复用。所谓鱼和熊掌不可兼得。\n 面向对象体系需要多一个逻辑层,可以自由操作所有组件的instance,instance之间的逻辑关系构建出了整个程序。这样组件间的逻辑,通信,复用就全部迎刃而解。组件也更加单一职责,更松耦合。\n\n对比函数式编程、命令式编程与面向对象编程,可以归纳总结出下面几条:\n\n- 命令式编程干脆直接,利用循环条件等控制流程,强调执行过程\n- 命令式编程对硬件执行友好,运行更容易,却阻碍了复杂程序的设计\n- 函数式强调输入和输出,并非执行过程\n- 函数式倡导多个简单执行单元组合成复杂运算程序\n- 面向对象编程将对象作为程序的基本单元,更具有重用性、灵活性和扩展性\n\nJavascript是哪种类型的语言?现在ES6+已经有了class。那么他是面向对象语言?\n但是JS可以在任意地方定义函数并且当作把函数当作值来传递。那么他是函数式编程语言?\n所以,没有精准的定义,取决于你的用法和姿势。其次,Web组件化架构层面编程模型和语言层面编程模型是非常自由的关系。意思就是,你可以用Javascript构建函数式编程框架如React,也可以基于面向对象体系搭建Omi。\n\n### 函数式编程 VS 面向对象编程\n\n在UI组件框架层面,函数式编程的代表有React,Omi属于面向对象编程体系。那么他们各有什么优缺点?下面做了个对比(其实也是函数式编程与面向对象编程的对比):\n\n| | React | Omi |\n| ------------- |:-------------:|:-----:|\n| 组件通信 | ★★★★☆| ★★★★★ |\n| 稳定性 | ★★★★★ | ★★★★☆ |\n| 灵活性 | ★★★★☆| ★★★★★ |\n| 扩展性 | ★★★★☆ | ★★★★★ |\n| 测试性 | ★★★★★ | ★★★★☆ |\n| 文件大小 | ★★★☆☆ | ★★★★★ |\n| 功能特性 | ★★★☆☆ | ★★★★☆ |\n| DOM性能 | ★★★★★ | ★★★★☆ |\n| 动画性能 | ★★★★☆ | ★★★★★ |\n| 抽象复杂度 | ★★★★☆ | ★★★★★ |\n| 异步编程 | ★★★★★ | ★★★★☆ |\n\n可以看得出,鱼和熊掌不可兼得。面向对象编程更具有重用性、灵活性和扩展性,带来的问题就是更加难测试。\n具体来说,如函数式编程,其测试面积是state1 + state2 + ... + stateN;在面向对象编程中,其测试面积是state1×event1 + state2×event2 + ... + stateN×eventN。\n\n总结来说,更加推荐使用面向对象的方式去搭建UI组件化框架。\n\n
\n\n### 全文结束,感谢阅读。[开始Omi之旅吧!](https://github.com/AlloyTeam/omi) \n\n" - -/***/ }, -/* 24 */ -/***/ function(module, exports) { - - module.exports = "## Component Communication\r\n\r\nCommunication between [Omi](https://github.com/AlloyTeam/omi) components is very flexible, there are many options:\r\n\r\n- By declaring `data-*` on the component to pass data to child node\r\n- By declaring `data` on the component to pass data to child node (support complex data types mapping)\r\n- By declaring `group-data` (support complex data types mapping)\r\n- It's completely object-oriented, you can easily get the object instance, then you can set the instance of the property or call the instance of the method\r\n\r\nLet's see some examples.\r\n\r\n### Communicate by `data-*`\r\n\r\n```js\r\nclass Hello extends Omi.Component {\r\n constructor(data) {\r\n super(data);\r\n }\r\n \r\n style () {\r\n return `\r\n h1{\r\n \tcursor:pointer;\r\n }\r\n `;\r\n }\r\n \r\n handleClick(target, evt){\r\n alert(target.innerHTML);\r\n }\r\n \r\n render() {\r\n return `\r\n
\r\n \t

Hello ,{{name}}!

\r\n
\r\n \t\t`;\r\n }\r\n}\r\n\r\nOmi.makeHTML('Hello', Hello);\r\n\r\nclass App extends Omi.Component {\r\n constructor(data) {\r\n super(data);\r\n }\r\n \r\n render() {\r\n return `\r\n
\r\n \r\n
\r\n `;\r\n }\r\n}\r\n\r\nOmi.render(new App(),\"#container\");\r\n```\r\n\r\nGenerally `data-*` is used to pass value types such as string and number. It is worth noting that, through `data-*`, received data types are string. You need to manually transform it to the number type.\r\n\r\nNormally, communicate by `data-*` is enough, but sometimes we may need to use complex data types, then we can use `data` to communicate.\r\n\r\n### Communicate by `data`\r\n\r\nAs shown in the above code, name can be passed to the subcomponent by `data-name=\"Omi\"`. The following code can also achieve the same effect.\r\n\r\n```js\r\n...\r\nclass App extends Omi.Component {\r\n constructor(data) {\r\n super(data);\r\n this.helloData = { name : 'Omi' };\r\n }\r\n \r\n render() {\r\n return `\r\n
\r\n \r\n
\r\n `;\r\n }\r\n}\r\n\r\nOmi.render(new App(),\"#container\");\r\n```\r\n\r\nUse the `data` tag, it will find the property from the component instance (that is, this), this can be mounted with any complex objects. This also broke the limitations of `data-*`.\r\n\r\nThen how do we pass `data` that is in a deep depth of the instance to the Hello? No worries, `data` tag can be a complex statement:\r\n\r\n```js\r\n...\r\nclass App extends Omi.Component {\r\n constructor(data) {\r\n super(data);\r\n this.complexData ={\r\n a:{\r\n b:{\r\n c:[\r\n {\r\n e:[{\r\n name:'ComplexData Support1'\r\n },{\r\n name:'ComplexData Support2'\r\n }]\r\n },\r\n {\r\n name: 'ComplexData Support3'\r\n }\r\n ]\r\n }\r\n }\r\n };\r\n }\r\n \r\n render() {\r\n return `\r\n
\r\n \r\n
\r\n `;\r\n }\r\n}\r\n...\r\n```\r\n\r\nClick me for the complex data mapping\r\n\r\n### Communicate by `group-data`\r\n\r\n`group-data` can pass data to a group of components. \r\n\r\n```js\r\nimport Hello from './hello.js';\r\n\r\n\r\nOmi.makeHTML('Hello', Hello);\r\n\r\nclass App extends Omi.Component {\r\n constructor(data) {\r\n super(data);\r\n this.testData = [{name: 'Omi'}, {name: 'dntzhang'}, {name: 'AlloyTeam'}];\r\n }\r\n\r\n render() {\r\n return `\r\n
\r\n \r\n \r\n \r\n
\r\n `;\r\n\r\n }\r\n}\r\n\r\nOmi.render(new App(),\"#container\");\r\n```\r\n\r\nBy declaring a `group-data` tag in the sub-components, it will go to the current instance of the component (that is, `this`) to find the corresponding property. Then according to the current location, the data will pass to the positions one by one.\r\n\r\nThe results are as follows:\r\n\r\n![group-data results](http://images2015.cnblogs.com/blog/105416/201702/105416-20170216110701535-1698390390.png)\r\n\r\nClick me for the group-data example\r\n\r\nSimilarly, `group-data` supports the mapping of complex data types. It should be noted that the end of the group-data mapping must be an array:\r\n\r\n```js\r\nimport Hello from './hello.js';\r\n\r\n\r\nOmi.makeHTML('Hello', Hello);\r\n\r\nclass App extends Omi.Component {\r\n constructor(data) {\r\n super(data);\r\n this.complexData ={\r\n a:{\r\n b:{\r\n c:[\r\n {\r\n e:[{\r\n name:'ComplexData Support1'\r\n },{\r\n name:'ComplexData Support2'\r\n }]\r\n },\r\n {\r\n name: 'ComplexData Support3'\r\n }\r\n ]\r\n }\r\n }\r\n };\r\n }\r\n\r\n render() {\r\n return `\r\n
\r\n \r\n \r\n
\r\n `;\r\n\r\n }\r\n}\r\n\r\nOmi.render(new App(),\"#container\");\r\n```\r\n\r\nClick me for the complex group-data mapping\r\n\r\n### By object instance\r\n\r\n```js\r\n...\r\nclass App extends Omi.Component {\r\n constructor(data) {\r\n super(data);\r\n }\r\n \r\n installed(){\r\n this.hello.data.name = \"Omi\";\r\n this.update()\r\n }\r\n \r\n render() {\r\n return `\r\n
\r\n \r\n
\r\n `;\r\n }\r\n}\r\n\r\nOmi.render(new App(),\"#container\");\r\n```\r\n\r\n### By omi-id\r\n\r\n```js\r\n...\r\nclass App extends Omi.Component {\r\n constructor(data) {\r\n super(data);\r\n }\r\n \r\n installed(){\r\n Omi.get(\"hello\").data.name = \"Omi\";\r\n this.update()\r\n }\r\n \r\n render() {\r\n return `\r\n
\r\n \r\n
\r\n `;\r\n }\r\n}\r\n\r\nOmi.render(new App(),\"#container\");\r\n```\r\n\r\nBy declaring `omi-id` on the component, we can get the instance of the object anywhere in the program. This can be regarded as any component communication artifacts.\r\n\r\n" - -/***/ }, -/* 25 */ -/***/ function(module, exports) { - - module.exports = "## Components\r\n\r\n[Omi](https://github.com/AlloyTeam/omi) is based entirely on component architecture, which allows developers to build web applications like building blocks. Everything is components, components can be nested to create new components.\r\n\r\n![Omi Components System](http://images2015.cnblogs.com/blog/105416/201702/105416-20170210093427338-1536910080.png)\r\n\r\n### Simple Components\r\n\r\nLet's explore a simple Todo example to learn the components system in Omi.\r\n\r\n```js\r\nclass Todo extends Omi.Component {\r\n constructor(data) {\r\n super(data);\r\n }\r\n \r\n add (evt) {\r\n evt.preventDefault();\r\n this.data.items.push(this.data.text);\r\n this.data.text = '';\r\n this.update();\r\n }\r\n\r\n style () {\r\n return `\r\n h3 { color:red; }\r\n button{ color:green;}\r\n `;\r\n }\r\n\r\n handleChange(target){\r\n this.data.text = target.value;\r\n }\r\n\r\n render () {\r\n return `
\r\n

TODO

\r\n
    {{#items}}
  • {{.}}
  • {{/items}}
\r\n
\r\n \r\n \r\n
\r\n
`;\r\n }\r\n}\r\n\r\nOmi.render(new Todo({ items: [] ,text : '' }),\"body\");\r\n```\r\n\r\nThe HTML generated by the component will eventually be inserted into the body. The above example shows some of the features of Omi:\r\n\r\n- Data flow: `data` in `new Todo(data,..)` can be used directly in the template in render method.\r\n- Partial CSS: `h3` in `style()` only effect inside of render. It'll never pollute `h3` outside of this component. The same rule applies to `button`.\r\n- Declarative event binding: `onchange` will call `handleChange` that inside of the component. `this` refers to the current DOM element, `event` refers to the current DOM Event Object.\r\n- You need to manually call the `this.update()` method to update the component\r\n\r\nIt is important to note that, for more freedom and flexibility, Omi does not automatically update DOM while data changes. Developers need to call the `update` method manually.\r\n\r\nYou can also use [oba] (https://github.com/dntzhang/oba) or mobx to implement automatic updates.\r\n\r\nClick me for the live demo\r\n\r\n### Component Nesting\r\n\r\nIt's ok to not use nesting component if your page is super simple. However, for most of webpages and web applications, it is a necessary to define the nesting Components to implement complex features.\r\n\r\nFor instance, we can extract a `List` component form the Todo example. This brings maintainable, scalable and reuseable to our project:\r\n\r\n```js\r\nclass List extends Omi.Component {\r\n constructor(data) {\r\n super(data);\r\n }\r\n\r\n render () {\r\n return `
    {{#items}}
  • {{.}}
  • {{/items}}
`;\r\n }\r\n}\r\n```\r\n\r\nThen how to use this `List`? We need to use `Omi.makeHTML` to make the `List` to a tag which can be used in render method:\r\n\r\n```js\r\nimport List from './list.js';\r\n\r\nOmi.makeHTML('List', List);\r\n\r\nclass Todo extends Omi.Component {\r\n constructor(data) {\r\n super(data);\r\n this.data.length = this.data.items.length;\r\n this.listData = { items : this.data.items };\r\n }\r\n\r\n add (evt) {\r\n evt.preventDefault();\r\n this.list.data.items.push(this.data.text);\r\n this.data.length = this.list.data.items.length;\r\n this.data.text = '';\r\n this.update();\r\n }\r\n\r\n style () {\r\n return `\r\n h3 { color:red; }\r\n button{ color:green;}\r\n `;\r\n }\r\n\r\n handleChange(target){\r\n this.data.text = target.value;\r\n }\r\n\r\n render () {\r\n return `
\r\n

TODO

\r\n \r\n
\r\n \r\n \r\n
\r\n
`;\r\n }\r\n}\r\n```\r\n\r\n- In line 3, we use `makeHTML` to make the component to a tag which can be used in render method. Of course, `Omi.makeHTML('List', List);` can also be written in the end of List component.\r\n- In line 9, the parent component defines the 'listData' property\r\n- In line 34, we use List component in the render method. `name` attribute allows us easily find the instance of the component by using `this`.`data=\"listData\"` attribute allows us easily pass `this.listData` to the sub component from parent component.\r\n\r\nIt should be noted that the `data` passed from `data=\"listData\"` is cloned to the subcomponents by Object.assign(shallow copy) , which means if we want to change the DOM, we recommend that first update the `data` of the instance of subcomponent(not the parent component's `listData` ) and secondly call the `update` method.\r\n\r\nIn fact there are 4 way to communicate between components, it'll be explained later.\r\n\r\nClick me for the live demo\r\n" - -/***/ }, -/* 26 */ -/***/ function(module, exports) { - - module.exports = "## Conditional Rendering\r\n\r\nIn most case, we need to show different layouts according to different states. For example, some users are vip and we need to show vip logo for them. Omi has many ways to meet this kind of requirements.\r\n\r\n### First Option\r\n\r\n```js\r\nclass ConditionTest extends Omi.Component {\r\n constructor(data) {\r\n super(data);\r\n }\r\n\r\n render () {\r\n return `{{#isVip}}\r\n
you are VIP.
\r\n {{/isVip}}\r\n {{^isVip}}\r\n
you are not VIP.
\r\n {{/isVip}}`;\r\n }\r\n}\r\n```\r\n\r\nIn the above case, we use the condition in mustachejs for rendering. Of course Omi does not force you to use mustachejs. You can use omi.lite.js and then override the `Omi.template` method to use any of your favorite template engines.\r\n\r\n### Second Option\r\n\r\n```js\r\nclass ConditionTest extends Omi.Component {\r\n constructor(data) {\r\n super(data);\r\n }\r\n\r\n render () {\r\n if(this.data.isVip){\r\n return '
you are VIP.
';\r\n }else{\r\n return '
you are not VIP.
';\r\n }\r\n }\r\n}\r\n```\r\n\r\n`render` provides a very good programmability, which can write any js code inside. Oh, don't forget that `style` method can also have js code inside it.\r\n\r\n```js\r\nclass ConditionTest extends Omi.Component {\r\n constructor(data) {\r\n super(data);\r\n }\r\n\r\n style (){\r\n if(this.data.isVip){\r\n return 'div{ color : red; }';\r\n }else{\r\n return 'div{ color : green; }';\r\n }\r\n }\r\n\r\n render () {\r\n if(this.data.isVip){\r\n return '
you are VIP.
';\r\n }else{\r\n return '
you are not VIP.
';\r\n }\r\n }\r\n}\r\n```" - -/***/ }, -/* 27 */ -/***/ function(module, exports) { - - module.exports = "## Handling Events\r\n\r\nThere are two types of events in Omi, built-in events and custom events. Built-in events clever use of the browser's own pipeline mechanism, you can easily get events instance and the triggered event elements through `event` and `this`.\r\n\r\n### Built-in events\r\n\r\nWhat is the built-in event? As long as the it can match the following regular expression.\r\n\r\n```js\r\non(abort|blur|cancel|canplay|canplaythrough|change|click|close|contextmenu|cuechange|dblclick|drag|dragend|dragenter|dragleave|dragover|dragstart|drop|durationchange|emptied|ended|error|focus|input|invalid|keydown|keypress|keyup|load|loadeddata|loadedmetadata|loadstart|mousedown|mouseenter|mouseleave|mousemove|mouseout|mouseover|mouseup|mousewheel|pause|play|playing|progress|ratechange|reset|resize|scroll|seeked|seeking|select|show|stalled|submit|suspend|timeupdate|toggle|volumechange|waiting|autocomplete|autocompleteerror|beforecopy|beforecut|beforepaste|copy|cut|paste|search|selectstart|wheel|webkitfullscreenchange|webkitfullscreenerror|touchstart|touchmove|touchend|touchcancel|pointerdown|pointerup|pointercancel|pointermove|pointerover|pointerout|pointerenter|pointerleave)\r\n```\r\n\r\nHow to bind built-in events? As follows:\r\n\r\n```js\r\nclass EventTest extends Omi.Component {\r\n constructor(data) {\r\n super(data);\r\n }\r\n\r\n handleClick(dom, evt){\r\n alert(dom.innerHTML);\r\n }\r\n\r\n render () {\r\n return `
Hello, Omi!
`;\r\n }\r\n}\r\n```\r\n\r\n### Custom events\r\n\r\nEvents that defined by developers is the custom events. Here is the pagination example:\r\n\r\n```js\r\nimport Omi from '../../src/index.js';\r\nimport Pagination from './pagination.js';\r\nimport Content from './content.js';\r\n\r\nOmi.makeHTML('Pagination', Pagination);\r\nOmi.makeHTML('Content', Content);\r\n\r\nclass Main extends Omi.Component {\r\n constructor(data) {\r\n super(data);\r\n }\r\n\r\n installed(){\r\n this.content.goto(this.pagination.data.currentPage+1);\r\n }\r\n \r\n handlePageChange(index){\r\n this.content.goto(index+1);\r\n }\r\n\r\n render () {\r\n return `
\r\n

Pagination Example

\r\n \r\n \r\n
`;\r\n }\r\n}\r\n\r\nOmi.render( new Main(),'body');\r\n```\r\n\r\nAs we can see, the `onPageChange` is a custom event, `handlePageChange` will being executed when `onPageChange` is triggered. The `onPageChange` method is executed in `Pagination`:\r\n\r\n```js\r\nimport Omi from '../../src/index.js';\r\n\r\nclass Pagination extends Omi.Component {\r\n ...\r\n ...\r\n ...\r\n linkTo: \"#\",\r\n prevText: \"Prev\",\r\n nextText: \"Next\",\r\n ellipseText: \"...\",\r\n prevShow: true,\r\n nextShow: true,\r\n onPageChange: function () { return false; }\r\n }, this.data);\r\n\r\n this.pageNum = Math.ceil(this.data.total / this.data.pageSize);\r\n }\r\n \r\n goto (index,evt) {\r\n evt.preventDefault();\r\n this.data.currentPage=index;\r\n this.update();\r\n this.data.onPageChange(index);\r\n }\r\n ...\r\n ...\r\n ...\r\n}\r\n```\r\n\r\nThis is a part of `Pagination` code. Highlight is the place to execute `onPageChange`.\r\n\r\n### Links\r\n\r\n- [Demo](http://alloyteam.github.io/omi/example/pagination/)\r\n- [Source](https://github.com/AlloyTeam/omi/tree/master/example/pagination)" - -/***/ }, -/* 28 */ -/***/ function(module, exports) { - - module.exports = "## Forms\r\n\r\nIt's much more convenient to control forms in Omi, especially `\r\n \r\n \r\n \r\n \r\n\r\n```\r\n\r\nThe third option is selected because it is being set to `selected` attribute. The problem is that developers need to traversed each option. While using Omi, you can write code like this:\r\n\r\n```html\r\n\r\n```\r\n\r\nThis will achieve the same effect. For example, you want to choose the first item:\r\n\r\n```html\r\n\r\n```\r\n\r\nIsn't it very convenient?\r\n\r\n### For Example\r\n\r\n```js\r\nclass FormTest extends Omi.Component {\r\n constructor(data) {\r\n super(data);\r\n \r\n }\r\n\r\n handleChange(target){\r\n console.log(target.value)\r\n this.data.value = target.value;\r\n }\r\n\r\n handleSubmit(evt) {\r\n alert('Your favorite flavor is: ' + this.data.value);\r\n evt.preventDefault();\r\n }\r\n \r\n render () {\r\n return `\r\n
\r\n \r\n \r\n
`;\r\n }\r\n}\r\n\r\nOmi.render(new FormTest({ value: 'mango' }),'#container');\r\n```\r\n\r\nClick me for a live demo" - -/***/ }, -/* 29 */ -/***/ function(module, exports) { - - module.exports = "## Get DOM\r\n\r\nWhile most of the time, developers do not need to find the DOM, but sometimes is a need to get the DOM.\r\n\r\nOmi provides a way to get the DOM node.\r\n\r\n### ref and refs\r\n\r\n```js\r\nclass Hello extends Omi.Component {\r\n constructor(data) {\r\n super(data);\r\n }\r\n \r\n style () {\r\n return `\r\n h1{\r\n cursor:pointer;\r\n }\r\n `;\r\n }\r\n \r\n handleClick(){\r\n alert(this.refs.abc.innerHTML);\r\n }\r\n \r\n render() {\r\n return `\r\n
\r\n

Hello ,{{name}}!

\r\n
\r\n `;\r\n }\r\n}\r\n\r\nOmi.render(new Hello({ name : \"Omi\" }),\"#container\");\r\n```\r\n\r\nAs we can see, by referencing `ref` as `abc` in HTML, the DOM node can be accessed through `this.refs.abc`.\r\n\r\nClick me for the live demo\r\n" - -/***/ }, -/* 30 */ -/***/ function(module, exports) { - - module.exports = "## Hello World\r\n\r\n### Hello World with ES20XX \r\n\r\nWe recommend using a bundler like [webpack](https://webpack.github.io/) or [Browserify](http://browserify.org/) so you can write modular code and bundle it together into small packages to optimize load time.\r\n\r\nThe small Omi example looks like this:\r\n\r\n```js\r\nimport Omi from './omi.js';\r\n\r\nclass Hello extends Omi.Component {\r\n constructor(data) {\r\n super(data);\r\n }\r\n \r\n style () {\r\n return `\r\n h1{\r\n cursor:pointer;\r\n }\r\n `;\r\n }\r\n \r\n handleClick(target){\r\n alert(target.innerHTML);\r\n }\r\n \r\n render() {\r\n return `\r\n
\r\n

Hello ,{{name}}!

\r\n
\r\n `;\r\n }\r\n}\r\n\r\nOmi.render(new Hello({ name : \"Omi\" }),\"body\");\r\n```\r\n\r\nThis code renders into body element. \r\n\r\n### Hello World with ES5\r\n\r\n```html\r\n\r\n```\r\n\r\nthen:\r\n\r\n```js\r\nvar Hello = Omi.create(\"Hello\", {\r\n style: function () {\r\n return \"h1{ cursor:pointer }\";\r\n },\r\n \r\n handleClick: function (dom) {\r\n alert(dom.innerHTML)\r\n },\r\n \r\n render: function () {\r\n return '
\\\r\n

\\\r\n Hello ,{{name}}!\\\r\n

\\\r\n
'\r\n }\r\n});\r\n\r\nvar Test = Omi.create(\"Test\", {\r\n render: function () {\r\n return '
\\\r\n
Test
\\\r\n \\\r\n
'\r\n }\r\n});\r\n\r\nOmi.render(new Test(),'#container');\r\n```" - -/***/ }, -/* 31 */ -/***/ function(module, exports) { - - module.exports = "## Inheritance\r\n\r\nThrough the inheritance mechanism, we can define new classes base on old classes. The new classes not only have newly defined members, but also have old members at the same time.\r\n\r\nWe call the existing class the base class, also known as the parent class. And the new class derived from the existing class is called a derived class, also known as a subclass.\r\n\r\n### For Example\r\n\r\n```js\r\nclass Hello extends Omi.Component {\r\n constructor(data) {\r\n super(data);\r\n }\r\n \r\n style () {\r\n return `\r\n div{\r\n cursor:pointer;\r\n }\r\n `;\r\n }\r\n \r\n handleClick(target, evt){\r\n alert(target.innerHTML);\r\n }\r\n \r\n render() {\r\n return '
Hello {{name}}!
'\r\n }\r\n}\r\n\r\nclass SubHello extends Hello {\r\n constructor(data) {\r\n super(data);\r\n }\r\n}\r\n\r\nOmi.render(new SubHello({ name : 'Omi' }),'#container');\r\n```\r\n\r\nClick me for the live demo\r\n\r\n### inherit in ES5\r\n\r\n```js\r\nvar Hello = Omi.create(\"Hello\",{\r\n render:function(){\r\n return '
Hello {{name}}!
'\r\n }\r\n})\r\n\r\nvar SubHello = Omi.create(\"SubHello\",Hello,{ });\r\n\r\n\r\nOmi.render(new SubHello({ name : 'Omi' }),'#container');\r\n```\r\n\r\nClick me for the live demo" - -/***/ }, -/* 32 */ -/***/ function(module, exports) { - - module.exports = "## Installation\r\n\r\n[Omi](https://github.com/AlloyTeam/omi) is open and modern framework for building user interfaces.\r\n\r\n### Installing Omi\r\n\r\nWe recommend using [npm](https://www.npmjs.com/) for managing front-end dependencies. If you're new to package managers.\r\n\r\nTo install Omi with npm, run:\r\n\r\n``` js\r\n$ npm install omi\r\n```\r\n### omi-cli\r\n\r\n``` js\r\n$ npm install omi-cli -g \r\n$ omi init your_project_name \r\n$ cd your_project_name \r\n$ npm run dev \r\n$ npm run dist \r\n```" - -/***/ }, -/* 33 */ -/***/ function(module, exports) { - - module.exports = "## Lifecycle\r\n\r\n| Name | Meaning | Occasion |\r\n| :-------------: | :-------------: | :-----: |\r\n| constructor | The constructor | When new a constructor |\r\n| install | The installation. We can process the data that user pass | When instantiate |\r\n| installed | Complete the installation. It'll trigger after HTML being inserted to the page. Please note that it'll trigger when component being removed and restored | **Instantiation and existence** |\r\n| uninstall | Uninstall the component. It'll trigger when remove is executed | When destroy |\r\n| beforeUpdate | Before update | When existence |\r\n| afterUpdate | After update | When existence |\r\n\r\n## Illustration\r\n\r\n![lc](http://images2015.cnblogs.com/blog/105416/201703/105416-20170322084234049-1482108845.jpg)\r\n\r\nIt should be noted that the installed will be executed during the instantiation, which is not shown above. For example, it'll executed when a component is removed and restored, or when the new component is being added.\r\n\r\n### Examples\r\n\r\n```js\r\nclass Timer extends Omi.Component {\r\n constructor(data) {\r\n super(data);\r\n }\r\n\r\n install () {\r\n this.data = {secondsElapsed: 0};\r\n }\r\n\r\n tick() {\r\n this.data.secondsElapsed++;\r\n this.update();\r\n }\r\n\r\n installed(){\r\n this.interval = setInterval(() => this.tick(), 1000);\r\n }\r\n\r\n uninstall() {\r\n clearInterval(this.interval);\r\n }\r\n\r\n\r\n style () {\r\n return `\r\n .num { color:red; }\r\n `;\r\n }\r\n\r\n render () {\r\n return `
Seconds Elapsed: {{secondsElapsed}}
`;\r\n }\r\n}\r\n```\r\n\r\nClick me for the live demo" - -/***/ }, -/* 34 */ -/***/ function(module, exports) { - - module.exports = "## Loop\r\n\r\nThe following describes how to traverses in mustache.js and javascript.\r\n\r\n### First Option\r\n\r\n```js\r\nclass List extends Omi.Component {\r\n constructor(data) {\r\n super(data);\r\n }\r\n\r\n render () {\r\n return `
\r\n
    \r\n {{#items}} \r\n
  • {{text}}
  • \r\n {{/items}}\r\n
\r\n
`;\r\n }\r\n}\r\n\r\nOmi.render(new List({\r\n items: [\r\n {id: 1, text: 'Omi'},\r\n {id: 2, text: 'dntzhang'},\r\n {id: 3, text: 'AlloyTeam'}\r\n ]\r\n}),\"body\");\r\n```\r\n\r\nMustache.js more detailed loop traversal use can see \r\n\r\nFor more details for traversal in mustache.js please view [https://github.com/janl/mustache.js#non-empty-lists](https://github.com/janl/mustache.js#non-empty-lists).\r\n\r\nFor example, it also support:\r\n\r\n- If each item of items is a string, you can directly use **{{.}}** to output each item\r\n- Call the defined function when looping\r\n\r\nClick me for the live demo\r\n\r\n### Second Option\r\n\r\nOf course, you can also use template string inside the `map`:\r\n\r\n```js\r\nclass List extends Omi.Component {\r\n constructor(data) {\r\n super(data);\r\n }\r\n\r\n render() {\r\n return `
\r\n
    \r\n ${this.data.items.map(item =>\r\n `
  • ${item.text}
  • `\r\n ).join('')}\r\n
\r\n
`;\r\n }\r\n}\r\n\r\nOmi.render(new List({\r\n items: [\r\n {id: 1, text: 'Omi'},\r\n {id: 2, text: 'dntzhang'},\r\n {id: 3, text: 'AlloyTeam'}\r\n ]\r\n}),\"body\");\r\n```\r\n\r\nYou will see the following page:\r\n\r\n![pv](http://images2015.cnblogs.com/blog/105416/201701/105416-20170122095724129-2059595233.png)\r\n\r\nClick me for the live demo" - -/***/ }, -/* 35 */ -/***/ function(module, exports) { - - module.exports = "## Plugin\r\n\r\n[Omi](https://github.com/AlloyTeam/omi) is a componentized web framework. Then what is plugin?\r\n\r\nIt can be understood that the Omi plugin system can give the dom element some ability and can be associated with the instance of the components.\r\n\r\n### omi-drag\r\n\r\nLet's see this example:\r\n\r\nClick me for the live deme\r\n\r\n```js\r\nimport OmiDrag from './omi-drag.js';\r\n\r\nOmiDrag.init();\r\n\r\nclass App extends Omi.Component {\r\n constructor(data) {\r\n super(data);\r\n }\r\n\r\n render() {\r\n return `\r\n
\r\n
Drag Me
\r\n
\r\n `;\r\n\r\n }\r\n\r\n style(){\r\n return `\r\n .test{\r\n width:100px;\r\n height:100px;\r\n color:white;\r\n line-height:90px;\r\n text-align:center;\r\n background-color:#00BFF3;\r\n }\r\n `\r\n }\r\n}\r\n\r\nOmi.render(new App(),\"#container\");\r\n```\r\n\r\nAs shown above, by adding `omi-drag` attribute to the div, it can be dragged by the user using the mouse. We call omi-drag.js an omi plugin.\r\n\r\nIsn't it very convenient? So how did this omi-drag implement?\r\n\r\n如上面的代码所示,通过在div上标记omi-drag,这个div就能够被用户使用鼠标拖拽。我们称omi-drag.js为omi插件。\r\n是不是非常方便?那么这个omi-drag是怎么实现的?\r\n\r\n## Omi.extendPlugin\r\n\r\nCore method: Omi.extendPlugin( pluginName, handler )\r\n\r\nThe following code shows how to use `Omi.extendPlugin` to give dom the drap and drop ability:\r\n\r\n```js\r\n;(function () {\r\n\r\n var OmiDrag = {};\r\n var Omi = typeof require === 'function'\r\n ? require('omi')\r\n : window.Omi;\r\n\r\n OmiDrag.init = function(){\r\n Omi.extendPlugin('omi-drag',function(dom, instance){\r\n dom.style.cursor='move';\r\n var isMouseDown = false,\r\n preX = null,\r\n preY = null,\r\n currentX = null,\r\n currentY = null,\r\n translateX = 0,\r\n translateY = 0;\r\n\r\n dom.addEventListener('mousedown',function(evt){\r\n isMouseDown = true;\r\n preX = evt.pageX;\r\n preY = evt.pageY;\r\n evt.stopPropagation();\r\n },false);\r\n\r\n window.addEventListener('mousemove',function(evt){\r\n if(isMouseDown){\r\n currentX = evt.pageX;\r\n currentY = evt.pageY;\r\n if(preX != null){\r\n translateX += currentX - preX;\r\n translateY += currentY - preY;\r\n dom.style.transform = 'translateX('+translateX+'px) translateY('+translateY+'px)';\r\n }\r\n preX = currentX;\r\n preY = currentY;\r\n evt.preventDefault();\r\n }\r\n },false);\r\n\r\n window.addEventListener('mouseup',function(){\r\n isMouseDown = false;\r\n preX = preY = currentX = currentY = null;\r\n },false);\r\n });\r\n }\r\n\r\n OmiDrag.destroy = function(){\r\n delete Omi.plugins['omi-drag'];\r\n };\r\n\r\n if (typeof exports == \"object\") {\r\n module.exports = OmiDrag;\r\n } else if (typeof define == \"function\" && define.amd) {\r\n define([], function(){ return OmiDrag });\r\n } else {\r\n window.OmiDrag = OmiDrag;\r\n }\r\n\r\n})();\r\n```\r\n\r\nMethod: Omi.extendPlugin( pluginName, handler )\r\n\r\n`pluginName` is the name of the plugin.\r\n\r\n`handler` is the processor. The handler can get the dom which marked as the `pluginName` and the instance of the component.\r\n\r\nWith `Omi.extendPlugin`, we can give the dom some ability, and can also be associated with the component instance.\r\n\r\nThe above example is not associated with the instance, let's try it:\r\n\r\n## Associated with instance\r\n\r\nWe want to be able to listen to the `move` inside the component and perform a callback. As follows:\r\n\r\n```js\r\n...\r\n...\r\nmoveHandler(){\r\n console.log('moving');\r\n}\r\n\r\nrender() {\r\n return `\r\n
\r\n
Drag Me
\r\n
\r\n `;\r\n}\r\n...\r\n```\r\n\r\nIn this case, the `moveHandler` will be continually executed while dragging. We can modify some code to solve this issue:\r\n\r\n```js\r\n...\r\nwindow.addEventListener('mousemove',function(evt){\r\n if(isMouseDown){\r\n currentX = evt.pageX;\r\n currentY = evt.pageY;\r\n if(preX != null){\r\n translateX += currentX - preX;\r\n translateY += currentY - preY;\r\n dom.style.transform = 'translateX('+translateX+'px) translateY('+translateY+'px)';\r\n }\r\n preX = currentX;\r\n preY = currentY;\r\n evt.preventDefault();\r\n instance.moveHandler(evt);\r\n }\r\n},false);\r\n```\r\n\r\nWe add `instance.moveHandler(evt)` method to execute the `moveHandler` method of component instance.\r\n\r\nThis is how associated with instance works.\r\n\r\nHowever, this may still have an issue if we add `omi-drag` to a list of `div`:\r\n\r\n```js\r\n...\r\nrender() {\r\n return `\r\n
\r\n
Drag Me
\r\n
Drag Me
\r\n
\r\n `;\r\n}\r\n...\r\n```\r\n\r\nUsually each of our `omi-drag` can correspond to a callback function, such as:\r\n\r\n```js\r\n...\r\n...\r\nmoveHandlerA(){\r\n console.log('moving');\r\n}\r\n\r\nmoveHandlerB(){\r\n console.log('moving');\r\n}\r\n\r\nrender() {\r\n return `\r\n
\r\n
Drag Me A
\r\n
Drag Me B
\r\n
\r\n `;\r\n}\r\n...\r\n```\r\n\r\nHow to achieve this? We can pass the data to the plugin via dom.\r\n\r\n## Passing data\r\n\r\nLet's see the final code:\r\n\r\n```js\r\n...\r\n...\r\nmoveHandlerA(){\r\n console.log('moving');\r\n}\r\n\r\nmoveHandlerB(){\r\n console.log('moving');\r\n}\r\n\r\nrender() {\r\n return `\r\n
\r\n
Drag Me A
\r\n
Drag Me B
\r\n
\r\n `;\r\n}\r\n...\r\n```\r\n\r\nWhere `omi-drag` modified:\r\n\r\n```js\r\n...\r\nvar handlerName = dom.getAttribute('dragMove');\r\n\r\nwindow.addEventListener('mousemove',function(evt){\r\n if(isMouseDown){\r\n currentX = evt.pageX;\r\n currentY = evt.pageY;\r\n if(preX != null){\r\n translateX += currentX - preX;\r\n translateY += currentY - preY;\r\n dom.style.transform = 'translateX('+translateX+'px) translateY('+translateY+'px)';\r\n }\r\n preX = currentX;\r\n preY = currentY;\r\n evt.preventDefault();\r\n instance[handlerName](evt);\r\n }\r\n},false);\r\n...\r\n```\r\n\r\n- We use `var handlerName = dom.getAttribute('dragMove')` to get the `dragMove` of dom\r\n- We use `instance[handlerName](evt)` to execute the method\r\n\r\nClick me for the live demo\r\n\r\n## More plugins\r\n\r\n* [omi-finger](https://github.com/AlloyTeam/omi/tree/master/plugins/omi-finger) The [AlloyFinger](https://github.com/AlloyTeam/AlloyFinger) plugin for Omi, which support touch events and gustures\r\n* [omi-transform](https://github.com/AlloyTeam/omi/tree/master/plugins/omi-transform) The [transformjs](http://alloyteam.github.io/AlloyTouch/transformjs/) plugin for Omi, which can easily set CSS3 Transform to DOM\r\n* [omi-touch](https://github.com/AlloyTeam/omi/tree/master/plugins/omi-touch) The [AlloyTouch](https://github.com/AlloyTeam/AlloyTouch) plugin for Omi. The touch movement solution for Omi (support touch scroll, rotate, flip, select, etc.)\r\n* [omi-jquery-date-picker](https://github.com/AlloyTeam/omi/tree/master/plugins/omi-jquery-date-picker) The date picker plugin for Omi, which support choose any time zone\r\n" - -/***/ }, -/* 36 */ -/***/ function(module, exports) { - - module.exports = "## Templates\r\n\r\nThere are three types of Omi. omi.js and omi.lite.js is for web side.\r\n\r\n- omi.js has a built-in [mustache.js](https://github.com/janl/mustache.js) as the template engine\r\n- omi.lite.js doesn't have any template engines\r\n\r\nOmi does not force developers to use mustache.js, you can use any template engine based on business scenarios or do not use any template engines.\r\n\r\nHow to use other template engines? Let's see the [artTemplate](https://github.com/aui/artTemplate) example.\r\n\r\n### Use artTemplate\r\n\r\n```js\r\nOmi.template = function(tpl, data){\r\n return artTemplate.compile(tpl)(data);\r\n}\r\n```\r\n\r\nWe need to rewrite the `Omi.template` method, the `tpl` is the incoming template, the `data` is the required data for the template, and the return value is HTML.\r\n\r\nAfter rewriting, you can use the artTemplate syntax in `render`, such as:\r\n\r\n```js\r\nclass List extends Omi.Component {\r\n constructor(data) {\r\n super(data);\r\n }\r\n\r\n style () {\r\n return `\r\n h1 { color:red; }\r\n li{ color:green;}\r\n `;\r\n }\r\n\r\n render () {\r\n return `

{{title}}

\r\n
    \r\n {{each list as value i}}\r\n
  • # {{i + 1}} :{{value}}
  • \r\n {{/each}}\r\n
`;\r\n }\r\n}\r\n```\r\n\r\n### Links\r\n\r\n* [Demo Link](http://alloyteam.github.io/omi/example/artTemplate/)\r\n* [Source Code](https://github.com/AlloyTeam/omi/tree/master/example/artTemplate)" - -/***/ }, -/* 37 */ -/***/ function(module, exports) { - - module.exports = "## Thinking in Omi\r\n\r\nOmi is based on object-oriented programming, with plugin system.\r\n\r\nThe traditional one-way data flow or the event-throwing component communicating can increase the stability of the system, but it loses it's flexibility. To a certain extent also reduced the component reusing.\r\n\r\nObject-oriented system has an other logical layer, which let you control the instance of components. The logic between instances build the entire program.\r\n\r\nThen the issues like communication, reusing and logics between components are all solved.\r\n\r\n\r\nPlus, the component is also more single duty, more loosely coupled.\r\n\r\nFor functional programming, imperative programming and object-oriented programming, we can sum up the following list:\r\n\r\n- Imperative programming is well understood, we use loop and if-else condition to control processes, it emphasize the process of execution\r\n- Imperative programming is hardware friendly, easy to run, but hard to design complex program\r\n- Functional programming is all about input and output, not the process of execution\r\n- Functional programming advocates multiple simple execution units into complex operations\r\n- Object-oriented programming uses objects as the basic unit of the program, with more reusability, flexibility, and extensibility\r\n\r\nWhat kind of language is JavaScript? We have `class` in ES6+, so is JavaScript object-oriented language?\r\n\r\nJavaScript can pass a function as a argumant, so is JavaScript a functional language?\r\n\r\nThere are no right answer, it depands on how you use JavaScript.\r\n\r\nIt's free to chooce, you can use functional programming framework like React, or object-oriented framework like Omi. \r\n\r\n### Functional Programming VS Object-Oriented Programming\r\n\r\nIn the UI component framework scope, functional programming is represented by React, while Omi belongs to object-oriented programming.\r\n\r\nSo what are their strengths and weaknesses? The following is a comparison (in fact, functional programming and object-oriented programming comparison):\r\n\r\n| | React | Omi |\r\n| ------------- |:-------------:|:-----:|\r\n| Component communication | ★★★★☆| ★★★★★ |\r\n| Stability | ★★★★★ | ★★★★☆ |\r\n| Flexibility | ★★★★☆| ★★★★★ |\r\n| Scalability | ★★★★☆ | ★★★★★ |\r\n| Testability | ★★★★★ | ★★★★☆ |\r\n| File size | ★★★☆☆ | ★★★★★ |\r\n| Features | ★★★☆☆ | ★★★★☆ |\r\n| DOM performance | ★★★★★ | ★★★★☆ |\r\n| Animation performance | ★★★★☆ | ★★★★★ |\r\n| Abstract complexity | ★★★★☆ | ★★★★★ |\r\n| Asynchronous programming | ★★★★★ | ★★★★☆ |\r\n\r\nAs we can see, we can not have it both ways. Object-oriented programming is more reusable, flexible and scalable, the problem is more difficult to test.\r\n\r\nSpecifically, if the functional programming, the test area is state1 + state2 + ... + stateN; in object-oriented programming, the test area is state1 × event1 + state2 × event2 + ... + stateN × eventN.\r\n\r\nIn summary, it is more recommended to use the object-oriented programming to build UI component framework.\r\n\r\n
\r\n\r\n### The end. Thanks for reading. [Let's start the Omi journey](https://github.com/AlloyTeam/omi)!\r\n" - -/***/ }, -/* 38 */ -/***/ function(module, exports, __webpack_require__) { - - 'use strict'; - - Object.defineProperty(exports, "__esModule", { - value: true - }); - - var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); - - var _omi = __webpack_require__(2); - - var _omi2 = _interopRequireDefault(_omi); - - var _index = __webpack_require__(39); - - var _index2 = _interopRequireDefault(_index); - - var _config = __webpack_require__(4); - - var _config2 = _interopRequireDefault(_config); - - function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - - function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } - - function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; } - - function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } - - _omi2.default.makeHTML('List', _index2.default); - - var Sidebar = function (_Omi$Component) { - _inherits(Sidebar, _Omi$Component); - - function Sidebar(data) { - _classCallCheck(this, Sidebar); - - return _possibleConstructorReturn(this, (Sidebar.__proto__ || Object.getPrototypeOf(Sidebar)).call(this, data)); - } - - _createClass(Sidebar, [{ - key: 'install', - value: function install() { - this.data.items = _config2.default['menus'][this.data.lan]; - this.data.height = window.innerHeight - 45; - } - }, { - key: 'style', - value: function style() { - return __webpack_require__(42); - } - }, { - key: 'render', - value: function render() { - return __webpack_require__(43); - } - }]); - - return Sidebar; - }(_omi2.default.Component); - - exports.default = Sidebar; - -/***/ }, -/* 39 */ -/***/ function(module, exports, __webpack_require__) { - - 'use strict'; - - Object.defineProperty(exports, "__esModule", { - value: true - }); - - var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); - - var _omi = __webpack_require__(2); - - var _omi2 = _interopRequireDefault(_omi); - - function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - - function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } - - function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; } - - function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } - - var tpl = __webpack_require__(40); - var css = __webpack_require__(41); - - var List = function (_Omi$Component) { - _inherits(List, _Omi$Component); - - function List(data) { - _classCallCheck(this, List); - - var _this = _possibleConstructorReturn(this, (List.__proto__ || Object.getPrototypeOf(List)).call(this, data)); - - _omi2.default.mixIndexToArray(_this.data.list); - _this.data.currentIndex = 0; - var self = _this; - _this.data.isCurrent = function () { - return this.index === self.data.currentIndex && self.data.active; - }; - return _this; - } - - _createClass(List, [{ - key: 'goto', - value: function goto(name, index) { - var _this2 = this; - - _omi2.default.get('content').data.name = name; - _omi2.default.get('content').update(); - this.data.currentIndex = index; - this.parent.children.forEach(function (child, index) { - child.data.active = false; - if (child.id === _this2.id) { - _omi2.default.get('pager').activeIndex = index; - child.data.active = true; - } - child.update(); - }); - _omi2.default.get('pager').currentIndex = index; - _omi2.default.get('pager').update(); - document.body.scrollTop = 0; - } - }, { - key: 'render', - value: function render() { - return tpl; - } - }, { - key: 'style', - value: function style() { - return css; - } - }]); - - return List; - }(_omi2.default.Component); - - exports.default = List; - -/***/ }, -/* 40 */ -/***/ function(module, exports) { - - module.exports = "" - -/***/ }, -/* 41 */ -/***/ function(module, exports) { - - module.exports = "li.title{ font-size: 16px; font-weight: bold; margin-bottom:10px; margin-top:10px; text-indent: 23px;}li{ margin-bottom:3px; text-indent: 33px;}li a{ display:block; font-size:14px; height:20px; line-height:20px; color: #666;}li a.current{ background-color:#c3d4fc; color:white;}li a:hover{ background-color:#b3d4fc; color:white;}" - -/***/ }, -/* 42 */ -/***/ function(module, exports) { - - module.exports = "@media only screen and (max-width: 768px) { .list{ transform: translateX(-100%); background-color:white; -moz-transition: all .6s ease; -o-transition: all .6s ease; -webkit-transition: all .6s ease; transition: all .6s ease; } .list.show { -moz-transform: translateX(0%) translateZ(0); -ms-transform: translateX(0%) translateZ(0); -o-transform: translateX(0%) translateZ(0); -webkit-transform: translateX(0%) translateZ(0); transform: translateX(0%) translateZ(0); }}.list{ width:200px; text-indent: 20px; border-right: 1px solid #eee; overflow-x: hidden; overflow-y: auto; position:fixed; top:45px;}.version{ height:20px;}" - -/***/ }, -/* 43 */ -/***/ function(module, exports) { - - module.exports = "
{{#items}} {{/items}}
" - -/***/ }, -/* 44 */ -/***/ function(module, exports, __webpack_require__) { - - 'use strict'; - - Object.defineProperty(exports, "__esModule", { - value: true - }); - - var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); - - var _omi = __webpack_require__(2); - - var _omi2 = _interopRequireDefault(_omi); - - var _omiFinger = __webpack_require__(45); - - var _omiFinger2 = _interopRequireDefault(_omiFinger); - - function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - - function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } - - function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; } - - function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } - - var tpl = __webpack_require__(47); - var css = __webpack_require__(48); - - _omiFinger2.default.init(); - - var Head = function (_Omi$Component) { - _inherits(Head, _Omi$Component); - - function Head(data) { - _classCallCheck(this, Head); - - return _possibleConstructorReturn(this, (Head.__proto__ || Object.getPrototypeOf(Head)).call(this, data)); - } - - _createClass(Head, [{ - key: 'install', - value: function install() { - var _this2 = this; - - this.data.isEnLan = this.data.lan === 'en'; - document.body.addEventListener('touchend', function () { - setTimeout(function () { - _this2.removeClass(_omi2.default.get('sidebar').node, 'show'); - }, 300); - }, false); - } - }, { - key: 'toggleMenus', - value: function toggleMenus(evt) { - this.toggleClass(_omi2.default.get('sidebar').node, 'show'); - evt.stopPropagation(); - } - }, { - key: 'handleTouchEnd', - value: function handleTouchEnd(evt) { - evt.stopPropagation(); - } - }, { - key: 'toggleClass', - value: function toggleClass(element, className) { - if (!element || !className) { - return; - } - - var classString = element.className, - nameIndex = classString.indexOf(className); - if (nameIndex == -1) { - classString += ' ' + className; - } else { - classString = classString.substr(0, nameIndex) + classString.substr(nameIndex + className.length); - } - element.className = classString; - } - }, { - key: 'removeClass', - value: function removeClass(element, className) { - var classString = element.className, - nameIndex = classString.indexOf(className); - if (nameIndex !== -1) { - classString = classString.substr(0, nameIndex) + classString.substr(nameIndex + className.length); - } - element.className = classString; - } - }, { - key: 'style', - value: function style() { - return css; - } - }, { - key: 'render', - value: function render() { - return tpl; - } - }]); - - return Head; - }(_omi2.default.Component); - - exports.default = Head; - -/***/ }, -/* 45 */ -/***/ function(module, exports, __webpack_require__) { - - /*! - * omi-finger v0.1.3 by dntzhang - * Omi / AlloyFinger integration. Support touch and gesture events in your Omi project. - * Github: https://github.com/AlloyTeam/omi - * MIT Licensed. - */ - - ;(function () { - - var OmiFinger = {}; - var AlloyFinger = true - ? __webpack_require__(46) - : window.AlloyFinger; - var Omi = true - ? __webpack_require__(2) - : window.Omi; - - var noop = function(){ - - }; - - var getHandler = function(name, dom, instance) { - var value = dom.getAttribute(name); - if (value === null) { - return noop; - }else{ - return instance[value].bind(instance); - } - }; - - - OmiFinger.init = function(){ - Omi.extendPlugin('omi-finger',function(dom, instance){ - if(!instance.alloyFingerInstances)instance.alloyFingerInstances = []; - var len = instance.alloyFingerInstances.length; - var i = 0 ; - for(;i 1) r = 1; - return Math.acos(r); - } - - function cross(v1, v2) { - return v1.x * v2.y - v2.x * v1.y; - } - - function getRotateAngle(v1, v2) { - var angle = getAngle(v1, v2); - if (cross(v1, v2) > 0) { - angle *= -1; - } - - return angle * 180 / Math.PI; - } - - var HandlerAdmin = function(el) { - this.handlers = []; - this.el = el; - }; - - HandlerAdmin.prototype.add = function(handler) { - this.handlers.push(handler); - } - - HandlerAdmin.prototype.del = function(handler) { - if(!handler) this.handlers = []; - - for(var i=this.handlers.length; i>=0; i--) { - if(this.handlers[i] === handler) { - this.handlers.splice(i, 1); - } - } - } - - HandlerAdmin.prototype.dispatch = function() { - for(var i=0,len=this.handlers.length; i 0 && this.delta <= 250 && Math.abs(this.preTapPosition.x - this.x1) < 30 && Math.abs(this.preTapPosition.y - this.y1) < 30); - } - this.preTapPosition.x = this.x1; - this.preTapPosition.y = this.y1; - this.last = this.now; - var preV = this.preV, - len = evt.touches.length; - if (len > 1) { - this._cancelLongTap(); - this._cancelSingleTap(); - var v = { x: evt.touches[1].pageX - this.x1, y: evt.touches[1].pageY - this.y1 }; - preV.x = v.x; - preV.y = v.y; - this.pinchStartLen = getLen(preV); - this.multipointStart.dispatch(evt); - } - this.longTapTimeout = setTimeout(function () { - this.longTap.dispatch(evt); - }.bind(this), 750); - }, - move: function (evt) { - if (!evt.touches) return; - var preV = this.preV, - len = evt.touches.length, - currentX = evt.touches[0].pageX, - currentY = evt.touches[0].pageY; - this.isDoubleTap = false; - if (len > 1) { - var v = { x: evt.touches[1].pageX - currentX, y: evt.touches[1].pageY - currentY }; - - if (preV.x !== null) { - if (this.pinchStartLen > 0) { - evt.scale = getLen(v) / this.pinchStartLen; - this.pinch.dispatch(evt); - } - - evt.angle = getRotateAngle(v, preV); - this.rotate.dispatch(evt); - } - preV.x = v.x; - preV.y = v.y; - } else { - if (this.x2 !== null) { - evt.deltaX = currentX - this.x2; - evt.deltaY = currentY - this.y2; - - } else { - evt.deltaX = 0; - evt.deltaY = 0; - } - this.pressMove.dispatch(evt); - } - - this.touchMove.dispatch(evt); - - this._cancelLongTap(); - this.x2 = currentX; - this.y2 = currentY; - if (len > 1) { - evt.preventDefault(); - } - }, - end: function (evt) { - if (!evt.changedTouches) return; - this._cancelLongTap(); - var self = this; - if (evt.touches.length < 2) { - this.multipointEnd.dispatch(evt); - } - this.touchEnd.dispatch(evt); - //swipe - if ((this.x2 && Math.abs(this.x1 - this.x2) > 30) || - (this.y2 && Math.abs(this.y1 - this.y2) > 30)) { - evt.direction = this._swipeDirection(this.x1, this.x2, this.y1, this.y2); - this.swipeTimeout = setTimeout(function () { - self.swipe.dispatch(evt); - - }, 0) - } else { - this.tapTimeout = setTimeout(function () { - self.tap.dispatch(evt); - // trigger double tap immediately - if (self.isDoubleTap) { - self.doubleTap.dispatch(evt); - clearTimeout(self.singleTapTimeout); - self.isDoubleTap = false; - } - }, 0) - - if (!self.isDoubleTap) { - self.singleTapTimeout = setTimeout(function () { - self.singleTap.dispatch(evt); - }, 250); - } - } - - this.preV.x = 0; - this.preV.y = 0; - this.scale = 1; - this.pinchStartLen = null; - this.x1 = this.x2 = this.y1 = this.y2 = null; - }, - cancel: function (evt) { - clearTimeout(this.singleTapTimeout); - clearTimeout(this.tapTimeout); - clearTimeout(this.longTapTimeout); - clearTimeout(this.swipeTimeout); - this.touchCancel.dispatch(evt); - }, - _cancelLongTap: function () { - clearTimeout(this.longTapTimeout); - }, - _cancelSingleTap: function () { - clearTimeout(this.singleTapTimeout); - }, - _swipeDirection: function (x1, x2, y1, y2) { - return Math.abs(x1 - x2) >= Math.abs(y1 - y2) ? (x1 - x2 > 0 ? 'Left' : 'Right') : (y1 - y2 > 0 ? 'Up' : 'Down') - }, - - on: function(evt, handler) { - if(this[evt]) { - this[evt].add(handler); - } - }, - - off: function(evt, handler) { - if(this[evt]) { - this[evt].del(handler); - } - }, - - destroy: function() { - if(this.singleTapTimeout) clearTimeout(this.singleTapTimeout); - if(this.tapTimeout) clearTimeout(this.tapTimeout); - if(this.longTapTimeout) clearTimeout(this.longTapTimeout); - if(this.swipeTimeout) clearTimeout(this.swipeTimeout); - - this.element.removeEventListener("touchstart", this.start); - this.element.removeEventListener("touchmove", this.move); - this.element.removeEventListener("touchend", this.end); - this.element.removeEventListener("touchcancel", this.cancel); - - this.rotate.del(); - this.touchStart.del(); - this.multipointStart.del(); - this.multipointEnd.del(); - this.pinch.del(); - this.swipe.del(); - this.tap.del(); - this.doubleTap.del(); - this.longTap.del(); - this.singleTap.del(); - this.pressMove.del(); - this.touchMove.del(); - this.touchEnd.del(); - this.touchCancel.del(); - - this.preV = this.pinchStartLen = this.scale = this.isDoubleTap = this.delta = this.last = this.now = this.tapTimeout = this.singleTapTimeout = this.longTapTimeout = this.swipeTimeout = this.x1 = this.x2 = this.y1 = this.y2 = this.preTapPosition = this.rotate = this.touchStart = this.multipointStart = this.multipointEnd = this.pinch = this.swipe = this.tap = this.doubleTap = this.longTap = this.singleTap = this.pressMove = this.touchMove = this.touchEnd = this.touchCancel = null; - - return null; - } - }; - - if (true) { - module.exports = AlloyFinger; - } else { - window.AlloyFinger = AlloyFinger; - } - })(); - - -/***/ }, -/* 47 */ -/***/ function(module, exports) { - - module.exports = "
\"\"
Omi
" - -/***/ }, -/* 48 */ -/***/ function(module, exports) { - - module.exports = ".head{ position:fixed; height:45px; line-height: 45px; border-bottom: 1px solid #eee; width:100%; background-color:#303030; z-index:100;}ul,li{ display: inline-block;}.logo_box{ width:100px; display: inline-block; text-align:center; line-height: 60px;}.menu a,.logo_box a{ display: inline-block; height:45px; color:#ddd;}.menu{ position: absolute; right:20px;}.menu li{ margin-left:15px;}.logo_box a{ font-size: 34px; font-weight: bold; color: #00bff3; padding: 0px 15px; line-height: 45px; cursor: pointer;}.menu a:hover{ color: white;}.m_menu{ position:fixed; display:none;}@media only screen and (max-width: 768px) { .menu li{ display:none; } .menu .m_show{ display:block; } .logo_box{ display:inline-block; } .head{ text-align:center; } .m_menu{ top:0; left:0; display:block; width:50px; height:50px; padding-top: 6px; } .m_menu img{ width:30px; }}" - -/***/ }, -/* 49 */ -/***/ function(module, exports, __webpack_require__) { - - 'use strict'; - - Object.defineProperty(exports, "__esModule", { - value: true - }); - - var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); - - var _omi = __webpack_require__(2); - - var _omi2 = _interopRequireDefault(_omi); - - var _config = __webpack_require__(4); - - var _config2 = _interopRequireDefault(_config); - - var _omiFinger = __webpack_require__(45); - - var _omiFinger2 = _interopRequireDefault(_omiFinger); - - function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - - function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } - - function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; } - - function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } - - _omiFinger2.default.init(); - - var Pager = function (_Omi$Component) { - _inherits(Pager, _Omi$Component); - - function Pager(data) { - _classCallCheck(this, Pager); - - var _this = _possibleConstructorReturn(this, (Pager.__proto__ || Object.getPrototypeOf(Pager)).call(this, data)); - - _this.activeIndex = 0; - _this.currentIndex = 0; - return _this; - } - - _createClass(Pager, [{ - key: 'updatePager', - value: function updatePager() { - this.data.preMd = null; - this.data.preName = null; - this.data.nextMd = null; - this.data.nextName = null; - var item = _config2.default.menus[this.data.lan][this.activeIndex]; - - var pre = item.list[this.currentIndex - 1]; - if (pre) { - this.data.preMd = pre.md; - this.data.preName = pre.name; - } - var next = item.list[this.currentIndex + 1]; - if (next) { - this.data.nextMd = next.md; - this.data.nextName = next.name; - } - } - }, { - key: 'goto', - value: function goto(name, dir) { - var sidebar = _omi2.default.get('sidebar'); - if (dir === 'next') { - sidebar.children[this.activeIndex].goto(name, ++this.currentIndex); - } else { - sidebar.children[this.activeIndex].goto(name, --this.currentIndex); - } - this.update(); - } - }, { - key: 'handleTap', - value: function handleTap(evt) { - var dir = evt.target.getAttribute('data-dir'); - var name = evt.target.getAttribute('data-name'); - this.goto(name, dir); - } - }, { - key: 'isMobile', - value: function isMobile() { - var browser = { - versions: function () { - var u = navigator.userAgent, - app = navigator.appVersion; - return { //移动终端浏览器版本信息 - trident: u.indexOf('Trident') > -1, //IE内核 - presto: u.indexOf('Presto') > -1, //opera内核 - webKit: u.indexOf('AppleWebKit') > -1, //苹果、谷歌内核 - gecko: u.indexOf('Gecko') > -1 && u.indexOf('KHTML') == -1, //火狐内核 - mobile: !!u.match(/AppleWebKit.*Mobile.*/), //是否为移动终端 - ios: !!u.match(/\(i[^;]+;( U;)? CPU.+Mac OS X/), //ios终端 - android: u.indexOf('Android') > -1 || u.indexOf('Linux') > -1, //android终端或者uc浏览器 - iPhone: u.indexOf('iPhone') > -1, //是否为iPhone或者QQHD浏览器 - iPad: u.indexOf('iPad') > -1, //是否iPad - webApp: u.indexOf('Safari') == -1 //是否web应该程序,没有头部与底部 - }; - }(), - language: (navigator.browserLanguage || navigator.language).toLowerCase() - }; - - if (browser.versions.mobile || browser.versions.ios || browser.versions.android || browser.versions.iPhone || browser.versions.iPad) { - return true; - } - return false; - } - }, { - key: 'render', - value: function render() { - this.updatePager(); - if (this.isMobile()) { - return '\n
\n {{#preName}} \u2190{{preName}}{{/preName}}\n {{#nextName}} {{/nextName}}\n
'; - } else { - return '\n
\n {{#preName}} \u2190{{preName}}{{/preName}}\n {{#nextName}} {{/nextName}}\n
'; - } - } - }, { - key: 'style', - value: function style() { - return __webpack_require__(50); - } - }]); - - return Pager; - }(_omi2.default.Component); - - exports.default = Pager; - -/***/ }, -/* 50 */ -/***/ function(module, exports) { - - module.exports = ".pager { width:85%; height:80px; line-height:80px; position: relative; font-size:16px;}@media only screen and (max-width: 768px) { .pager { width:100%; }}.pre{ position: absolute; left:10px; top:10px;}.next{ position: absolute; right:10px; top:10px;}" - -/***/ } -]); \ No newline at end of file diff --git a/website/js/docs-en.b820c139.js b/website/js/docs-en.b820c139.js deleted file mode 100644 index c34d95a5b..000000000 --- a/website/js/docs-en.b820c139.js +++ /dev/null @@ -1,1401 +0,0 @@ -window.Root ={}; Root.isDev = false;webpackJsonp([1],[ -/* 0 */ -/***/ function(module, exports, __webpack_require__) { - - 'use strict'; - - var _frame = __webpack_require__(1); - - var _frame2 = _interopRequireDefault(_frame); - - function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - - Omi.render(new _frame2.default({ lan: 'en' }), 'body', true); - -/***/ }, -/* 1 */ -/***/ function(module, exports, __webpack_require__) { - - 'use strict'; - - Object.defineProperty(exports, "__esModule", { - value: true - }); - - var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); - - var _omi = __webpack_require__(2); - - var _omi2 = _interopRequireDefault(_omi); - - var _index = __webpack_require__(3); - - var _index2 = _interopRequireDefault(_index); - - var _index3 = __webpack_require__(38); - - var _index4 = _interopRequireDefault(_index3); - - var _index5 = __webpack_require__(44); - - var _index6 = _interopRequireDefault(_index5); - - var _config = __webpack_require__(4); - - var _config2 = _interopRequireDefault(_config); - - var _index7 = __webpack_require__(49); - - var _index8 = _interopRequireDefault(_index7); - - function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - - function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } - - function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; } - - function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } - - _omi2.default.makeHTML('Content', _index2.default); - _omi2.default.makeHTML('Sidebar', _index4.default); - _omi2.default.makeHTML('Head', _index6.default); - _omi2.default.makeHTML('Pager', _index8.default); - - var Frame = function (_Omi$Component) { - _inherits(Frame, _Omi$Component); - - function Frame(data) { - _classCallCheck(this, Frame); - - return _possibleConstructorReturn(this, (Frame.__proto__ || Object.getPrototypeOf(Frame)).call(this, data)); - } - - _createClass(Frame, [{ - key: 'install', - value: function install() { - var _this2 = this; - - this.setViewport(); - window.onresize = function () { - if (window.innerWidth < 768) { - _this2.refs.main.style.width = '100%'; - } else { - _this2.refs.main.style.width = window.innerWidth - 220 + 'px'; - } - }; - } - }, { - key: 'setViewport', - value: function setViewport() { - if (window.innerWidth < 768) { - this.data.width = '100%'; - } else { - this.data.width = window.innerWidth - 220 + 'px'; - } - } - }, { - key: 'style', - value: function style() { - return '\n \n '; - } - }, { - key: 'render', - value: function render() { - return '
\n \n
\n \n \n
\n \n
'; - } - }]); - - return Frame; - }(_omi2.default.Component); - - exports.default = Frame; - -/***/ }, -/* 2 */, -/* 3 */ -/***/ function(module, exports, __webpack_require__) { - - 'use strict'; - - Object.defineProperty(exports, "__esModule", { - value: true - }); - - var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); - - var _omi = __webpack_require__(2); - - var _omi2 = _interopRequireDefault(_omi); - - var _config = __webpack_require__(4); - - var _config2 = _interopRequireDefault(_config); - - var _highlightLines = __webpack_require__(5); - - var _highlightLines2 = _interopRequireDefault(_highlightLines); - - function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - - function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } - - function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; } - - function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } - - var tpl = __webpack_require__(6); - var css = __webpack_require__(7); - - var Content = function (_Omi$Component) { - _inherits(Content, _Omi$Component); - - function Content(data) { - _classCallCheck(this, Content); - - data = Object.assign({ - lan: 'cn', - name: 'installation' - }, data); - - var _this = _possibleConstructorReturn(this, (Content.__proto__ || Object.getPrototypeOf(Content)).call(this, data)); - - _this.md = new Remarkable({ html: true }); - return _this; - } - - _createClass(Content, [{ - key: 'getMarkDown', - value: function getMarkDown(name, lan) { - return __webpack_require__(8)("./" + lan + "/" + name + ".md"); - } - }, { - key: 'installed', - value: function installed() { - this.initCodeStyle(); - } - }, { - key: 'afterUpdate', - value: function afterUpdate() { - this.initCodeStyle(); - } - }, { - key: 'initCodeStyle', - value: function initCodeStyle() { - var _this2 = this; - - var codes = _omi2.default.$$("code"); - var codeHlNumArr = []; - codes.forEach(function (code) { - hljs.highlightBlock(code); - var arr = code.className.match(/{\S*}/); - var hllNums = null; - if (arr) { - var numArr = arr[0].replace(/[{|}]/g, '').split(','); - hllNums = _this2._arrToNumber(numArr); - } - codeHlNumArr.push(hllNums); - }); - - (0, _highlightLines2.default)(); - - codes.forEach(function (code, index) { - _this2._hll(code, codeHlNumArr[index]); - }); - } - }, { - key: '_arrToNumber', - value: function _arrToNumber(numArr) { - var arr = []; - numArr.forEach(function (item) { - if (item.indexOf('-') !== -1) { - var tempArr = item.split('-'); - var begin = Number(tempArr[0]); - var end = Number(tempArr[1]); - for (var i = begin; i < end + 1; i++) { - arr.push(i); - } - } else { - arr.push(Number(item)); - } - }); - return arr; - } - }, { - key: '_hll', - value: function _hll(code, hllNums) { - var spans = _omi2.default.$$('.line', code); - hllNums && hllNums.forEach(function (num) { - spans[num] && spans[num].classList.add('highlight'); - }); - } - }, { - key: 'render', - value: function render() { - this.data.html = this.md.render(this.getMarkDown(this.data.name, this.data.lan)); - return tpl; - } - }, { - key: 'style', - value: function style() { - return css; - } - }]); - - return Content; - }(_omi2.default.Component); - - exports.default = Content; - -/***/ }, -/* 4 */ -/***/ function(module, exports) { - - 'use strict'; - - Object.defineProperty(exports, "__esModule", { - value: true - }); - var config = { - menus: { - cn: [{ - active: true, - title: '快速开始', - currentIndex: 0, - list: [{ 'name': '安装', md: 'installation' }, { 'name': 'Hello World', md: 'hello_world' }, { 'name': '组件', md: 'components' }, { 'name': '组件通讯', md: 'communication' }, { 'name': '生命周期', md: 'lifecycle' }, { 'name': '事件处理', md: 'events' }, { 'name': '条件判断', md: 'condition' }, { 'name': '循环遍历', md: 'loop' }, { 'name': 'Store体系', md: 'store' }, { 'name': '表单', md: 'form' }, { 'name': '继承', md: 'inherit' }, { 'name': '模板切换', md: 'template' }, { 'name': '获取DOM节点', md: 'get_dom' }, { 'name': '插件体系', md: 'plugin' }, { 'name': 'Omi的理念', md: 'thinking_in_omi' }] - }], - en: [{ - title: 'QUICK START', - active: true, - currentIndex: 0, - list: [{ 'name': 'Installation', md: 'installation' }, { 'name': 'Hello World', md: 'hello_world' }, { 'name': 'Components', md: 'components' }, { 'name': 'Communication', md: 'communication' }, { 'name': 'Lifecycle', md: 'lifecycle' }, { 'name': 'Handling Events', md: 'events' }, { 'name': 'Conditional Rendering', md: 'condition' }, { 'name': 'Loop', md: 'loop' }, { 'name': 'Forms', md: 'form' }, { 'name': 'Inheritance', md: 'inherit' }, { 'name': 'Templates', md: 'template' }, { 'name': 'Get DOM', md: 'get_dom' }, { 'name': 'Plugin', md: 'plugin' }, { 'name': 'Thinking in Omi', md: 'thinking_in_omi' }] - }] - } - }; - - exports.default = config; - -/***/ }, -/* 5 */ -/***/ function(module, exports) { - - 'use strict'; - - Object.defineProperty(exports, "__esModule", { - value: true - }); - - // Iterates through `array`, running `callback` for each `array` element. - function forEach(array, callback) { - var i = -1, - length = array ? array.length : 0; - while (++i < length) { - callback(array[i]); - } - } - - function indexOf(array, elem) { - var i = -1, - length = array ? array.length : 0; - while (++i < length) { - if (array[i] === elem) { - return i; - } - } - } - function highlightLines() { - // TODO: mark as parsed. - forEach(document.querySelectorAll('pre code'), function (element) { - // Trim whitespace if the `data-trim` attribute is present. - if (element.hasAttribute('data-trim') && typeof element.innerHTML.trim == 'function') { - element.innerHTML = element.innerHTML.trim(); - } - - // Highlight code using highlight.js. - hljs.highlightBlock(element); - - // Split highlighted code into lines. - var openTags = [], - reHtmlTag = /<(\/?)span(?:\s+(?:class=(['"])hljs-.*?\2)?\s*|\s*)>/g; - element.innerHTML = element.innerHTML.replace(/(.*?)\r?\n/g, function (_, string) { - if (!string) { - return ' '; - } - var openTag, stringPrepend; - // Re-open all tags that were previously closed. - if (openTags.length) { - stringPrepend = openTags.join(''); - } - // Match all HTML `` tags. - reHtmlTag.lastIndex = 0; - while (openTag = reHtmlTag.exec(string)) { - // If it is a closing tag, remove the opening tag from the list. - if (openTag[1]) { - openTags.pop(); - } - // Otherwise if it is an opening tag, push it to the list. - else { - openTags.push(openTag[0]); - } - } - // Close all opened tags, so that strings can be wrapped with `span.line`. - if (openTags.length) { - string += Array(openTags.length + 1).join(''); - } - if (stringPrepend) { - string = stringPrepend + string; - } - return '' + string + ''; - }); - }); - } - - exports.default = highlightLines; - -/***/ }, -/* 6 */ -/***/ function(module, exports) { - - module.exports = "
{{{html}}}
" - -/***/ }, -/* 7 */ -/***/ function(module, exports) { - - module.exports = ".content{ width: 80%;}h3{ color:#444444;}pre{ border: 1px solid #eee; width: 100%;}li{ text-indent: 20px; list-style:disc inside ;}@media only screen and (max-width: 768px) { .content{ width: 100%; }}" - -/***/ }, -/* 8 */ -/***/ function(module, exports, __webpack_require__) { - - var map = { - "./cn/communication.md": 9, - "./cn/components.md": 10, - "./cn/condition.md": 11, - "./cn/events.md": 12, - "./cn/form.md": 13, - "./cn/get_dom.md": 14, - "./cn/hello_world.md": 15, - "./cn/inherit.md": 16, - "./cn/installation.md": 17, - "./cn/lifecycle.md": 18, - "./cn/loop.md": 19, - "./cn/plugin.md": 20, - "./cn/store.md": 21, - "./cn/template.md": 22, - "./cn/thinking_in_omi.md": 23, - "./en/communication.md": 24, - "./en/components.md": 25, - "./en/condition.md": 26, - "./en/events.md": 27, - "./en/form.md": 28, - "./en/get_dom.md": 29, - "./en/hello_world.md": 30, - "./en/inherit.md": 31, - "./en/installation.md": 32, - "./en/lifecycle.md": 33, - "./en/loop.md": 34, - "./en/plugin.md": 35, - "./en/template.md": 36, - "./en/thinking_in_omi.md": 37 - }; - function webpackContext(req) { - return __webpack_require__(webpackContextResolve(req)); - }; - function webpackContextResolve(req) { - return map[req] || (function() { throw new Error("Cannot find module '" + req + "'.") }()); - }; - webpackContext.keys = function webpackContextKeys() { - return Object.keys(map); - }; - webpackContext.resolve = webpackContextResolve; - module.exports = webpackContext; - webpackContext.id = 8; - - -/***/ }, -/* 9 */ -/***/ function(module, exports) { - - module.exports = "## 组件通讯\r\n\r\n[Omi框架](https://github.com/AlloyTeam/omi)组建间的通讯非常遍历灵活,因为有许多可选方案进行通讯:\r\n\r\n* 通过在组件上声明 data-* 传递给子节点 \r\n* 通过在组件上声明 data 传递给子节点 (支持复杂数据类型的映射)\r\n* 父容器设置 childrenData 自动传递给子节点\r\n* 声明 group-data 传递(支持复杂数据类型的映射)\r\n* 完全面向对象,可以非常容易地拿到对象的实例,之后可以设置实例属性和调用实例的方法\r\n\r\n所以通讯变得畅通无阻,下面一一来举例说明。\r\n\r\n### data-*通讯 \r\n\r\n```js {36}\r\nclass Hello extends Omi.Component {\r\n constructor(data) {\r\n super(data);\r\n }\r\n \r\n style () {\r\n return `\r\n h1{\r\n \tcursor:pointer;\r\n }\r\n `;\r\n }\r\n \r\n handleClick(target, evt){\r\n alert(target.innerHTML);\r\n }\r\n \r\n render() {\r\n return `\r\n
\r\n \t

Hello ,{{name}}!

\r\n
\r\n \t\t`;\r\n }\r\n}\r\n\r\nOmi.makeHTML('Hello', Hello);\r\n\r\nclass App extends Omi.Component {\r\n constructor(data) {\r\n super(data);\r\n }\r\n \r\n render() {\r\n return `\r\n
\r\n \r\n
\r\n `;\r\n }\r\n}\r\n\r\nOmi.render(new App(),\"#container\");\r\n```\r\n\r\n一般data-*用来传递值类型,如string、number。值得注意的是,通过data-*接收到的数据类型都是string,需要自行转成number类型。\r\n通常情况下,data-*能满足我们的要求,但是遇到复杂的数据类型是没有办法通过大量data-*去表达,所以可以通过data通讯,请往下看。\r\n\r\n### data通讯 \r\n\r\n如上面代码所示,通过 data-name=\"Omi\"可以把name传递给子组件。下面的代码也可以达到同样的效果。\r\n\r\n```js {4,10}\r\n...\r\nclass App extends Omi.Component {\r\n constructor(data) {\r\n super(data);\r\n this.helloData = { name : 'Omi' };\r\n }\r\n \r\n render() {\r\n return `\r\n
\r\n \r\n
\r\n `;\r\n }\r\n}\r\n\r\nOmi.render(new App(),\"#container\");\r\n```\r\n\r\n使用data声明,会去组件的instance(也就是this)下找对应的属性,this下可以挂载任意复杂的对象。所以这也就突破了data-*的局限性。\r\n\r\n如果instance下面的某个属性下面的某个属性下面的某个数组的第一个元素的某个属性要作为data传递Hello怎么办?\r\n没关系,data声明是支持复杂类型的,使用方式如下:\r\n\r\n```js\r\n...\r\nclass App extends Omi.Component {\r\n constructor(data) {\r\n super(data);\r\n this.complexData ={\r\n a:{\r\n b:{\r\n c:[\r\n {\r\n e:[{\r\n name:'ComplexData Support1'\r\n },{\r\n name:'ComplexData Support2'\r\n }]\r\n },\r\n {\r\n name: 'ComplexData Support3'\r\n }\r\n ]\r\n }\r\n }\r\n };\r\n }\r\n \r\n render() {\r\n return `\r\n
\r\n \r\n
\r\n `;\r\n }\r\n}\r\n...\r\n```\r\n\r\n点击这里→data映射复杂数据\r\n\r\n### childrenData通讯\r\n\r\n```js\r\n...\r\nclass App extends Omi.Component {\r\n constructor(data) {\r\n super(data);\r\n this.childrenData = [{ name : 'Omi' } , { name : 'dntzhang' }];\r\n }\r\n \r\n render() {\r\n return `\r\n
\r\n \r\n \r\n
\r\n `;\r\n }\r\n}\r\n\r\nOmi.render(new App(),\"#container\");\r\n```\r\n\r\n使用this.childrenData传递data给子组件,childrenData是一个数组类型,所以支持同时给多个组件传递data,与render里面的组件会一一对应上。\r\n\r\n### group-data通讯\r\n\r\nchildrenData的方式可以批量传递数据给组件,但是有很多场景下data的来源不一定非要都从childrenData来,childrenData是个数组,会和组件的顺序一一对应,这就给不同传递方式的data必须全部集中的childrenData中,非常不方便。group-data专门为解决上面的痛点而生,专门是为了给一组组件批量传递data。\r\n\r\n```js\r\nimport Hello from './hello.js';\r\n\r\n\r\nOmi.makeHTML('Hello', Hello);\r\n\r\nclass App extends Omi.Component {\r\n constructor(data) {\r\n super(data);\r\n this.testData = [{name: 'Omi'}, {name: 'dntzhang'}, {name: 'AlloyTeam'}];\r\n }\r\n\r\n render() {\r\n return `\r\n
\r\n \r\n \r\n \r\n
\r\n `;\r\n\r\n }\r\n}\r\n\r\nOmi.render(new App(),\"#container\");\r\n```\r\n\r\n只需要在声明的子组件上标记group-data,就会去当前组件的instance(也就是this)下面找对应的属性,然后根据当前的位置,和对应数组的位置会一一对应起来。\r\n\r\n运行结果如下:\r\n![](http://images2015.cnblogs.com/blog/105416/201702/105416-20170216110701535-1698390390.png)\r\n\r\n点击这里→group-data\r\n\r\n同样group-data支持复杂数据类型的映射,需要注意的是,group-data映射的终点必须是一个数组:\r\n\r\n```js\r\nimport Hello from './hello.js';\r\n\r\n\r\nOmi.makeHTML('Hello', Hello);\r\n\r\nclass App extends Omi.Component {\r\n constructor(data) {\r\n super(data);\r\n this.complexData ={\r\n a:{\r\n b:{\r\n c:[\r\n {\r\n e:[{\r\n name:'ComplexData Support1'\r\n },{\r\n name:'ComplexData Support2'\r\n }]\r\n },\r\n {\r\n name: 'ComplexData Support3'\r\n }\r\n ]\r\n }\r\n }\r\n };\r\n }\r\n\r\n render() {\r\n return `\r\n
\r\n \r\n \r\n
\r\n `;\r\n\r\n }\r\n}\r\n\r\nOmi.render(new App(),\"#container\");\r\n```\r\n\r\n点击这里→group-data映射复杂数据\r\n\r\n### 通过对象实例\r\n\r\n```js {7}\r\n...\r\nclass App extends Omi.Component {\r\n constructor(data) {\r\n super(data);\r\n }\r\n \r\n installed(){\r\n this.hello.data.name = \"Omi\";\r\n this.update()\r\n }\r\n \r\n render() {\r\n return `\r\n
\r\n \r\n
\r\n `;\r\n }\r\n}\r\n\r\nOmi.render(new App(),\"#container\");\r\n```\r\n\r\n### 通过omi-id\r\n\r\n```js {7,14}\r\n...\r\nclass App extends Omi.Component {\r\n constructor(data) {\r\n super(data);\r\n }\r\n \r\n installed(){\r\n Omi.get(\"hello\").data.name = \"Omi\";\r\n this.update()\r\n }\r\n \r\n render() {\r\n return `\r\n
\r\n \r\n
\r\n `;\r\n }\r\n}\r\n\r\nOmi.render(new App(),\"#container\");\r\n```\r\n\r\n通过在组件上声明omi-id,在程序任何地方拿到该对象的实例。这个可以算是跨任意组件通讯神器。\r\n\r\n### 特别强调\r\n\r\n* 通过childrenData或者data方式通讯都是一锤子买卖。后续变更只能通过组件实例下的data属性去更新组件\r\n* 通过data-✼通讯也是一锤子买卖。后续变更只能通过组件实例下的data属性去更新组件。\r\n* 关于data-✼通讯也可以不是一锤子买卖,但是要设置组件实例的dataFirst为false,这样的话data-✼就会覆盖组件实例的data对应的属性\r\n\r\n关于上面的第三条也就是这样的逻辑伪代码:\r\n```js\r\nif(this.dataFirst){\r\n this.data = Object.assign({},data-✼ ,this.data);\r\n}else{\r\n this.data = Object.assign({},this.data, data-✼);\r\n}\r\n```" - -/***/ }, -/* 10 */ -/***/ function(module, exports) { - - module.exports = "## 组件\r\n\r\n[Omi框架](https://github.com/AlloyTeam/omi)完全基于组件体系设计,我们希望开发者可以像搭积木一样制作Web程序,一切皆是组件,组件也可以嵌套子组件形成新的组件,新的组件又可以当作子组件嵌套至任意组件形成新的组件...\r\n\r\n![](http://images2015.cnblogs.com/blog/105416/201702/105416-20170210093427338-1536910080.png)\r\n\r\n## 简单组件\r\n\r\n这里使用Todo的例子来讲解Omi组件体系的使用。\r\n\r\n```js\r\nclass Todo extends Omi.Component {\r\n constructor(data) {\r\n super(data);\r\n }\r\n \r\n add (evt) {\r\n evt.preventDefault();\r\n this.data.items.push(this.data.text);\r\n this.data.text = '';\r\n this.update();\r\n }\r\n\r\n style () {\r\n return `\r\n h3 { color:red; }\r\n button{ color:green;}\r\n `;\r\n }\r\n\r\n handleChange(target){\r\n this.data.text = target.value;\r\n }\r\n\r\n render () {\r\n return `
\r\n

TODO

\r\n
    {{#items}}
  • {{.}}
  • {{/items}}
\r\n
\r\n \r\n \r\n
\r\n
`;\r\n }\r\n}\r\n\r\nOmi.render(new Todo({ items: [] ,text : '' }),\"body\");\r\n```\r\n\r\n组件生成的HTML最终会插入到body中。上面的例子展示了Omi的部分特性:\r\n\r\n- data传递: new Todo(data,..)的data可以直接提供给render方法里的模板\r\n- 局部CSS: h3只对render里的h3生效,不会污染外面的h3;button也是同样的\r\n- 声明式事件绑定: onchange调用的就是组件内的handleChange,this可以拿到当然的DOM元素,还可以拿到当前的event\r\n- 需要手动调用update方法才能更新组件\r\n\r\n这里需要特别强调的是,为了更加的自由和灵活度。Omi没有内置数据变更的自动更新,需要开发者自己调用update方法。\r\n\r\n点击这里→在线试试\r\n\r\n## 组件嵌套\r\n\r\n如果页面超级简单的话,可以没有组件嵌套。但是绝大部分Web网页或者Web应用,需要嵌套定义的组件来完成所有的功能和展示。比如上面的Todo,我们也是可以抽取出List。\r\n这样让程序易维护、可扩展、方便复用。如,我们抽取出List:\r\n\r\n```js\r\nclass List extends Omi.Component {\r\n constructor(data) {\r\n super(data);\r\n }\r\n\r\n render () {\r\n return `
    {{#items}}
  • {{.}}
  • {{/items}}
`;\r\n }\r\n}\r\n```\r\n\r\n怎么使用这个List?我们需要使用Omi.makeHTML把List制作成可以声明式的标签,在render方法中就能直接使用该标签。如下所示:\r\n\r\n```js\r\nimport List from './list.js';\r\n\r\nOmi.makeHTML('List', List);\r\n\r\nclass Todo extends Omi.Component {\r\n constructor(data) {\r\n super(data);\r\n this.data.length = this.data.items.length;\r\n this.listData = { items : this.data.items };\r\n }\r\n\r\n add (evt) {\r\n evt.preventDefault();\r\n this.list.data.items.push(this.data.text);\r\n this.data.length = this.list.data.items.length;\r\n this.data.text = '';\r\n this.update();\r\n }\r\n\r\n style () {\r\n return `\r\n h3 { color:red; }\r\n button{ color:green;}\r\n `;\r\n }\r\n\r\n handleChange(target){\r\n this.data.text = target.value;\r\n }\r\n\r\n render () {\r\n return `
\r\n

TODO

\r\n \r\n
\r\n \r\n \r\n
\r\n
`;\r\n }\r\n}\r\n```\r\n\r\n* 第3行,通过makeHTML方法把组件制作成可以在render中使用的标签。当然Omi.makeHTML('List', List);也可以写在List组件的代码下面。\r\n* 第9行,在父组件上定义listData属性用来传递给子组件。\r\n* 第34行,在render方法中使用List组件。其中name方法可以让你在代码里通过this快速方法到该组件的实例。data=\"listData\"可以让你把this.listData传递给子组件。\r\n\r\n需要注意的是,父组件的this.listData会被通过Object.assign浅拷贝到子组件。\r\n这样做的目的主要是希望以后DOM的变更都尽量修改子组件自身的data,然后再调用其update方法,而不是去更改父组件的listData。\r\n\r\n关于Omi组件通讯其实有4种方案,这个后续教程会专门来讲。\r\n\r\n点击这里→在线试试\r\n" - -/***/ }, -/* 11 */ -/***/ function(module, exports) { - - module.exports = "## 条件判断\r\n\r\n我们经常需要根据不同的状态呈现不同的界面,比如有的用户是vip要显示vip的Logo。Omi有许多种方式满足你的要求。\r\n\r\n### 方式一\r\n\r\n```js\r\nclass ConditionTest extends Omi.Component {\r\n constructor(data) {\r\n super(data);\r\n }\r\n\r\n render () {\r\n return `{{#isVip}}\r\n
you are VIP.
\r\n {{/isVip}}\r\n {{^isVip}}\r\n
you are not VIP.
\r\n {{/isVip}}`;\r\n }\r\n}\r\n```\r\n\r\n上面完全使用mustachejs的条件判断的语法。当然Omi不强制你使用mustachejs。你可以是omi.lite.js,然后重写Omi.template方法去使用任意你喜爱的模板引擎。\r\n\r\n### 方式二\r\n\r\n```js\r\nclass ConditionTest extends Omi.Component {\r\n constructor(data) {\r\n super(data);\r\n }\r\n\r\n render () {\r\n if(this.data.isVip){\r\n return '
you are VIP.
';\r\n }else{\r\n return '
you are not VIP.
';\r\n }\r\n }\r\n}\r\n```\r\n\r\nrender就是提供了很好的可编程性,里面可以写任意js逻辑代码。对了,差点忘了,style方法里面也可以写js逻辑的。\r\n\r\n```js\r\nclass ConditionTest extends Omi.Component {\r\n constructor(data) {\r\n super(data);\r\n }\r\n\r\n style (){\r\n if(this.data.isVip){\r\n return 'div{ color : red; }';\r\n }else{\r\n return 'div{ color : green; }';\r\n }\r\n }\r\n\r\n render () {\r\n if(this.data.isVip){\r\n return '
you are VIP.
';\r\n }else{\r\n return '
you are not VIP.
';\r\n }\r\n }\r\n}\r\n```\r\n\r\n### 方式三\r\n\r\n```js\r\nclass ConditionTest extends Omi.Component {\r\n constructor(data) {\r\n super(data);\r\n }\r\n\r\n render() {\r\n return `\r\n ${this.data.isVip\r\n ?\"
you are VIP.
\"\r\n :\"
you are not VIP.
\"\r\n \t\t}\r\n `;\r\n }\r\n}\r\n```\r\n\r\n当然可以使用${ }里面写javascript代码进行输出。" - -/***/ }, -/* 12 */ -/***/ function(module, exports) { - - module.exports = "## 事件处理\r\n\r\nOmi的事件分内置事件和自定义事件。在内置事件处理方面巧妙地利用了浏览器自身的管线机制,可以通过event和this轻松拿到事件实例和触发该事件的元素。\r\n\r\n### 内置事件\r\n\r\n什么算内置事件?只要下面正则能匹配到就算内置事件。\r\n\r\n```js\r\non(abort|blur|cancel|canplay|canplaythrough|change|click|close|contextmenu|cuechange|dblclick|drag|dragend|dragenter|dragleave|dragover|dragstart|drop|durationchange|emptied|ended|error|focus|input|invalid|keydown|keypress|keyup|load|loadeddata|loadedmetadata|loadstart|mousedown|mouseenter|mouseleave|mousemove|mouseout|mouseover|mouseup|mousewheel|pause|play|playing|progress|ratechange|reset|resize|scroll|seeked|seeking|select|show|stalled|submit|suspend|timeupdate|toggle|volumechange|waiting|autocomplete|autocompleteerror|beforecopy|beforecut|beforepaste|copy|cut|paste|search|selectstart|wheel|webkitfullscreenchange|webkitfullscreenerror|touchstart|touchmove|touchend|touchcancel|pointerdown|pointerup|pointercancel|pointermove|pointerover|pointerout|pointerenter|pointerleave)\r\n```\r\n\r\n内置事件怎么绑定?如下所示:\r\n\r\n```js\r\nclass EventTest extends Omi.Component {\r\n constructor(data) {\r\n super(data);\r\n }\r\n\r\n handleClick(dom, evt){\r\n alert(dom.innerHTML);\r\n }\r\n\r\n render () {\r\n return `
Hello, Omi!
`;\r\n }\r\n}\r\n```\r\n\r\n### 自定义事件\r\n\r\n开发者自己定义的组件的事件,称为自定义事件,自定义事件必须以on开头,即onXXXX的格式,不然Omi识别不到。这里拿分页作为例子:\r\n\r\n```js\r\nimport Omi from '../../src/index.js';\r\nimport Pagination from './pagination.js';\r\nimport Content from './content.js';\r\n\r\nOmi.makeHTML('Pagination', Pagination);\r\nOmi.makeHTML('Content', Content);\r\n\r\nclass Main extends Omi.Component {\r\n constructor(data) {\r\n super(data);\r\n }\r\n\r\n installed(){\r\n this.content.goto(this.pagination.data.currentPage+1);\r\n }\r\n \r\n handlePageChange(index){\r\n this.content.goto(index+1);\r\n }\r\n\r\n render () {\r\n return `
\r\n

Pagination Example

\r\n \r\n \r\n
`;\r\n }\r\n}\r\n\r\nOmi.render( new Main(),'body');\r\n```\r\n\r\n如上面的onPageChange就是自定义事件,触发会执行handlePageChange。onPageChange方法是在Pagination中执行:\r\n\r\n```js\r\nimport Omi from '../../src/index.js';\r\n\r\nclass Pagination extends Omi.Component {\r\n ...\r\n ...\r\n ...\r\n linkTo: \"#\",\r\n prevText: \"Prev\",\r\n nextText: \"Next\",\r\n ellipseText: \"...\",\r\n prevShow: true,\r\n nextShow: true,\r\n onPageChange: function () { return false; }\r\n }, this.data);\r\n\r\n this.pageNum = Math.ceil(this.data.total / this.data.pageSize);\r\n }\r\n \r\n goto (index,evt) {\r\n evt.preventDefault();\r\n this.data.currentPage=index;\r\n this.update();\r\n this.data.onPageChange(index);\r\n }\r\n ...\r\n ...\r\n ...\r\n}\r\n```\r\n\r\n这里取了Pagination组件的部分代码。高亮的就是执行onPageChange的地方。\r\n\r\n### 相关地址\r\n\r\n* [演示地址](http://alloyteam.github.io/omi/example/pagination/)\r\n* [源码地址](https://github.com/AlloyTeam/omi/tree/master/example/pagination)\r\n" - -/***/ }, -/* 13 */ -/***/ function(module, exports) { - - module.exports = "## 表单\r\n\r\nOmi让一些表单操控起来更加方便,特别是select!\r\n\r\n### select标签\r\n\r\n以前,我们需要像如下的方式选中一个选项:\r\n\r\n```html\r\n\r\n```\r\n\r\n第三个option由于加上了selected,所有会被选中。这样带来的问题就是,开发者写的程序可能要操遍历每个option。而使用Omi,你只需要这样子:\r\n\r\n```html\r\n\r\n```\r\n\r\n这样就能达到同样的效果。比如你想选择第一项:\r\n\r\n```html\r\n\r\n```\r\n\r\n是不是非常方便?\r\n\r\n### 举个例子\r\n\r\n```js\r\nclass FormTest extends Omi.Component {\r\n constructor(data) {\r\n super(data);\r\n \r\n }\r\n\r\n handleChange(target){\r\n console.log(target.value)\r\n this.data.value = target.value;\r\n }\r\n\r\n handleSubmit(evt) {\r\n alert('Your favorite flavor is: ' + this.data.value);\r\n evt.preventDefault();\r\n }\r\n \r\n render () {\r\n return `\r\n
\r\n \r\n \r\n
`;\r\n }\r\n}\r\n\r\nOmi.render(new FormTest({ value: 'mango' }),'#container');\r\n```\r\n\r\n点击这里→在线试试" - -/***/ }, -/* 14 */ -/***/ function(module, exports) { - - module.exports = "## 获取DOM节点\r\n\r\n虽然绝大部分情况下,开发者不需要去查找获取DOM,但是还是有需要获取DOM的场景,所以Omi提供了方便获取DOM节点的方式。\r\n\r\n### ref和refs\r\n\r\n```js\r\nclass Hello extends Omi.Component {\r\n constructor(data) {\r\n super(data);\r\n }\r\n \r\n style () {\r\n return `\r\n h1{\r\n cursor:pointer;\r\n }\r\n `;\r\n }\r\n \r\n handleClick(){\r\n alert(this.refs.abc.innerHTML);\r\n }\r\n \r\n render() {\r\n return `\r\n
\r\n

Hello ,{{name}}!

\r\n
\r\n `;\r\n }\r\n}\r\n\r\nOmi.render(new Hello({ name : \"Omi\" }),\"#container\");\r\n```\r\n\r\n可以看到通过在HTML中标记ref为abc,那么就通过this.refs.abc访问到该DOM节点。\r\n\r\n点击这里→在线试试" - -/***/ }, -/* 15 */ -/***/ function(module, exports) { - - module.exports = "## Hello World\r\n\r\n你可以使用ES6+或者ES5的方式编写Omi程序来搭建你的Web程序。\r\n\r\n### Hello World with ES6+\r\n\r\n你可以使用 [webpack](https://webpack.github.io/) 打包工具,webpack会把你的模块代码打成一个很小的包,优化加载时间。使用[babel](http://babeljs.io/),让你立刻马上使用ES6+来编写你的web程序。你只需要在webpack配置的module设置好[babel-loader](https://github.com/babel/babel-loader)便可。\r\n\r\n一个Omi的简短的例子如下所示:\r\n\r\n```js\r\nimport Omi from './omi.js';\r\n\r\nclass Hello extends Omi.Component {\r\n constructor(data) {\r\n super(data);\r\n }\r\n \r\n style () {\r\n //注意,return中的包裹是可选的。主要是为了识别为JSX文件可以有CSS高亮。\r\n return `\r\n \r\n `;\r\n }\r\n \r\n handleClick(target, evt){\r\n alert(target.innerHTML);\r\n }\r\n \r\n render() {\r\n return `\r\n
\r\n

Hello ,{{name}}!

\r\n
\r\n `;\r\n }\r\n}\r\n\r\nOmi.render(new Hello({ name : \"Omi\" }),\"#container\");\r\n```\r\n\r\n组件生成的HTML最终会插入到#container中。上面的例子展示了Omi的部分特性:\r\n\r\n- data传递: new Hello(data,..)的data可以直接提供给render方法里的模板\r\n- 局部CSS: h1只对render里的h1生效,不会污染外面的h1\r\n- 声明式事件绑定: onclick调用的就是组件内的handleClick,this可以拿到当前的DOM元素,还可以拿到当前的event\r\n\r\n点击这里→在线试试\r\n\r\n你可以使用Omi.makeHTML来生成组件标签用于嵌套。\r\n```js\r\n Omi.makeHTML('Hello', Hello);\r\n```\r\n那么你就在其他组件中使用,如\r\n```js\r\n ...\r\n render() {\r\n return `\r\n
\r\n
Test
\r\n \r\n
\r\n `;\r\n }\r\n ...\r\n```\r\n\r\n点击这里→在线试试\r\n\r\n### Hello World with ES5\r\n\r\n当然Omi没有抛弃ES5的用户。你可以使用ES5的方式编写Omi。如,在你的HTML中引用omi.js:\r\n\r\n```html\r\n\r\n```\r\n\r\n然后:\r\n\r\n```js\r\nvar Hello = Omi.create(\"Hello\", {\r\n style: function () {\r\n return \"h1{ cursor:pointer }\";\r\n },\r\n \r\n handleClick: function (dom) {\r\n alert(dom.innerHTML)\r\n },\r\n \r\n render: function () {\r\n return '
\\\r\n

\\\r\n Hello ,{{name}}!\\\r\n

\\\r\n
'\r\n }\r\n});\r\n\r\nvar Test = Omi.create(\"Test\", {\r\n render: function () {\r\n return '
\\\r\n
Test
\\\r\n \\\r\n
'\r\n }\r\n});\r\n\r\nOmi.render(new Test(),'#container');\r\n```\r\n当然除了在HTML引入脚本,你还可以使用AMD、CMD或者CommonJS的方式引入Omi,这里就不再一一列举。\r\n\r\n需要注意的是,Omi.create的第一个参数Hello是用来生成Tag Name的。你可以在其他地方嵌入你的组件。如:\r\n\r\n```js\r\n ...\r\n render:function() {\r\n return '
\\\r\n \\\r\n
Test XXXX
\\\r\n \\\r\n
';\r\n }\r\n ...\r\n```\r\n\r\n点击这里→在线试试\r\n" - -/***/ }, -/* 16 */ -/***/ function(module, exports) { - - module.exports = "## 继承\r\n\r\n通过继承机制,可以利用已有的数据类型来定义新的数据类型。所定义的新的数据类型不仅拥有新定义的成员,而且还同时拥有旧的成员。我们称已存在的用来派生新类的类为基类,又称为父类。由已存在的类派生出的新类称为派生类,又称为子类。\r\n\r\n### 举个例子\r\n\r\n```js\r\nclass Hello extends Omi.Component {\r\n constructor(data) {\r\n super(data);\r\n }\r\n \r\n style () {\r\n return `\r\n div{\r\n cursor:pointer;\r\n }\r\n `;\r\n }\r\n \r\n handleClick(target, evt){\r\n alert(target.innerHTML);\r\n }\r\n \r\n render() {\r\n return '
Hello {{name}}!
'\r\n }\r\n}\r\n\r\nclass SubHello extends Hello {\r\n constructor(data) {\r\n super(data);\r\n }\r\n}\r\n\r\nOmi.render(new SubHello({ name : 'Omi' }),'#container');\r\n```\r\n\r\n点击这里→在线试试\r\n\r\n### ES5下的继承\r\n\r\n```js\r\nvar Hello = Omi.create(\"Hello\",{\r\n render:function(){\r\n return '
Hello {{name}}!
'\r\n }\r\n})\r\n\r\nvar SubHello = Omi.create(\"SubHello\",Hello,{ });\r\n\r\n\r\nOmi.render(new SubHello({ name : 'Omi' }),'#container');\r\n```\r\n\r\n点击这里→在线试试" - -/***/ }, -/* 17 */ -/***/ function(module, exports) { - - module.exports = "## 安装\n\n[Omi](https://github.com/AlloyTeam/omi)(读音 / [ˈomɪ] /, 汉字类似于 欧米) 是一款用于创建用户界面的组件化框架,开放并且现代,故得名:Omi。\n\n### 安装 Omi\n\n我们推荐使用 [npm](https://www.npmjs.com/) 来管理你的前端依赖.\n\n通过npm安装Omi,你只需要执行下面的命令:\n\n``` js\n$ npm install omi\n```\n\n## omi-cli\n\n你也可以通过omi-cli去初始化你的项目:\n\n``` js\n$ npm install omi-cli -g //安装cli\n$ omi init your_project_name //初始化项目,你也可以在一个空的文件夹下执行 omi init\n$ cd your_project_name //如果你是在空文件夹下执行的 omi init。请无视这条命令\n$ npm run dev //开发\n$ npm run dist //部署发布\n```" - -/***/ }, -/* 18 */ -/***/ function(module, exports) { - - module.exports = "## 生命周期\r\n\r\n|name |avatars |company | \r\n|---|---|---|\r\n| constructor | 构造函数 | new的时候 |\r\n| install | 初始化安装,这可以拿到用户传进的data进行处理 | 实例化 |\r\n| installed | 安装完成,HTML已经插入页面之后执行 | 实例化 |\r\n| uninstall | 卸载组件。执行remove方法会触发该事件 | 销毁时 |\r\n| beforeUpdate | 更新前 | 存在期 |\r\n| afterUpdate | 更新后 | 存在期 |\r\n\r\n## 示意图\r\n\r\n![lc](http://images2015.cnblogs.com/blog/105416/201703/105416-20170322083548924-1871234168.jpg)\r\n \r\n### 举个例子\r\n\r\n```js\r\nclass Timer extends Omi.Component {\r\n constructor(data) {\r\n super(data);\r\n }\r\n\r\n install () {\r\n this.data = {secondsElapsed: 0};\r\n }\r\n\r\n tick() {\r\n this.data.secondsElapsed++;\r\n this.update();\r\n }\r\n\r\n installed(){\r\n this.interval = setInterval(() => this.tick(), 1000);\r\n }\r\n\r\n uninstall() {\r\n clearInterval(this.interval);\r\n }\r\n\r\n\r\n style () {\r\n return `\r\n .num { color:red; }\r\n `;\r\n }\r\n\r\n render () {\r\n return `
Seconds Elapsed: {{secondsElapsed}}
`;\r\n }\r\n}\r\n```\r\n\r\n点击这里→在线试试\r\n" - -/***/ }, -/* 19 */ -/***/ function(module, exports) { - - module.exports = "## 循环遍历\r\n\r\n下面介绍mustache.js的方式和javascript遍历的方式。\r\n\r\n### 方式一\r\n\r\n```js\r\nclass List extends Omi.Component {\r\n constructor(data) {\r\n super(data);\r\n }\r\n\r\n render () {\r\n return `
\r\n
    \r\n {{#items}} \r\n
  • {{text}}
  • \r\n {{/items}}\r\n
\r\n
`;\r\n }\r\n}\r\n\r\nOmi.render(new List({\r\n items: [\r\n {id: 1, text: 'Omi'},\r\n {id: 2, text: 'dntzhang'},\r\n {id: 3, text: 'AlloyTeam'}\r\n ]\r\n}),\"body\");\r\n```\r\n\r\nmustache.js更详细的循环遍历使用可看[https://github.com/janl/mustache.js#non-empty-lists](https://github.com/janl/mustache.js#non-empty-lists)。 比如还支持:\r\n\r\n* 如果items的每一项是字符串,可以直接**{{.}}**的方式来输出每一项\r\n* 循环的时候调用定义好的函数\r\n\r\n点击这里→在线试试\r\n\r\n### 方式二\r\n\r\n既然ES6+了,当然可以使用${ }以及Array的map方法: \r\n\r\n```js\r\nclass List extends Omi.Component {\r\n constructor(data) {\r\n super(data);\r\n }\r\n\r\n render() {\r\n return `
\r\n
    \r\n ${this.data.items.map(item =>\r\n `
  • ${item.text}
  • `\r\n ).join('')}\r\n
\r\n
`;\r\n }\r\n}\r\n\r\nOmi.render(new List({\r\n items: [\r\n {id: 1, text: 'Omi'},\r\n {id: 2, text: 'dntzhang'},\r\n {id: 3, text: 'AlloyTeam'}\r\n ]\r\n}),\"body\");\r\n```\r\n\r\n你将在页面看到如下效果:\r\n\r\n![pv](http://images2015.cnblogs.com/blog/105416/201701/105416-20170122095724129-2059595233.png)\r\n\r\n点击这里→在线试试\r\n\r\n如果想在循环里加些判断呢?比如需要把id为偶数的隐藏起来:\r\n\r\n```js\r\nrender() {\r\n return `
\r\n
    \r\n ${this.data.items.map(item =>\r\n `
  • ${item.text}
  • `\r\n ).join('')}\r\n
\r\n
`;\r\n}\r\n```\r\n\r\n所以模板字符串还是非常方便,随着ES继续发展下去,模板引擎估计会慢慢消失。所以omi提供了 omi.lite.js 版本不包含任何模板引擎。" - -/***/ }, -/* 20 */ -/***/ function(module, exports) { - - module.exports = "## 插件体系\r\n\r\n[Omi](https://github.com/AlloyTeam/omi)是Web组件化框架,怎么又来了个插件的概念?\r\n\r\n可以这么理解: Omi插件体系可以赋予dom元素一些能力,并且可以和组件的实例产生关联。\r\n\r\n### omi-drag\r\n\r\n且看这个例子:\r\n\r\n点击这里→在线试试\r\n\r\n```js\r\nimport OmiDrag from './omi-drag.js';\r\n\r\nOmiDrag.init();\r\n\r\nclass App extends Omi.Component {\r\n constructor(data) {\r\n super(data);\r\n }\r\n\r\n render() {\r\n return `\r\n
\r\n
Drag Me
\r\n
\r\n `;\r\n\r\n }\r\n\r\n style(){\r\n return `\r\n .test{\r\n width:100px;\r\n height:100px;\r\n color:white;\r\n line-height:90px;\r\n text-align:center;\r\n background-color:#00BFF3;\r\n }\r\n `\r\n }\r\n}\r\n\r\nOmi.render(new App(),\"#container\");\r\n```\r\n\r\n如上面的代码所示,通过在div上标记omi-drag,这个div就能够被用户使用鼠标拖拽。我们称omi-drag.js为omi插件。\r\n是不是非常方便?那么这个omi-drag是怎么实现的?\r\n\r\n## Omi.extendPlugin\r\n\r\n核心方法: Omi.extendPlugin( pluginName, handler )\r\n\r\n下面的代码就是展示了如何通过 Omi.extendPlugin 赋予dom拖拽的能力:\r\n\r\n```js\r\n;(function () {\r\n\r\n var OmiDrag = {};\r\n var Omi = typeof require === 'function'\r\n ? require('omi')\r\n : window.Omi;\r\n\r\n OmiDrag.init = function(){\r\n Omi.extendPlugin('omi-drag',function(dom, instance){\r\n dom.style.cursor='move';\r\n var isMouseDown = false,\r\n preX = null,\r\n preY = null,\r\n currentX = null,\r\n currentY = null,\r\n translateX = 0,\r\n translateY = 0;\r\n\r\n dom.addEventListener('mousedown',function(evt){\r\n isMouseDown = true;\r\n preX = evt.pageX;\r\n preY = evt.pageY;\r\n evt.stopPropagation();\r\n },false);\r\n\r\n window.addEventListener('mousemove',function(evt){\r\n if(isMouseDown){\r\n currentX = evt.pageX;\r\n currentY = evt.pageY;\r\n if(preX != null){\r\n translateX += currentX - preX;\r\n translateY += currentY - preY;\r\n dom.style.transform = 'translateX('+translateX+'px) translateY('+translateY+'px)';\r\n }\r\n preX = currentX;\r\n preY = currentY;\r\n evt.preventDefault();\r\n }\r\n },false);\r\n\r\n window.addEventListener('mouseup',function(){\r\n isMouseDown = false;\r\n preX = preY = currentX = currentY = null;\r\n },false);\r\n });\r\n }\r\n\r\n OmiDrag.destroy = function(){\r\n delete Omi.plugins['omi-drag'];\r\n };\r\n\r\n if (typeof exports == \"object\") {\r\n module.exports = OmiDrag;\r\n } else if (typeof define == \"function\" && define.amd) {\r\n define([], function(){ return OmiDrag });\r\n } else {\r\n window.OmiDrag = OmiDrag;\r\n }\r\n\r\n})();\r\n```\r\n\r\n方法: Omi.extendPlugin( pluginName, handler )\r\n\r\n其中pluginName为插件的名称\r\n其中handler为处理器。handler可以拿到标记了pluginName的dom以及dom所在的组件的实例,即 dom 和 instance。\r\n\r\n通过 Omi.extendPlugin,可以赋予dom元素一些能力,也可以和组件的实例(instance)产生关联。\r\n但是上面的例子没有和instance产生关联,我们接下来试试:\r\n\r\n## 关联instance\r\n\r\n我们想在组件里面能够监听到move并且执行回调。如下:\r\n\r\n```js\r\n...\r\n...\r\nmoveHandler(){\r\n console.log('moving');\r\n}\r\n\r\nrender() {\r\n return `\r\n
\r\n
Drag Me
\r\n
\r\n `;\r\n}\r\n...\r\n```\r\n\r\n主要被拖动过程中,moveHandler就不断地被执行。插件代码需要修改:\r\n\r\n```js\r\n...\r\nwindow.addEventListener('mousemove',function(evt){\r\n if(isMouseDown){\r\n currentX = evt.pageX;\r\n currentY = evt.pageY;\r\n if(preX != null){\r\n translateX += currentX - preX;\r\n translateY += currentY - preY;\r\n dom.style.transform = 'translateX('+translateX+'px) translateY('+translateY+'px)';\r\n }\r\n preX = currentX;\r\n preY = currentY;\r\n evt.preventDefault();\r\n instance.moveHandler(evt);\r\n }\r\n},false);\r\n```\r\n\r\n我们在里面增加了instance.moveHandler(evt);方法,用来执行组件实例上的moveHandler方法。\r\n这样的话:就是组件的实例(instance)产生关联。但是还是有问题?如果标记了多个omi-drag 就会有问题!如:\r\n\r\n```js\r\n...\r\nrender() {\r\n return `\r\n
\r\n
Drag Me
\r\n
Drag Me
\r\n
\r\n `;\r\n}\r\n...\r\n```\r\n\r\n通常我们系统每个omi-drag都能对应一个回调函数,如:\r\n\r\n```js\r\n...\r\n...\r\nmoveHandlerA(){\r\n console.log('moving');\r\n}\r\n\r\nmoveHandlerB(){\r\n console.log('moving');\r\n}\r\n\r\nrender() {\r\n return `\r\n
\r\n
Drag Me A
\r\n
Drag Me B
\r\n
\r\n `;\r\n}\r\n...\r\n```\r\n\r\n怎么办?怎么实现?有办法!通过dom传递数据给插件。\r\n\r\n## 传递数据\r\n\r\n先来看最后实现的效果:\r\n\r\n```js\r\n...\r\n...\r\nmoveHandlerA(){\r\n console.log('moving');\r\n}\r\n\r\nmoveHandlerB(){\r\n console.log('moving');\r\n}\r\n\r\nrender() {\r\n return `\r\n
\r\n
Drag Me A
\r\n
Drag Me B
\r\n
\r\n `;\r\n}\r\n...\r\n```\r\n\r\nomi-drag修改的地方:\r\n\r\n```js\r\n...\r\nvar handlerName = dom.getAttribute('dragMove');\r\n\r\nwindow.addEventListener('mousemove',function(evt){\r\n if(isMouseDown){\r\n currentX = evt.pageX;\r\n currentY = evt.pageY;\r\n if(preX != null){\r\n translateX += currentX - preX;\r\n translateY += currentY - preY;\r\n dom.style.transform = 'translateX('+translateX+'px) translateY('+translateY+'px)';\r\n }\r\n preX = currentX;\r\n preY = currentY;\r\n evt.preventDefault();\r\n instance[handlerName](evt);\r\n }\r\n},false);\r\n...\r\n```\r\n\r\n* 通过 var handlerName = dom.getAttribute('dragMove') 拿到dom上声明的dragMove\r\n* 通过 instance[handlerName](evt) 去执行对应的方法\r\n\r\n点击这里→在线试试\r\n\r\n## 更多插件\r\n\r\n* [omi-finger](https://github.com/AlloyTeam/omi/tree/master/plugins/omi-finger) Omi的[AlloyFinger](https://github.com/AlloyTeam/AlloyFinger)插件,支持各种触摸事件和手势\r\n* [omi-transform](https://github.com/AlloyTeam/omi/tree/master/plugins/omi-transform) Omi的[transformjs](http://alloyteam.github.io/AlloyTouch/transformjs/)插件,快速方便地设置DOM的CSS3 Transform属性\r\n* [omi-touch](https://github.com/AlloyTeam/omi/tree/master/plugins/omi-touch) Omi的[AlloyTouch](https://github.com/AlloyTeam/AlloyTouch)插件,Omi项目的触摸运动解决方案(支持触摸滚动、旋转、翻页、选择等等)\r\n* [omi-jquery-date-picker](https://github.com/AlloyTeam/omi/tree/master/plugins/omi-jquery-date-picker) Omi的时间选择插件,支持各种时间或者时间区域选择\r\n" - -/***/ }, -/* 21 */ -/***/ function(module, exports) { - - module.exports = "## Store 体系\r\n\r\n先说说Store系统是干什么的!\r\n\r\n当我们组件之间,拥有共享的数据的时候,经常需要进行组件通讯。在Omi框架里,组件通讯非常方便:\r\n\r\n* 通过在组件上声明 data-* 传递给子节点\r\n* 通过在组件上声明 data 传递给子节点 (支持复杂数据类型的映射)\r\n* 声明 group-data 把数组里的data传给一堆组件传递(支持复杂数据类型的映射)\r\n* 完全面向对象,可以非常容易地拿到对象的实例,之后可以设置实例属性和调用实例的方法。比如(标记name、标记omi-id)\r\n\r\n当然你也可以使用event emitter / pubsub库在组件之间通讯,比如这个只有 200b 的超小库[mitt](https://github.com/developit/mitt) 。但是需要注意mitt兼容到IE9+,Omi兼容IE8。\r\n\r\n虽然组件通讯非常方便,但是各种数据传递、组件实例互操作或者循环依赖,让代码非常难看且难以维护。所以:\r\n\r\nOmi.Store是为了让 组件通讯几乎绝迹 。虽然:\r\n\r\n\tRedux 的作者 Dan Abramov 说过:Flux 架构就像眼镜:您自会知道什么时候需要它。\r\n\t\r\n但是,我不会告诉你\r\n\r\n\tOmi Store 系统就像眼镜:您自会知道什么时候需要它。\r\n\t\r\n因为,Omi Store使用足够简便,对架构入侵性极极极小(3个极代表比极小还要小),让数据、数据逻辑和UI展现彻底分离,所以我的观点是:\r\n\r\n\t如果使用Omi,请使用Omi.Store架构。\r\n\t\r\n比如连这个[Todo例子](https://github.com/AlloyTeam/omi/tree/master/example/todo-store)都能使用Omi.Store架构。如果连复杂度都达不到Todo,那么Omi其实都没有必要使用,你可能只需要一个模板引擎便可。\r\n\r\n\r\n### 定义 Omi.Store\r\n\r\nOmi.Store是基类,我们可以继承Omi.Store来定义自己的Store,比如下面的TodoStore。\r\n\r\n```js\r\nimport Omi from 'omi'\r\n\r\nclass TodoStore extends Omi.Store {\r\n constructor(data , isReady) {\r\n super(isReady)\r\n\r\n this.data = Object.assign({\r\n items:[],\r\n text:'',\r\n length:0\r\n },data)\r\n\r\n this.data.length = this.data.items.length\r\n }\r\n\r\n add(){\r\n this.data.items.push(this.data.text)\r\n this.data.text = \"\"\r\n this.data.length = this.data.items.length\r\n this.update()\r\n }\r\n\r\n updateText(text){\r\n this.data.text = text\r\n }\r\n\r\n clear(){\r\n this.data.items.length = 0\r\n this.data.length = 0\r\n this.data.text = \"\"\r\n this.update()\r\n }\r\n}\r\n\r\nexport default TodoStore\r\n```\r\n\r\nTodoStore定义类数据的基本格式和数据模型的逻辑。\r\n比如 this.data 就是数据的基本格式, \r\n\r\n```js\r\n{\r\n items:[],\r\n text:'',\r\n length:0\r\n}\r\n```\r\n\r\nadd,updateText和clear就是数据模型的逻辑。\r\n\r\n### 使用 Omi.Store\r\n\r\n通过 new 关键字来使用TodoStore对象的实例。\r\n\r\n```js\r\nlet store = new TodoStore({ /* 初始化配置 */ })\r\n```\r\n\r\n上面可以传入一些初始化配置信息,store里面便包含了整个应用程序共享的状态数据以及相关数据逻辑方法(add,updateText,clear)。\r\n\r\n当然,这些初始化配置信息可能是异步拉取的。所以,有两种方法解决异步拉取store配置的问题:\r\n\r\n* 先let store = new TodoStore(),再Omi.render,组件内部监听store.ready,拉取数据更改store的data信息,然后执行store.beReady()\r\n* 拉取数据,然后new TodoStore(),再Omi.render\r\n\r\n### 根组件注入 store\r\n\r\n为了让组件树能够使用到 store,可以通过Omi.render的第三个参数给根组件注入 store:\r\n\r\n```js\r\nOmi.render(new Todo(),'body',{\r\n store: store\r\n});\r\n```\r\n\r\n当然ES2015已经允许你这样写了:\r\n\r\n```js\r\nOmi.render(new Todo(),'body',{\r\n store\r\n});\r\n```\r\n\r\n两份代码同样的效果。\r\n\r\n通过Omi.render注入之后,在组件树的所有组件都可以通过 this.$store 访问到 store。\r\n\r\n### 简便的 beforeRender\r\n\r\nbeforeRender这个函数,是生命周期的一部分。且看下面这张图:\r\n\r\n![beforeRender](http://images2015.cnblogs.com/blog/105416/201703/105416-20170322083548924-1871234168.jpg)\r\n\r\n在render之前,会去执行beforeRender方法。所以可以利用该方法写store的data到组件data的转换逻辑。比如:\r\n\r\n```js\r\nclass List extends Omi.Component {\r\n beforeRender(){\r\n this.data.items = this.$store.data.items\r\n }\r\n\r\n render () {\r\n return `
    {{#items}}
  • {{.}}
  • {{/items}}
`\r\n }\r\n}\r\n```\r\n\r\n再比如todo使用length和text:\r\n\r\n```js\r\nimport Omi from '../../src/index.js';\r\nimport List from './list.js';\r\n\r\nOmi.makeHTML('List', List);\r\n\r\nclass Todo extends Omi.Component {\r\n\r\n install(){\r\n this.$store.ready(()=>this.update())\r\n }\r\n\r\n beforeRender(){\r\n this.data.length = this.$store.data.items.length\r\n this.data.text = this.$store.text\r\n }\r\n\r\n add (evt) {\r\n evt.preventDefault();\r\n this.$store.add();\r\n }\r\n\r\n handleChange(target){\r\n this.$store.updateText(target.value);\r\n }\r\n\r\n render () {\r\n return `
\r\n

TODO

\r\n \r\n
\r\n \r\n \r\n
\r\n
`;\r\n }\r\n}\r\n\r\nexport default Todo;\r\n```\r\n\r\n为什么要去写beforeRender方法?因为render只会使用this.data去渲染页面而不会去使用this.$store.data,所以需要把数据转移到组件的this.data下。这样组件既能使用自身的data,也能使用全局放this.$store.data了。\r\n\r\n更为详细的代码可以[点击这里](https://github.com/AlloyTeam/omi/tree/master/example/todo-store)。" - -/***/ }, -/* 22 */ -/***/ function(module, exports) { - - module.exports = "## 模板切换\r\n\r\nOmi有三个版本。其中的omi.js和omi.lite.js属于Web端使用的版本。\r\n\r\n* omi.js内置了[mustache.js](https://github.com/janl/mustache.js)作为模版引擎\r\n* omi.lite.js不包含任何模版引擎\r\n\r\nOmi不强制开发者使用mustache.js,你可以根据业务场景使用任意模板引擎或者不使用模板引擎。\r\n\r\n那么怎么使用别的模板引擎?下面拿[artTemplate](https://github.com/aui/artTemplate)作为例子。\r\n\r\n### 使用artTemplate\r\n\r\n```js\r\nOmi.template = function(tpl, data){\r\n return artTemplate.compile(tpl)(data);\r\n}\r\n```\r\n重写Omi.template方法,tpl为传入的模板,data为模板所需的数据,返回值为HTML。\r\n重写完毕后就能在render使用artTemplate的语法,如:\r\n\r\n```js\r\nclass List extends Omi.Component {\r\n constructor(data) {\r\n super(data);\r\n }\r\n\r\n style () {\r\n return `\r\n h1 { color:red; }\r\n li{ color:green;}\r\n `;\r\n }\r\n\r\n render () {\r\n return `

{{title}}

\r\n
    \r\n {{each list as value i}}\r\n
  • 索引 {{i + 1}} :{{value}}
  • \r\n {{/each}}\r\n
`;\r\n }\r\n}\r\n```\r\n\r\n### 相关地址\r\n\r\n* [演示地址](http://alloyteam.github.io/omi/example/artTemplate/)\r\n* [源码地址](https://github.com/AlloyTeam/omi/tree/master/example/artTemplate)" - -/***/ }, -/* 23 */ -/***/ function(module, exports) { - - module.exports = "## Omi的理念\n\nOmi的理念是基于面向对象编程体系,内建积木系统。\n 传统的单向数据流或者抛出event的组件通讯方式增加了系统的稳定性,但是丧失了灵活性。一定程度上也降低了组件的复用。所谓鱼和熊掌不可兼得。\n 面向对象体系需要多一个逻辑层,可以自由操作所有组件的instance,instance之间的逻辑关系构建出了整个程序。这样组件间的逻辑,通信,复用就全部迎刃而解。组件也更加单一职责,更松耦合。\n\n对比函数式编程、命令式编程与面向对象编程,可以归纳总结出下面几条:\n\n- 命令式编程干脆直接,利用循环条件等控制流程,强调执行过程\n- 命令式编程对硬件执行友好,运行更容易,却阻碍了复杂程序的设计\n- 函数式强调输入和输出,并非执行过程\n- 函数式倡导多个简单执行单元组合成复杂运算程序\n- 面向对象编程将对象作为程序的基本单元,更具有重用性、灵活性和扩展性\n\nJavascript是哪种类型的语言?现在ES6+已经有了class。那么他是面向对象语言?\n但是JS可以在任意地方定义函数并且当作把函数当作值来传递。那么他是函数式编程语言?\n所以,没有精准的定义,取决于你的用法和姿势。其次,Web组件化架构层面编程模型和语言层面编程模型是非常自由的关系。意思就是,你可以用Javascript构建函数式编程框架如React,也可以基于面向对象体系搭建Omi。\n\n### 函数式编程 VS 面向对象编程\n\n在UI组件框架层面,函数式编程的代表有React,Omi属于面向对象编程体系。那么他们各有什么优缺点?下面做了个对比(其实也是函数式编程与面向对象编程的对比):\n\n| | React | Omi |\n| ------------- |:-------------:|:-----:|\n| 组件通信 | ★★★★☆| ★★★★★ |\n| 稳定性 | ★★★★★ | ★★★★☆ |\n| 灵活性 | ★★★★☆| ★★★★★ |\n| 扩展性 | ★★★★☆ | ★★★★★ |\n| 测试性 | ★★★★★ | ★★★★☆ |\n| 文件大小 | ★★★☆☆ | ★★★★★ |\n| 功能特性 | ★★★☆☆ | ★★★★☆ |\n| DOM性能 | ★★★★★ | ★★★★☆ |\n| 动画性能 | ★★★★☆ | ★★★★★ |\n| 抽象复杂度 | ★★★★☆ | ★★★★★ |\n| 异步编程 | ★★★★★ | ★★★★☆ |\n\n可以看得出,鱼和熊掌不可兼得。面向对象编程更具有重用性、灵活性和扩展性,带来的问题就是更加难测试。\n具体来说,如函数式编程,其测试面积是state1 + state2 + ... + stateN;在面向对象编程中,其测试面积是state1×event1 + state2×event2 + ... + stateN×eventN。\n\n总结来说,更加推荐使用面向对象的方式去搭建UI组件化框架。\n\n
\n\n### 全文结束,感谢阅读。[开始Omi之旅吧!](https://github.com/AlloyTeam/omi) \n\n" - -/***/ }, -/* 24 */ -/***/ function(module, exports) { - - module.exports = "## Component Communication\r\n\r\nCommunication between [Omi](https://github.com/AlloyTeam/omi) components is very flexible, there are many options:\r\n\r\n- By declaring `data-*` on the component to pass data to child node\r\n- By declaring `data` on the component to pass data to child node (support complex data types mapping)\r\n- By declaring `childrenData` on parent component to automatically pass data to child node\r\n- By declaring `group-data` (support complex data types mapping)\r\n- It's completely object-oriented, you can easily get the object instance, then you can set the instance of the property or call the instance of the method\r\n\r\nLet's see some examples.\r\n\r\n### Communicate by `data-*`\r\n\r\n```js\r\nclass Hello extends Omi.Component {\r\n constructor(data) {\r\n super(data);\r\n }\r\n \r\n style () {\r\n return `\r\n h1{\r\n \tcursor:pointer;\r\n }\r\n `;\r\n }\r\n \r\n handleClick(target, evt){\r\n alert(target.innerHTML);\r\n }\r\n \r\n render() {\r\n return `\r\n
\r\n \t

Hello ,{{name}}!

\r\n
\r\n \t\t`;\r\n }\r\n}\r\n\r\nOmi.makeHTML('Hello', Hello);\r\n\r\nclass App extends Omi.Component {\r\n constructor(data) {\r\n super(data);\r\n }\r\n \r\n render() {\r\n return `\r\n
\r\n \r\n
\r\n `;\r\n }\r\n}\r\n\r\nOmi.render(new App(),\"#container\");\r\n```\r\n\r\nGenerally `data-*` is used to pass value types such as string and number. It is worth noting that, through `data-*`, received data types are string. You need to manually transform it to the number type.\r\n\r\nNormally, communicate by `data-*` is enough, but sometimes we may need to use complex data types, then we can use `data` to communicate.\r\n\r\n### Communicate by `data`\r\n\r\nAs shown in the above code, name can be passed to the subcomponent by `data-name=\"Omi\"`. The following code can also achieve the same effect.\r\n\r\n```js\r\n...\r\nclass App extends Omi.Component {\r\n constructor(data) {\r\n super(data);\r\n this.helloData = { name : 'Omi' };\r\n }\r\n \r\n render() {\r\n return `\r\n
\r\n \r\n
\r\n `;\r\n }\r\n}\r\n\r\nOmi.render(new App(),\"#container\");\r\n```\r\n\r\nUse the `data` tag, it will find the property from the component instance (that is, this), this can be mounted with any complex objects. This also broke the limitations of `data-*`.\r\n\r\nThen how do we pass `data` that is in a deep depth of the instance to the Hello? No worries, `data` tag can be a complex statement:\r\n\r\n```js\r\n...\r\nclass App extends Omi.Component {\r\n constructor(data) {\r\n super(data);\r\n this.complexData ={\r\n a:{\r\n b:{\r\n c:[\r\n {\r\n e:[{\r\n name:'ComplexData Support1'\r\n },{\r\n name:'ComplexData Support2'\r\n }]\r\n },\r\n {\r\n name: 'ComplexData Support3'\r\n }\r\n ]\r\n }\r\n }\r\n };\r\n }\r\n \r\n render() {\r\n return `\r\n
\r\n \r\n
\r\n `;\r\n }\r\n}\r\n...\r\n```\r\n\r\nClick me for the complex data mapping\r\n\r\n### Communicate by `childrenData`\r\n\r\n```js\r\n...\r\nclass App extends Omi.Component {\r\n constructor(data) {\r\n super(data);\r\n this.childrenData = [{ name : 'Omi' } , { name : 'dntzhang' }];\r\n }\r\n \r\n render() {\r\n return `\r\n
\r\n \r\n \r\n
\r\n `;\r\n }\r\n}\r\n\r\nOmi.render(new App(),\"#container\");\r\n```\r\n\r\nWe can use `this.childrenData` to transfer data to the sub-component. In this case, `childrenData` is an array, so it can pass data to multiple components in the same time. In the meanwhile, the data will be passed to components one by one.\r\n\r\n### Communicate by `group-data`\r\n\r\n`childrenData` can pass data to multiple components. However, there are many scenes where the source of data does not have to be from `childrenData`. `childrenData` is an array, and it should be the same order with the components, so that the data must all concentrated in `childrenData`, it's very inconvenient. `group-data` dedicated to solve the above pain points, specifically to pass data to a group of components.\r\n\r\n```js\r\nimport Hello from './hello.js';\r\n\r\n\r\nOmi.makeHTML('Hello', Hello);\r\n\r\nclass App extends Omi.Component {\r\n constructor(data) {\r\n super(data);\r\n this.testData = [{name: 'Omi'}, {name: 'dntzhang'}, {name: 'AlloyTeam'}];\r\n }\r\n\r\n render() {\r\n return `\r\n
\r\n \r\n \r\n \r\n
\r\n `;\r\n\r\n }\r\n}\r\n\r\nOmi.render(new App(),\"#container\");\r\n```\r\n\r\nBy declaring a `group-data` tag in the sub-components, it will go to the current instance of the component (that is, `this`) to find the corresponding property. Then according to the current location, the data will pass to the positions one by one.\r\n\r\nThe results are as follows:\r\n\r\n![group-data results](http://images2015.cnblogs.com/blog/105416/201702/105416-20170216110701535-1698390390.png)\r\n\r\nClick me for the group-data example\r\n\r\nSimilarly, `group-data` supports the mapping of complex data types. It should be noted that the end of the group-data mapping must be an array:\r\n\r\n```js\r\nimport Hello from './hello.js';\r\n\r\n\r\nOmi.makeHTML('Hello', Hello);\r\n\r\nclass App extends Omi.Component {\r\n constructor(data) {\r\n super(data);\r\n this.complexData ={\r\n a:{\r\n b:{\r\n c:[\r\n {\r\n e:[{\r\n name:'ComplexData Support1'\r\n },{\r\n name:'ComplexData Support2'\r\n }]\r\n },\r\n {\r\n name: 'ComplexData Support3'\r\n }\r\n ]\r\n }\r\n }\r\n };\r\n }\r\n\r\n render() {\r\n return `\r\n
\r\n \r\n \r\n
\r\n `;\r\n\r\n }\r\n}\r\n\r\nOmi.render(new App(),\"#container\");\r\n```\r\n\r\nClick me for the complex group-data mapping\r\n\r\n### By object instance\r\n\r\n```js\r\n...\r\nclass App extends Omi.Component {\r\n constructor(data) {\r\n super(data);\r\n }\r\n \r\n installed(){\r\n this.hello.data.name = \"Omi\";\r\n this.update()\r\n }\r\n \r\n render() {\r\n return `\r\n
\r\n \r\n
\r\n `;\r\n }\r\n}\r\n\r\nOmi.render(new App(),\"#container\");\r\n```\r\n\r\n### By omi-id\r\n\r\n```js\r\n...\r\nclass App extends Omi.Component {\r\n constructor(data) {\r\n super(data);\r\n }\r\n \r\n installed(){\r\n Omi.get(\"hello\").data.name = \"Omi\";\r\n this.update()\r\n }\r\n \r\n render() {\r\n return `\r\n
\r\n \r\n
\r\n `;\r\n }\r\n}\r\n\r\nOmi.render(new App(),\"#container\");\r\n```\r\n\r\nBy declaring `omi-id` on the component, we can get the instance of the object anywhere in the program. This can be regarded as any component communication artifacts.\r\n\r\n### Warm Tips\r\n\r\n- The data that passed by `childrenData` or `data` is shadow copied to sub-components. In order to update it, we need to update the `data` attribute of the component instance.\r\n- The data that passed by `data-*` is also shadow copied to sub-components. In order to update it, we need to update the `data` attribute of the component instance.\r\n- If we set the `dataFirst` property of the component instance to `false`, then `data-*` will override the `data` of component instance.\r\n\r\nFor the third tip, please checkout the pseudo-code:\r\n\r\n```js\r\nif(this.dataFirst){\r\n this.data = Object.assign({},data-✼ ,this.data);\r\n}else{\r\n this.data = Object.assign({},this.data, data-✼);\r\n}\r\n```" - -/***/ }, -/* 25 */ -/***/ function(module, exports) { - - module.exports = "## Components\r\n\r\n[Omi](https://github.com/AlloyTeam/omi) is based entirely on component architecture, which allows developers to build web applications like building blocks. Everything is components, components can be nested to create new components.\r\n\r\n![Omi Components System](http://images2015.cnblogs.com/blog/105416/201702/105416-20170210093427338-1536910080.png)\r\n\r\n### Simple Components\r\n\r\nLet's explore a simple Todo example to learn the components system in Omi.\r\n\r\n```js\r\nclass Todo extends Omi.Component {\r\n constructor(data) {\r\n super(data);\r\n }\r\n \r\n add (evt) {\r\n evt.preventDefault();\r\n this.data.items.push(this.data.text);\r\n this.data.text = '';\r\n this.update();\r\n }\r\n\r\n style () {\r\n return `\r\n h3 { color:red; }\r\n button{ color:green;}\r\n `;\r\n }\r\n\r\n handleChange(target){\r\n this.data.text = target.value;\r\n }\r\n\r\n render () {\r\n return `
\r\n

TODO

\r\n
    {{#items}}
  • {{.}}
  • {{/items}}
\r\n
\r\n \r\n \r\n
\r\n
`;\r\n }\r\n}\r\n\r\nOmi.render(new Todo({ items: [] ,text : '' }),\"body\");\r\n```\r\n\r\nThe HTML generated by the component will eventually be inserted into the body. The above example shows some of the features of Omi:\r\n\r\n- Data flow: `data` in `new Todo(data,..)` can be used directly in the template in render method.\r\n- Partial CSS: `h3` in `style()` only effect inside of render. It'll never pollute `h3` outside of this component. The same rule applies to `button`.\r\n- Declarative event binding: `onchange` will call `handleChange` that inside of the component. `this` refers to the current DOM element, `event` refers to the current DOM Event Object.\r\n- You need to manually call the `this.update()` method to update the component\r\n\r\nIt is important to note that, for more freedom and flexibility, Omi does not automatically update DOM while data changes. Developers need to call the `update` method manually.\r\n\r\nYou can also use [oba] (https://github.com/dntzhang/oba) or mobx to implement automatic updates.\r\n\r\nClick me for the live demo\r\n\r\n### Component Nesting\r\n\r\nIt's ok to not use nesting component if your page is super simple. However, for most of webpages and web applications, it is a necessary to define the nesting Components to implement complex features.\r\n\r\nFor instance, we can extract a `List` component form the Todo example. This brings maintainable, scalable and reuseable to our project:\r\n\r\n```js\r\nclass List extends Omi.Component {\r\n constructor(data) {\r\n super(data);\r\n }\r\n\r\n render () {\r\n return `
    {{#items}}
  • {{.}}
  • {{/items}}
`;\r\n }\r\n}\r\n```\r\n\r\nThen how to use this `List`? We need to use `Omi.makeHTML` to make the `List` to a tag which can be used in render method:\r\n\r\n```js\r\nimport List from './list.js';\r\n\r\nOmi.makeHTML('List', List);\r\n\r\nclass Todo extends Omi.Component {\r\n constructor(data) {\r\n super(data);\r\n this.data.length = this.data.items.length;\r\n this.listData = { items : this.data.items };\r\n }\r\n\r\n add (evt) {\r\n evt.preventDefault();\r\n this.list.data.items.push(this.data.text);\r\n this.data.length = this.list.data.items.length;\r\n this.data.text = '';\r\n this.update();\r\n }\r\n\r\n style () {\r\n return `\r\n h3 { color:red; }\r\n button{ color:green;}\r\n `;\r\n }\r\n\r\n handleChange(target){\r\n this.data.text = target.value;\r\n }\r\n\r\n render () {\r\n return `
\r\n

TODO

\r\n \r\n
\r\n \r\n \r\n
\r\n
`;\r\n }\r\n}\r\n```\r\n\r\n- In line 3, we use `makeHTML` to make the component to a tag which can be used in render method. Of course, `Omi.makeHTML('List', List);` can also be written in the end of List component.\r\n- In line 9, the parent component defines the 'listData' property\r\n- In line 34, we use List component in the render method. `name` attribute allows us easily find the instance of the component by using `this`.`data=\"listData\"` attribute allows us easily pass `this.listData` to the sub component from parent component.\r\n\r\nIt should be noted that the `data` passed from `data=\"listData\"` is cloned to the subcomponents by Object.assign(shallow copy) , which means if we want to change the DOM, we recommend that first update the `data` of the instance of subcomponent(not the parent component's `listData` ) and secondly call the `update` method.\r\n\r\nIn fact there are 4 way to communicate between components, it'll be explained later.\r\n\r\nClick me for the live demo\r\n" - -/***/ }, -/* 26 */ -/***/ function(module, exports) { - - module.exports = "## Conditional Rendering\r\n\r\nIn most case, we need to show different layouts according to different states. For example, some users are vip and we need to show vip logo for them. Omi has many ways to meet this kind of requirements.\r\n\r\n### First Option\r\n\r\n```js\r\nclass ConditionTest extends Omi.Component {\r\n constructor(data) {\r\n super(data);\r\n }\r\n\r\n render () {\r\n return `{{#isVip}}\r\n
you are VIP.
\r\n {{/isVip}}\r\n {{^isVip}}\r\n
you are not VIP.
\r\n {{/isVip}}`;\r\n }\r\n}\r\n```\r\n\r\nIn the above case, we use the condition in mustachejs for rendering. Of course Omi does not force you to use mustachejs. You can use omi.lite.js and then override the `Omi.template` method to use any of your favorite template engines.\r\n\r\n### Second Option\r\n\r\n```js\r\nclass ConditionTest extends Omi.Component {\r\n constructor(data) {\r\n super(data);\r\n }\r\n\r\n render () {\r\n if(this.data.isVip){\r\n return '
you are VIP.
';\r\n }else{\r\n return '
you are not VIP.
';\r\n }\r\n }\r\n}\r\n```\r\n\r\n`render` provides a very good programmability, which can write any js code inside. Oh, don't forget that `style` method can also have js code inside it.\r\n\r\n```js\r\nclass ConditionTest extends Omi.Component {\r\n constructor(data) {\r\n super(data);\r\n }\r\n\r\n style (){\r\n if(this.data.isVip){\r\n return 'div{ color : red; }';\r\n }else{\r\n return 'div{ color : green; }';\r\n }\r\n }\r\n\r\n render () {\r\n if(this.data.isVip){\r\n return '
you are VIP.
';\r\n }else{\r\n return '
you are not VIP.
';\r\n }\r\n }\r\n}\r\n```" - -/***/ }, -/* 27 */ -/***/ function(module, exports) { - - module.exports = "## Handling Events\r\n\r\nThere are two types of events in Omi, built-in events and custom events. Built-in events clever use of the browser's own pipeline mechanism, you can easily get events instance and the triggered event elements through `event` and `this`.\r\n\r\n### Built-in events\r\n\r\nWhat is the built-in event? As long as the it can match the following regular expression.\r\n\r\n```js\r\non(abort|blur|cancel|canplay|canplaythrough|change|click|close|contextmenu|cuechange|dblclick|drag|dragend|dragenter|dragleave|dragover|dragstart|drop|durationchange|emptied|ended|error|focus|input|invalid|keydown|keypress|keyup|load|loadeddata|loadedmetadata|loadstart|mousedown|mouseenter|mouseleave|mousemove|mouseout|mouseover|mouseup|mousewheel|pause|play|playing|progress|ratechange|reset|resize|scroll|seeked|seeking|select|show|stalled|submit|suspend|timeupdate|toggle|volumechange|waiting|autocomplete|autocompleteerror|beforecopy|beforecut|beforepaste|copy|cut|paste|search|selectstart|wheel|webkitfullscreenchange|webkitfullscreenerror|touchstart|touchmove|touchend|touchcancel|pointerdown|pointerup|pointercancel|pointermove|pointerover|pointerout|pointerenter|pointerleave)\r\n```\r\n\r\nHow to bind built-in events? As follows:\r\n\r\n```js\r\nclass EventTest extends Omi.Component {\r\n constructor(data) {\r\n super(data);\r\n }\r\n\r\n handleClick(dom, evt){\r\n alert(dom.innerHTML);\r\n }\r\n\r\n render () {\r\n return `
Hello, Omi!
`;\r\n }\r\n}\r\n```\r\n\r\n### Custom events\r\n\r\nEvents that defined by developers is the custom events. Here is the pagination example:\r\n\r\n```js\r\nimport Omi from '../../src/index.js';\r\nimport Pagination from './pagination.js';\r\nimport Content from './content.js';\r\n\r\nOmi.makeHTML('Pagination', Pagination);\r\nOmi.makeHTML('Content', Content);\r\n\r\nclass Main extends Omi.Component {\r\n constructor(data) {\r\n super(data);\r\n }\r\n\r\n installed(){\r\n this.content.goto(this.pagination.data.currentPage+1);\r\n }\r\n \r\n handlePageChange(index){\r\n this.content.goto(index+1);\r\n }\r\n\r\n render () {\r\n return `
\r\n

Pagination Example

\r\n \r\n \r\n
`;\r\n }\r\n}\r\n\r\nOmi.render( new Main(),'body');\r\n```\r\n\r\nAs we can see, the `onPageChange` is a custom event, `handlePageChange` will being executed when `onPageChange` is triggered. The `onPageChange` method is executed in `Pagination`:\r\n\r\n```js\r\nimport Omi from '../../src/index.js';\r\n\r\nclass Pagination extends Omi.Component {\r\n ...\r\n ...\r\n ...\r\n linkTo: \"#\",\r\n prevText: \"Prev\",\r\n nextText: \"Next\",\r\n ellipseText: \"...\",\r\n prevShow: true,\r\n nextShow: true,\r\n onPageChange: function () { return false; }\r\n }, this.data);\r\n\r\n this.pageNum = Math.ceil(this.data.total / this.data.pageSize);\r\n }\r\n \r\n goto (index,evt) {\r\n evt.preventDefault();\r\n this.data.currentPage=index;\r\n this.update();\r\n this.data.onPageChange(index);\r\n }\r\n ...\r\n ...\r\n ...\r\n}\r\n```\r\n\r\nThis is a part of `Pagination` code. Highlight is the place to execute `onPageChange`.\r\n\r\n### Links\r\n\r\n- [Demo](http://alloyteam.github.io/omi/example/pagination/)\r\n- [Source](https://github.com/AlloyTeam/omi/tree/master/example/pagination)" - -/***/ }, -/* 28 */ -/***/ function(module, exports) { - - module.exports = "## Forms\r\n\r\nIt's much more convenient to control forms in Omi, especially `\r\n \r\n \r\n \r\n \r\n\r\n```\r\n\r\nThe third option is selected because it is being set to `selected` attribute. The problem is that developers need to traversed each option. While using Omi, you can write code like this:\r\n\r\n```html\r\n\r\n```\r\n\r\nThis will achieve the same effect. For example, you want to choose the first item:\r\n\r\n```html\r\n\r\n```\r\n\r\nIsn't it very convenient?\r\n\r\n### For Example\r\n\r\n```js\r\nclass FormTest extends Omi.Component {\r\n constructor(data) {\r\n super(data);\r\n \r\n }\r\n\r\n handleChange(target){\r\n console.log(target.value)\r\n this.data.value = target.value;\r\n }\r\n\r\n handleSubmit(evt) {\r\n alert('Your favorite flavor is: ' + this.data.value);\r\n evt.preventDefault();\r\n }\r\n \r\n render () {\r\n return `\r\n
\r\n \r\n \r\n
`;\r\n }\r\n}\r\n\r\nOmi.render(new FormTest({ value: 'mango' }),'#container');\r\n```\r\n\r\nClick me for a live demo" - -/***/ }, -/* 29 */ -/***/ function(module, exports) { - - module.exports = "## Get DOM\r\n\r\nWhile most of the time, developers do not need to find the DOM, but sometimes is a need to get the DOM.\r\n\r\nOmi provides a way to get the DOM node.\r\n\r\n### ref and refs\r\n\r\n```js\r\nclass Hello extends Omi.Component {\r\n constructor(data) {\r\n super(data);\r\n }\r\n \r\n style () {\r\n return `\r\n h1{\r\n cursor:pointer;\r\n }\r\n `;\r\n }\r\n \r\n handleClick(){\r\n alert(this.refs.abc.innerHTML);\r\n }\r\n \r\n render() {\r\n return `\r\n
\r\n

Hello ,{{name}}!

\r\n
\r\n `;\r\n }\r\n}\r\n\r\nOmi.render(new Hello({ name : \"Omi\" }),\"#container\");\r\n```\r\n\r\nAs we can see, by referencing `ref` as `abc` in HTML, the DOM node can be accessed through `this.refs.abc`.\r\n\r\nClick me for the live demo\r\n" - -/***/ }, -/* 30 */ -/***/ function(module, exports) { - - module.exports = "## Hello World\r\n\r\n### Hello World with ES20XX \r\n\r\nWe recommend using a bundler like [webpack](https://webpack.github.io/) or [Browserify](http://browserify.org/) so you can write modular code and bundle it together into small packages to optimize load time.\r\n\r\nThe small Omi example looks like this:\r\n\r\n```js\r\nimport Omi from './omi.js';\r\n\r\nclass Hello extends Omi.Component {\r\n constructor(data) {\r\n super(data);\r\n }\r\n \r\n style () {\r\n return `\r\n h1{\r\n cursor:pointer;\r\n }\r\n `;\r\n }\r\n \r\n handleClick(target){\r\n alert(target.innerHTML);\r\n }\r\n \r\n render() {\r\n return `\r\n
\r\n

Hello ,{{name}}!

\r\n
\r\n `;\r\n }\r\n}\r\n\r\nOmi.render(new Hello({ name : \"Omi\" }),\"body\");\r\n```\r\n\r\nThis code renders into body element. \r\n\r\n### Hello World with ES5\r\n\r\n```html\r\n\r\n```\r\n\r\nthen:\r\n\r\n```js\r\nvar Hello = Omi.create(\"Hello\", {\r\n style: function () {\r\n return \"h1{ cursor:pointer }\";\r\n },\r\n \r\n handleClick: function (dom) {\r\n alert(dom.innerHTML)\r\n },\r\n \r\n render: function () {\r\n return '
\\\r\n

\\\r\n Hello ,{{name}}!\\\r\n

\\\r\n
'\r\n }\r\n});\r\n\r\nvar Test = Omi.create(\"Test\", {\r\n render: function () {\r\n return '
\\\r\n
Test
\\\r\n \\\r\n
'\r\n }\r\n});\r\n\r\nOmi.render(new Test(),'#container');\r\n```" - -/***/ }, -/* 31 */ -/***/ function(module, exports) { - - module.exports = "## Inheritance\r\n\r\nThrough the inheritance mechanism, we can define new classes base on old classes. The new classes not only have newly defined members, but also have old members at the same time.\r\n\r\nWe call the existing class the base class, also known as the parent class. And the new class derived from the existing class is called a derived class, also known as a subclass.\r\n\r\n### For Example\r\n\r\n```js\r\nclass Hello extends Omi.Component {\r\n constructor(data) {\r\n super(data);\r\n }\r\n \r\n style () {\r\n return `\r\n div{\r\n cursor:pointer;\r\n }\r\n `;\r\n }\r\n \r\n handleClick(target, evt){\r\n alert(target.innerHTML);\r\n }\r\n \r\n render() {\r\n return '
Hello {{name}}!
'\r\n }\r\n}\r\n\r\nclass SubHello extends Hello {\r\n constructor(data) {\r\n super(data);\r\n }\r\n}\r\n\r\nOmi.render(new SubHello({ name : 'Omi' }),'#container');\r\n```\r\n\r\nClick me for the live demo\r\n\r\n### inherit in ES5\r\n\r\n```js\r\nvar Hello = Omi.create(\"Hello\",{\r\n render:function(){\r\n return '
Hello {{name}}!
'\r\n }\r\n})\r\n\r\nvar SubHello = Omi.create(\"SubHello\",Hello,{ });\r\n\r\n\r\nOmi.render(new SubHello({ name : 'Omi' }),'#container');\r\n```\r\n\r\nClick me for the live demo" - -/***/ }, -/* 32 */ -/***/ function(module, exports) { - - module.exports = "## Installation\r\n\r\n[Omi](https://github.com/AlloyTeam/omi) is open and modern framework for building user interfaces.\r\n\r\n### Installing Omi\r\n\r\nWe recommend using [npm](https://www.npmjs.com/) for managing front-end dependencies. If you're new to package managers.\r\n\r\nTo install Omi with npm, run:\r\n\r\n``` js\r\n$ npm install omi\r\n```\r\n### omi-cli\r\n\r\n``` js\r\n$ npm install omi-cli -g \r\n$ omi init your_project_name \r\n$ cd your_project_name \r\n$ npm run dev \r\n$ npm run dist \r\n```" - -/***/ }, -/* 33 */ -/***/ function(module, exports) { - - module.exports = "## Lifecycle\r\n\r\n| Name | Meaning | Occasion |\r\n| :-------------: | :-------------: | :-----: |\r\n| constructor | The constructor | When new a constructor |\r\n| install | The installation. We can process the data that user pass | When instantiate |\r\n| installed | Complete the installation. It'll trigger after HTML being inserted to the page. Please note that it'll trigger when component being removed and restored | **Instantiation and existence** |\r\n| uninstall | Uninstall the component. It'll trigger when remove is executed | When destroy |\r\n| beforeUpdate | Before update | When existence |\r\n| afterUpdate | After update | When existence |\r\n\r\n## Illustration\r\n\r\n![lc](http://images2015.cnblogs.com/blog/105416/201703/105416-20170322084234049-1482108845.jpg)\r\n\r\nIt should be noted that the installed will be executed during the instantiation, which is not shown above. For example, it'll executed when a component is removed and restored, or when the new component is being added.\r\n\r\n### Examples\r\n\r\n```js\r\nclass Timer extends Omi.Component {\r\n constructor(data) {\r\n super(data);\r\n }\r\n\r\n install () {\r\n this.data = {secondsElapsed: 0};\r\n }\r\n\r\n tick() {\r\n this.data.secondsElapsed++;\r\n this.update();\r\n }\r\n\r\n installed(){\r\n this.interval = setInterval(() => this.tick(), 1000);\r\n }\r\n\r\n uninstall() {\r\n clearInterval(this.interval);\r\n }\r\n\r\n\r\n style () {\r\n return `\r\n .num { color:red; }\r\n `;\r\n }\r\n\r\n render () {\r\n return `
Seconds Elapsed: {{secondsElapsed}}
`;\r\n }\r\n}\r\n```\r\n\r\nClick me for the live demo" - -/***/ }, -/* 34 */ -/***/ function(module, exports) { - - module.exports = "## Loop\r\n\r\nThe following describes how to traverses in mustache.js and javascript.\r\n\r\n### First Option\r\n\r\n```js\r\nclass List extends Omi.Component {\r\n constructor(data) {\r\n super(data);\r\n }\r\n\r\n render () {\r\n return `
\r\n
    \r\n {{#items}} \r\n
  • {{text}}
  • \r\n {{/items}}\r\n
\r\n
`;\r\n }\r\n}\r\n\r\nOmi.render(new List({\r\n items: [\r\n {id: 1, text: 'Omi'},\r\n {id: 2, text: 'dntzhang'},\r\n {id: 3, text: 'AlloyTeam'}\r\n ]\r\n}),\"body\");\r\n```\r\n\r\nMustache.js more detailed loop traversal use can see \r\n\r\nFor more details for traversal in mustache.js please view [https://github.com/janl/mustache.js#non-empty-lists](https://github.com/janl/mustache.js#non-empty-lists).\r\n\r\nFor example, it also support:\r\n\r\n- If each item of items is a string, you can directly use **{{.}}** to output each item\r\n- Call the defined function when looping\r\n\r\nClick me for the live demo\r\n\r\n### Second Option\r\n\r\nOf course, you can also use template string inside the `map`:\r\n\r\n```js\r\nclass List extends Omi.Component {\r\n constructor(data) {\r\n super(data);\r\n }\r\n\r\n render() {\r\n return `
\r\n
    \r\n ${this.data.items.map(item =>\r\n `
  • ${item.text}
  • `\r\n ).join('')}\r\n
\r\n
`;\r\n }\r\n}\r\n\r\nOmi.render(new List({\r\n items: [\r\n {id: 1, text: 'Omi'},\r\n {id: 2, text: 'dntzhang'},\r\n {id: 3, text: 'AlloyTeam'}\r\n ]\r\n}),\"body\");\r\n```\r\n\r\nYou will see the following page:\r\n\r\n![pv](http://images2015.cnblogs.com/blog/105416/201701/105416-20170122095724129-2059595233.png)\r\n\r\nClick me for the live demo" - -/***/ }, -/* 35 */ -/***/ function(module, exports) { - - module.exports = "## Plugin\r\n\r\n[Omi](https://github.com/AlloyTeam/omi) is a componentized web framework. Then what is plugin?\r\n\r\nIt can be understood that the Omi plugin system can give the dom element some ability and can be associated with the instance of the components.\r\n\r\n### omi-drag\r\n\r\nLet's see this example:\r\n\r\nClick me for the live deme\r\n\r\n```js\r\nimport OmiDrag from './omi-drag.js';\r\n\r\nOmiDrag.init();\r\n\r\nclass App extends Omi.Component {\r\n constructor(data) {\r\n super(data);\r\n }\r\n\r\n render() {\r\n return `\r\n
\r\n
Drag Me
\r\n
\r\n `;\r\n\r\n }\r\n\r\n style(){\r\n return `\r\n .test{\r\n width:100px;\r\n height:100px;\r\n color:white;\r\n line-height:90px;\r\n text-align:center;\r\n background-color:#00BFF3;\r\n }\r\n `\r\n }\r\n}\r\n\r\nOmi.render(new App(),\"#container\");\r\n```\r\n\r\nAs shown above, by adding `omi-drag` attribute to the div, it can be dragged by the user using the mouse. We call omi-drag.js an omi plugin.\r\n\r\nIsn't it very convenient? So how did this omi-drag implement?\r\n\r\n如上面的代码所示,通过在div上标记omi-drag,这个div就能够被用户使用鼠标拖拽。我们称omi-drag.js为omi插件。\r\n是不是非常方便?那么这个omi-drag是怎么实现的?\r\n\r\n## Omi.extendPlugin\r\n\r\nCore method: Omi.extendPlugin( pluginName, handler )\r\n\r\nThe following code shows how to use `Omi.extendPlugin` to give dom the drap and drop ability:\r\n\r\n```js\r\n;(function () {\r\n\r\n var OmiDrag = {};\r\n var Omi = typeof require === 'function'\r\n ? require('omi')\r\n : window.Omi;\r\n\r\n OmiDrag.init = function(){\r\n Omi.extendPlugin('omi-drag',function(dom, instance){\r\n dom.style.cursor='move';\r\n var isMouseDown = false,\r\n preX = null,\r\n preY = null,\r\n currentX = null,\r\n currentY = null,\r\n translateX = 0,\r\n translateY = 0;\r\n\r\n dom.addEventListener('mousedown',function(evt){\r\n isMouseDown = true;\r\n preX = evt.pageX;\r\n preY = evt.pageY;\r\n evt.stopPropagation();\r\n },false);\r\n\r\n window.addEventListener('mousemove',function(evt){\r\n if(isMouseDown){\r\n currentX = evt.pageX;\r\n currentY = evt.pageY;\r\n if(preX != null){\r\n translateX += currentX - preX;\r\n translateY += currentY - preY;\r\n dom.style.transform = 'translateX('+translateX+'px) translateY('+translateY+'px)';\r\n }\r\n preX = currentX;\r\n preY = currentY;\r\n evt.preventDefault();\r\n }\r\n },false);\r\n\r\n window.addEventListener('mouseup',function(){\r\n isMouseDown = false;\r\n preX = preY = currentX = currentY = null;\r\n },false);\r\n });\r\n }\r\n\r\n OmiDrag.destroy = function(){\r\n delete Omi.plugins['omi-drag'];\r\n };\r\n\r\n if (typeof exports == \"object\") {\r\n module.exports = OmiDrag;\r\n } else if (typeof define == \"function\" && define.amd) {\r\n define([], function(){ return OmiDrag });\r\n } else {\r\n window.OmiDrag = OmiDrag;\r\n }\r\n\r\n})();\r\n```\r\n\r\nMethod: Omi.extendPlugin( pluginName, handler )\r\n\r\n`pluginName` is the name of the plugin.\r\n\r\n`handler` is the processor. The handler can get the dom which marked as the `pluginName` and the instance of the component.\r\n\r\nWith `Omi.extendPlugin`, we can give the dom some ability, and can also be associated with the component instance.\r\n\r\nThe above example is not associated with the instance, let's try it:\r\n\r\n## Associated with instance\r\n\r\nWe want to be able to listen to the `move` inside the component and perform a callback. As follows:\r\n\r\n```js\r\n...\r\n...\r\nmoveHandler(){\r\n console.log('moving');\r\n}\r\n\r\nrender() {\r\n return `\r\n
\r\n
Drag Me
\r\n
\r\n `;\r\n}\r\n...\r\n```\r\n\r\nIn this case, the `moveHandler` will be continually executed while dragging. We can modify some code to solve this issue:\r\n\r\n```js\r\n...\r\nwindow.addEventListener('mousemove',function(evt){\r\n if(isMouseDown){\r\n currentX = evt.pageX;\r\n currentY = evt.pageY;\r\n if(preX != null){\r\n translateX += currentX - preX;\r\n translateY += currentY - preY;\r\n dom.style.transform = 'translateX('+translateX+'px) translateY('+translateY+'px)';\r\n }\r\n preX = currentX;\r\n preY = currentY;\r\n evt.preventDefault();\r\n instance.moveHandler(evt);\r\n }\r\n},false);\r\n```\r\n\r\nWe add `instance.moveHandler(evt)` method to execute the `moveHandler` method of component instance.\r\n\r\nThis is how associated with instance works.\r\n\r\nHowever, this may still have an issue if we add `omi-drag` to a list of `div`:\r\n\r\n```js\r\n...\r\nrender() {\r\n return `\r\n
\r\n
Drag Me
\r\n
Drag Me
\r\n
\r\n `;\r\n}\r\n...\r\n```\r\n\r\nUsually each of our `omi-drag` can correspond to a callback function, such as:\r\n\r\n```js\r\n...\r\n...\r\nmoveHandlerA(){\r\n console.log('moving');\r\n}\r\n\r\nmoveHandlerB(){\r\n console.log('moving');\r\n}\r\n\r\nrender() {\r\n return `\r\n
\r\n
Drag Me A
\r\n
Drag Me B
\r\n
\r\n `;\r\n}\r\n...\r\n```\r\n\r\nHow to achieve this? We can pass the data to the plugin via dom.\r\n\r\n## Passing data\r\n\r\nLet's see the final code:\r\n\r\n```js\r\n...\r\n...\r\nmoveHandlerA(){\r\n console.log('moving');\r\n}\r\n\r\nmoveHandlerB(){\r\n console.log('moving');\r\n}\r\n\r\nrender() {\r\n return `\r\n
\r\n
Drag Me A
\r\n
Drag Me B
\r\n
\r\n `;\r\n}\r\n...\r\n```\r\n\r\nWhere `omi-drag` modified:\r\n\r\n```js\r\n...\r\nvar handlerName = dom.getAttribute('dragMove');\r\n\r\nwindow.addEventListener('mousemove',function(evt){\r\n if(isMouseDown){\r\n currentX = evt.pageX;\r\n currentY = evt.pageY;\r\n if(preX != null){\r\n translateX += currentX - preX;\r\n translateY += currentY - preY;\r\n dom.style.transform = 'translateX('+translateX+'px) translateY('+translateY+'px)';\r\n }\r\n preX = currentX;\r\n preY = currentY;\r\n evt.preventDefault();\r\n instance[handlerName](evt);\r\n }\r\n},false);\r\n...\r\n```\r\n\r\n- We use `var handlerName = dom.getAttribute('dragMove')` to get the `dragMove` of dom\r\n- We use `instance[handlerName](evt)` to execute the method\r\n\r\nClick me for the live demo\r\n\r\n## More plugins\r\n\r\n* [omi-finger](https://github.com/AlloyTeam/omi/tree/master/plugins/omi-finger) The [AlloyFinger](https://github.com/AlloyTeam/AlloyFinger) plugin for Omi, which support touch events and gustures\r\n* [omi-transform](https://github.com/AlloyTeam/omi/tree/master/plugins/omi-transform) The [transformjs](http://alloyteam.github.io/AlloyTouch/transformjs/) plugin for Omi, which can easily set CSS3 Transform to DOM\r\n* [omi-touch](https://github.com/AlloyTeam/omi/tree/master/plugins/omi-touch) The [AlloyTouch](https://github.com/AlloyTeam/AlloyTouch) plugin for Omi. The touch movement solution for Omi (support touch scroll, rotate, flip, select, etc.)\r\n* [omi-jquery-date-picker](https://github.com/AlloyTeam/omi/tree/master/plugins/omi-jquery-date-picker) The date picker plugin for Omi, which support choose any time zone\r\n" - -/***/ }, -/* 36 */ -/***/ function(module, exports) { - - module.exports = "## Templates\r\n\r\nThere are three types of Omi. omi.js and omi.lite.js is for web side.\r\n\r\n- omi.js has a built-in [mustache.js](https://github.com/janl/mustache.js) as the template engine\r\n- omi.lite.js doesn't have any template engines\r\n\r\nOmi does not force developers to use mustache.js, you can use any template engine based on business scenarios or do not use any template engines.\r\n\r\nHow to use other template engines? Let's see the [artTemplate](https://github.com/aui/artTemplate) example.\r\n\r\n### Use artTemplate\r\n\r\n```js\r\nOmi.template = function(tpl, data){\r\n return artTemplate.compile(tpl)(data);\r\n}\r\n```\r\n\r\nWe need to rewrite the `Omi.template` method, the `tpl` is the incoming template, the `data` is the required data for the template, and the return value is HTML.\r\n\r\nAfter rewriting, you can use the artTemplate syntax in `render`, such as:\r\n\r\n```js\r\nclass List extends Omi.Component {\r\n constructor(data) {\r\n super(data);\r\n }\r\n\r\n style () {\r\n return `\r\n h1 { color:red; }\r\n li{ color:green;}\r\n `;\r\n }\r\n\r\n render () {\r\n return `

{{title}}

\r\n
    \r\n {{each list as value i}}\r\n
  • # {{i + 1}} :{{value}}
  • \r\n {{/each}}\r\n
`;\r\n }\r\n}\r\n```\r\n\r\n### Links\r\n\r\n* [Demo Link](http://alloyteam.github.io/omi/example/artTemplate/)\r\n* [Source Code](https://github.com/AlloyTeam/omi/tree/master/example/artTemplate)" - -/***/ }, -/* 37 */ -/***/ function(module, exports) { - - module.exports = "## Thinking in Omi\r\n\r\nOmi is based on object-oriented programming, with plugin system.\r\n\r\nThe traditional one-way data flow or the event-throwing component communicating can increase the stability of the system, but it loses it's flexibility. To a certain extent also reduced the component reusing.\r\n\r\nObject-oriented system has an other logical layer, which let you control the instance of components. The logic between instances build the entire program.\r\n\r\nThen the issues like communication, reusing and logics between components are all solved.\r\n\r\n\r\nPlus, the component is also more single duty, more loosely coupled.\r\n\r\nFor functional programming, imperative programming and object-oriented programming, we can sum up the following list:\r\n\r\n- Imperative programming is well understood, we use loop and if-else condition to control processes, it emphasize the process of execution\r\n- Imperative programming is hardware friendly, easy to run, but hard to design complex program\r\n- Functional programming is all about input and output, not the process of execution\r\n- Functional programming advocates multiple simple execution units into complex operations\r\n- Object-oriented programming uses objects as the basic unit of the program, with more reusability, flexibility, and extensibility\r\n\r\nWhat kind of language is JavaScript? We have `class` in ES6+, so is JavaScript object-oriented language?\r\n\r\nJavaScript can pass a function as a argumant, so is JavaScript a functional language?\r\n\r\nThere are no right answer, it depands on how you use JavaScript.\r\n\r\nIt's free to chooce, you can use functional programming framework like React, or object-oriented framework like Omi. \r\n\r\n### Functional Programming VS Object-Oriented Programming\r\n\r\nIn the UI component framework scope, functional programming is represented by React, while Omi belongs to object-oriented programming.\r\n\r\nSo what are their strengths and weaknesses? The following is a comparison (in fact, functional programming and object-oriented programming comparison):\r\n\r\n| | React | Omi |\r\n| ------------- |:-------------:|:-----:|\r\n| Component communication | ★★★★☆| ★★★★★ |\r\n| Stability | ★★★★★ | ★★★★☆ |\r\n| Flexibility | ★★★★☆| ★★★★★ |\r\n| Scalability | ★★★★☆ | ★★★★★ |\r\n| Testability | ★★★★★ | ★★★★☆ |\r\n| File size | ★★★☆☆ | ★★★★★ |\r\n| Features | ★★★☆☆ | ★★★★☆ |\r\n| DOM performance | ★★★★★ | ★★★★☆ |\r\n| Animation performance | ★★★★☆ | ★★★★★ |\r\n| Abstract complexity | ★★★★☆ | ★★★★★ |\r\n| Asynchronous programming | ★★★★★ | ★★★★☆ |\r\n\r\nAs we can see, we can not have it both ways. Object-oriented programming is more reusable, flexible and scalable, the problem is more difficult to test.\r\n\r\nSpecifically, if the functional programming, the test area is state1 + state2 + ... + stateN; in object-oriented programming, the test area is state1 × event1 + state2 × event2 + ... + stateN × eventN.\r\n\r\nIn summary, it is more recommended to use the object-oriented programming to build UI component framework.\r\n\r\n
\r\n\r\n### The end. Thanks for reading. [Let's start the Omi journey](https://github.com/AlloyTeam/omi)!\r\n" - -/***/ }, -/* 38 */ -/***/ function(module, exports, __webpack_require__) { - - 'use strict'; - - Object.defineProperty(exports, "__esModule", { - value: true - }); - - var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); - - var _omi = __webpack_require__(2); - - var _omi2 = _interopRequireDefault(_omi); - - var _index = __webpack_require__(39); - - var _index2 = _interopRequireDefault(_index); - - var _config = __webpack_require__(4); - - var _config2 = _interopRequireDefault(_config); - - function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - - function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } - - function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; } - - function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } - - _omi2.default.makeHTML('List', _index2.default); - - var Sidebar = function (_Omi$Component) { - _inherits(Sidebar, _Omi$Component); - - function Sidebar(data) { - _classCallCheck(this, Sidebar); - - return _possibleConstructorReturn(this, (Sidebar.__proto__ || Object.getPrototypeOf(Sidebar)).call(this, data)); - } - - _createClass(Sidebar, [{ - key: 'install', - value: function install() { - this.data.items = _config2.default['menus'][this.data.lan]; - this.data.height = window.innerHeight - 45; - } - }, { - key: 'style', - value: function style() { - return __webpack_require__(42); - } - }, { - key: 'render', - value: function render() { - return __webpack_require__(43); - } - }]); - - return Sidebar; - }(_omi2.default.Component); - - exports.default = Sidebar; - -/***/ }, -/* 39 */ -/***/ function(module, exports, __webpack_require__) { - - 'use strict'; - - Object.defineProperty(exports, "__esModule", { - value: true - }); - - var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); - - var _omi = __webpack_require__(2); - - var _omi2 = _interopRequireDefault(_omi); - - function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - - function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } - - function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; } - - function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } - - var tpl = __webpack_require__(40); - var css = __webpack_require__(41); - - var List = function (_Omi$Component) { - _inherits(List, _Omi$Component); - - function List(data) { - _classCallCheck(this, List); - - var _this = _possibleConstructorReturn(this, (List.__proto__ || Object.getPrototypeOf(List)).call(this, data)); - - _omi2.default.mixIndexToArray(_this.data.list); - _this.data.currentIndex = 0; - var self = _this; - _this.data.isCurrent = function () { - return this.index === self.data.currentIndex && self.data.active; - }; - return _this; - } - - _createClass(List, [{ - key: 'goto', - value: function goto(name, index) { - var _this2 = this; - - _omi2.default.get('content').data.name = name; - _omi2.default.get('content').update(); - this.data.currentIndex = index; - this.parent.children.forEach(function (child, index) { - child.data.active = false; - if (child.id === _this2.id) { - _omi2.default.get('pager').activeIndex = index; - child.data.active = true; - } - child.update(); - }); - _omi2.default.get('pager').currentIndex = index; - _omi2.default.get('pager').update(); - document.body.scrollTop = 0; - } - }, { - key: 'render', - value: function render() { - return tpl; - } - }, { - key: 'style', - value: function style() { - return css; - } - }]); - - return List; - }(_omi2.default.Component); - - exports.default = List; - -/***/ }, -/* 40 */ -/***/ function(module, exports) { - - module.exports = "" - -/***/ }, -/* 41 */ -/***/ function(module, exports) { - - module.exports = "li.title{ font-size: 16px; font-weight: bold; margin-bottom:10px; margin-top:10px; text-indent: 23px;}li{ margin-bottom:3px; text-indent: 33px;}li a{ display:block; font-size:14px; height:20px; line-height:20px; color: #666;}li a.current{ background-color:#c3d4fc; color:white;}li a:hover{ background-color:#b3d4fc; color:white;}" - -/***/ }, -/* 42 */ -/***/ function(module, exports) { - - module.exports = "@media only screen and (max-width: 768px) { .list{ transform: translateX(-100%); background-color:white; -moz-transition: all .6s ease; -o-transition: all .6s ease; -webkit-transition: all .6s ease; transition: all .6s ease; } .list.show { -moz-transform: translateX(0%) translateZ(0); -ms-transform: translateX(0%) translateZ(0); -o-transform: translateX(0%) translateZ(0); -webkit-transform: translateX(0%) translateZ(0); transform: translateX(0%) translateZ(0); }}.list{ width:200px; text-indent: 20px; border-right: 1px solid #eee; overflow-x: hidden; overflow-y: auto; position:fixed; top:45px;}.version{ height:20px;}" - -/***/ }, -/* 43 */ -/***/ function(module, exports) { - - module.exports = "
{{#items}} {{/items}}
" - -/***/ }, -/* 44 */ -/***/ function(module, exports, __webpack_require__) { - - 'use strict'; - - Object.defineProperty(exports, "__esModule", { - value: true - }); - - var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); - - var _omi = __webpack_require__(2); - - var _omi2 = _interopRequireDefault(_omi); - - var _omiFinger = __webpack_require__(45); - - var _omiFinger2 = _interopRequireDefault(_omiFinger); - - function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - - function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } - - function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; } - - function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } - - var tpl = __webpack_require__(47); - var css = __webpack_require__(48); - - _omiFinger2.default.init(); - - var Head = function (_Omi$Component) { - _inherits(Head, _Omi$Component); - - function Head(data) { - _classCallCheck(this, Head); - - return _possibleConstructorReturn(this, (Head.__proto__ || Object.getPrototypeOf(Head)).call(this, data)); - } - - _createClass(Head, [{ - key: 'install', - value: function install() { - var _this2 = this; - - this.data.isEnLan = this.data.lan === 'en'; - document.body.addEventListener('touchend', function () { - setTimeout(function () { - _this2.removeClass(_omi2.default.get('sidebar').node, 'show'); - }, 300); - }, false); - } - }, { - key: 'toggleMenus', - value: function toggleMenus(evt) { - this.toggleClass(_omi2.default.get('sidebar').node, 'show'); - evt.stopPropagation(); - } - }, { - key: 'handleTouchEnd', - value: function handleTouchEnd(evt) { - evt.stopPropagation(); - } - }, { - key: 'toggleClass', - value: function toggleClass(element, className) { - if (!element || !className) { - return; - } - - var classString = element.className, - nameIndex = classString.indexOf(className); - if (nameIndex == -1) { - classString += ' ' + className; - } else { - classString = classString.substr(0, nameIndex) + classString.substr(nameIndex + className.length); - } - element.className = classString; - } - }, { - key: 'removeClass', - value: function removeClass(element, className) { - var classString = element.className, - nameIndex = classString.indexOf(className); - if (nameIndex !== -1) { - classString = classString.substr(0, nameIndex) + classString.substr(nameIndex + className.length); - } - element.className = classString; - } - }, { - key: 'style', - value: function style() { - return css; - } - }, { - key: 'render', - value: function render() { - return tpl; - } - }]); - - return Head; - }(_omi2.default.Component); - - exports.default = Head; - -/***/ }, -/* 45 */ -/***/ function(module, exports, __webpack_require__) { - - /*! - * omi-finger v0.1.3 by dntzhang - * Omi / AlloyFinger integration. Support touch and gesture events in your Omi project. - * Github: https://github.com/AlloyTeam/omi - * MIT Licensed. - */ - - ;(function () { - - var OmiFinger = {}; - var AlloyFinger = true - ? __webpack_require__(46) - : window.AlloyFinger; - var Omi = true - ? __webpack_require__(2) - : window.Omi; - - var noop = function(){ - - }; - - var getHandler = function(name, dom, instance) { - var value = dom.getAttribute(name); - if (value === null) { - return noop; - }else{ - return instance[value].bind(instance); - } - }; - - - OmiFinger.init = function(){ - Omi.extendPlugin('omi-finger',function(dom, instance){ - if(!instance.alloyFingerInstances)instance.alloyFingerInstances = []; - var len = instance.alloyFingerInstances.length; - var i = 0 ; - for(;i 1) r = 1; - return Math.acos(r); - } - - function cross(v1, v2) { - return v1.x * v2.y - v2.x * v1.y; - } - - function getRotateAngle(v1, v2) { - var angle = getAngle(v1, v2); - if (cross(v1, v2) > 0) { - angle *= -1; - } - - return angle * 180 / Math.PI; - } - - var HandlerAdmin = function(el) { - this.handlers = []; - this.el = el; - }; - - HandlerAdmin.prototype.add = function(handler) { - this.handlers.push(handler); - } - - HandlerAdmin.prototype.del = function(handler) { - if(!handler) this.handlers = []; - - for(var i=this.handlers.length; i>=0; i--) { - if(this.handlers[i] === handler) { - this.handlers.splice(i, 1); - } - } - } - - HandlerAdmin.prototype.dispatch = function() { - for(var i=0,len=this.handlers.length; i 0 && this.delta <= 250 && Math.abs(this.preTapPosition.x - this.x1) < 30 && Math.abs(this.preTapPosition.y - this.y1) < 30); - } - this.preTapPosition.x = this.x1; - this.preTapPosition.y = this.y1; - this.last = this.now; - var preV = this.preV, - len = evt.touches.length; - if (len > 1) { - this._cancelLongTap(); - this._cancelSingleTap(); - var v = { x: evt.touches[1].pageX - this.x1, y: evt.touches[1].pageY - this.y1 }; - preV.x = v.x; - preV.y = v.y; - this.pinchStartLen = getLen(preV); - this.multipointStart.dispatch(evt); - } - this.longTapTimeout = setTimeout(function () { - this.longTap.dispatch(evt); - }.bind(this), 750); - }, - move: function (evt) { - if (!evt.touches) return; - var preV = this.preV, - len = evt.touches.length, - currentX = evt.touches[0].pageX, - currentY = evt.touches[0].pageY; - this.isDoubleTap = false; - if (len > 1) { - var v = { x: evt.touches[1].pageX - currentX, y: evt.touches[1].pageY - currentY }; - - if (preV.x !== null) { - if (this.pinchStartLen > 0) { - evt.scale = getLen(v) / this.pinchStartLen; - this.pinch.dispatch(evt); - } - - evt.angle = getRotateAngle(v, preV); - this.rotate.dispatch(evt); - } - preV.x = v.x; - preV.y = v.y; - } else { - if (this.x2 !== null) { - evt.deltaX = currentX - this.x2; - evt.deltaY = currentY - this.y2; - - } else { - evt.deltaX = 0; - evt.deltaY = 0; - } - this.pressMove.dispatch(evt); - } - - this.touchMove.dispatch(evt); - - this._cancelLongTap(); - this.x2 = currentX; - this.y2 = currentY; - if (len > 1) { - evt.preventDefault(); - } - }, - end: function (evt) { - if (!evt.changedTouches) return; - this._cancelLongTap(); - var self = this; - if (evt.touches.length < 2) { - this.multipointEnd.dispatch(evt); - } - this.touchEnd.dispatch(evt); - //swipe - if ((this.x2 && Math.abs(this.x1 - this.x2) > 30) || - (this.y2 && Math.abs(this.y1 - this.y2) > 30)) { - evt.direction = this._swipeDirection(this.x1, this.x2, this.y1, this.y2); - this.swipeTimeout = setTimeout(function () { - self.swipe.dispatch(evt); - - }, 0) - } else { - this.tapTimeout = setTimeout(function () { - self.tap.dispatch(evt); - // trigger double tap immediately - if (self.isDoubleTap) { - self.doubleTap.dispatch(evt); - clearTimeout(self.singleTapTimeout); - self.isDoubleTap = false; - } - }, 0) - - if (!self.isDoubleTap) { - self.singleTapTimeout = setTimeout(function () { - self.singleTap.dispatch(evt); - }, 250); - } - } - - this.preV.x = 0; - this.preV.y = 0; - this.scale = 1; - this.pinchStartLen = null; - this.x1 = this.x2 = this.y1 = this.y2 = null; - }, - cancel: function (evt) { - clearTimeout(this.singleTapTimeout); - clearTimeout(this.tapTimeout); - clearTimeout(this.longTapTimeout); - clearTimeout(this.swipeTimeout); - this.touchCancel.dispatch(evt); - }, - _cancelLongTap: function () { - clearTimeout(this.longTapTimeout); - }, - _cancelSingleTap: function () { - clearTimeout(this.singleTapTimeout); - }, - _swipeDirection: function (x1, x2, y1, y2) { - return Math.abs(x1 - x2) >= Math.abs(y1 - y2) ? (x1 - x2 > 0 ? 'Left' : 'Right') : (y1 - y2 > 0 ? 'Up' : 'Down') - }, - - on: function(evt, handler) { - if(this[evt]) { - this[evt].add(handler); - } - }, - - off: function(evt, handler) { - if(this[evt]) { - this[evt].del(handler); - } - }, - - destroy: function() { - if(this.singleTapTimeout) clearTimeout(this.singleTapTimeout); - if(this.tapTimeout) clearTimeout(this.tapTimeout); - if(this.longTapTimeout) clearTimeout(this.longTapTimeout); - if(this.swipeTimeout) clearTimeout(this.swipeTimeout); - - this.element.removeEventListener("touchstart", this.start); - this.element.removeEventListener("touchmove", this.move); - this.element.removeEventListener("touchend", this.end); - this.element.removeEventListener("touchcancel", this.cancel); - - this.rotate.del(); - this.touchStart.del(); - this.multipointStart.del(); - this.multipointEnd.del(); - this.pinch.del(); - this.swipe.del(); - this.tap.del(); - this.doubleTap.del(); - this.longTap.del(); - this.singleTap.del(); - this.pressMove.del(); - this.touchMove.del(); - this.touchEnd.del(); - this.touchCancel.del(); - - this.preV = this.pinchStartLen = this.scale = this.isDoubleTap = this.delta = this.last = this.now = this.tapTimeout = this.singleTapTimeout = this.longTapTimeout = this.swipeTimeout = this.x1 = this.x2 = this.y1 = this.y2 = this.preTapPosition = this.rotate = this.touchStart = this.multipointStart = this.multipointEnd = this.pinch = this.swipe = this.tap = this.doubleTap = this.longTap = this.singleTap = this.pressMove = this.touchMove = this.touchEnd = this.touchCancel = null; - - return null; - } - }; - - if (true) { - module.exports = AlloyFinger; - } else { - window.AlloyFinger = AlloyFinger; - } - })(); - - -/***/ }, -/* 47 */ -/***/ function(module, exports) { - - module.exports = "
\"\"
Omi
" - -/***/ }, -/* 48 */ -/***/ function(module, exports) { - - module.exports = ".head{ position:fixed; height:45px; line-height: 45px; border-bottom: 1px solid #eee; width:100%; background-color:#303030; z-index:100;}ul,li{ display: inline-block;}.logo_box{ width:100px; display: inline-block; text-align:center; line-height: 60px;}.menu a,.logo_box a{ display: inline-block; height:45px; color:#ddd;}.menu{ position: absolute; right:20px;}.menu li{ margin-left:15px;}.logo_box a{ font-size: 34px; font-weight: bold; color: #00bff3; padding: 0px 15px; line-height: 45px; cursor: pointer;}.menu a:hover{ color: white;}.m_menu{ position:fixed; display:none;}@media only screen and (max-width: 768px) { .menu li{ display:none; } .menu .m_show{ display:block; } .logo_box{ display:inline-block; } .head{ text-align:center; } .m_menu{ top:0; left:0; display:block; width:50px; height:50px; padding-top: 6px; } .m_menu img{ width:30px; }}" - -/***/ }, -/* 49 */ -/***/ function(module, exports, __webpack_require__) { - - 'use strict'; - - Object.defineProperty(exports, "__esModule", { - value: true - }); - - var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); - - var _omi = __webpack_require__(2); - - var _omi2 = _interopRequireDefault(_omi); - - var _config = __webpack_require__(4); - - var _config2 = _interopRequireDefault(_config); - - var _omiFinger = __webpack_require__(45); - - var _omiFinger2 = _interopRequireDefault(_omiFinger); - - function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - - function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } - - function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; } - - function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } - - _omiFinger2.default.init(); - - var Pager = function (_Omi$Component) { - _inherits(Pager, _Omi$Component); - - function Pager(data) { - _classCallCheck(this, Pager); - - var _this = _possibleConstructorReturn(this, (Pager.__proto__ || Object.getPrototypeOf(Pager)).call(this, data)); - - _this.activeIndex = 0; - _this.currentIndex = 0; - return _this; - } - - _createClass(Pager, [{ - key: 'updatePager', - value: function updatePager() { - this.data.preMd = null; - this.data.preName = null; - this.data.nextMd = null; - this.data.nextName = null; - var item = _config2.default.menus[this.data.lan][this.activeIndex]; - - var pre = item.list[this.currentIndex - 1]; - if (pre) { - this.data.preMd = pre.md; - this.data.preName = pre.name; - } - var next = item.list[this.currentIndex + 1]; - if (next) { - this.data.nextMd = next.md; - this.data.nextName = next.name; - } - } - }, { - key: 'goto', - value: function goto(name, dir) { - var sidebar = _omi2.default.get('sidebar'); - if (dir === 'next') { - sidebar.children[this.activeIndex].goto(name, ++this.currentIndex); - } else { - sidebar.children[this.activeIndex].goto(name, --this.currentIndex); - } - this.update(); - } - }, { - key: 'handleTap', - value: function handleTap(evt) { - var dir = evt.target.getAttribute('data-dir'); - var name = evt.target.getAttribute('data-name'); - this.goto(name, dir); - } - }, { - key: 'isMobile', - value: function isMobile() { - var browser = { - versions: function () { - var u = navigator.userAgent, - app = navigator.appVersion; - return { //移动终端浏览器版本信息 - trident: u.indexOf('Trident') > -1, //IE内核 - presto: u.indexOf('Presto') > -1, //opera内核 - webKit: u.indexOf('AppleWebKit') > -1, //苹果、谷歌内核 - gecko: u.indexOf('Gecko') > -1 && u.indexOf('KHTML') == -1, //火狐内核 - mobile: !!u.match(/AppleWebKit.*Mobile.*/), //是否为移动终端 - ios: !!u.match(/\(i[^;]+;( U;)? CPU.+Mac OS X/), //ios终端 - android: u.indexOf('Android') > -1 || u.indexOf('Linux') > -1, //android终端或者uc浏览器 - iPhone: u.indexOf('iPhone') > -1, //是否为iPhone或者QQHD浏览器 - iPad: u.indexOf('iPad') > -1, //是否iPad - webApp: u.indexOf('Safari') == -1 //是否web应该程序,没有头部与底部 - }; - }(), - language: (navigator.browserLanguage || navigator.language).toLowerCase() - }; - - if (browser.versions.mobile || browser.versions.ios || browser.versions.android || browser.versions.iPhone || browser.versions.iPad) { - return true; - } - return false; - } - }, { - key: 'render', - value: function render() { - this.updatePager(); - if (this.isMobile()) { - return '\n
\n {{#preName}} \u2190{{preName}}{{/preName}}\n {{#nextName}} {{/nextName}}\n
'; - } else { - return '\n
\n {{#preName}} \u2190{{preName}}{{/preName}}\n {{#nextName}} {{/nextName}}\n
'; - } - } - }, { - key: 'style', - value: function style() { - return __webpack_require__(50); - } - }]); - - return Pager; - }(_omi2.default.Component); - - exports.default = Pager; - -/***/ }, -/* 50 */ -/***/ function(module, exports) { - - module.exports = ".pager { width:85%; height:80px; line-height:80px; position: relative; font-size:16px;}@media only screen and (max-width: 768px) { .pager { width:100%; }}.pre{ position: absolute; left:10px; top:10px;}.next{ position: absolute; right:10px; top:10px;}" - -/***/ } -]); \ No newline at end of file diff --git a/website/js/docs-en.c02b58b9.js b/website/js/docs-en.c02b58b9.js deleted file mode 100644 index 0eda0d78d..000000000 --- a/website/js/docs-en.c02b58b9.js +++ /dev/null @@ -1,1401 +0,0 @@ -window.Root ={}; Root.isDev = false;webpackJsonp([1],[ -/* 0 */ -/***/ function(module, exports, __webpack_require__) { - - 'use strict'; - - var _frame = __webpack_require__(1); - - var _frame2 = _interopRequireDefault(_frame); - - function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - - Omi.render(new _frame2.default({ lan: 'en' }), 'body', true); - -/***/ }, -/* 1 */ -/***/ function(module, exports, __webpack_require__) { - - 'use strict'; - - Object.defineProperty(exports, "__esModule", { - value: true - }); - - var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); - - var _omi = __webpack_require__(2); - - var _omi2 = _interopRequireDefault(_omi); - - var _index = __webpack_require__(3); - - var _index2 = _interopRequireDefault(_index); - - var _index3 = __webpack_require__(38); - - var _index4 = _interopRequireDefault(_index3); - - var _index5 = __webpack_require__(44); - - var _index6 = _interopRequireDefault(_index5); - - var _config = __webpack_require__(4); - - var _config2 = _interopRequireDefault(_config); - - var _index7 = __webpack_require__(49); - - var _index8 = _interopRequireDefault(_index7); - - function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - - function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } - - function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; } - - function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } - - _omi2.default.makeHTML('Content', _index2.default); - _omi2.default.makeHTML('Sidebar', _index4.default); - _omi2.default.makeHTML('Head', _index6.default); - _omi2.default.makeHTML('Pager', _index8.default); - - var Frame = function (_Omi$Component) { - _inherits(Frame, _Omi$Component); - - function Frame(data) { - _classCallCheck(this, Frame); - - return _possibleConstructorReturn(this, (Frame.__proto__ || Object.getPrototypeOf(Frame)).call(this, data)); - } - - _createClass(Frame, [{ - key: 'install', - value: function install() { - var _this2 = this; - - this.setViewport(); - window.onresize = function () { - if (window.innerWidth < 768) { - _this2.refs.main.style.width = '100%'; - } else { - _this2.refs.main.style.width = window.innerWidth - 220 + 'px'; - } - }; - } - }, { - key: 'setViewport', - value: function setViewport() { - if (window.innerWidth < 768) { - this.data.width = '100%'; - } else { - this.data.width = window.innerWidth - 220 + 'px'; - } - } - }, { - key: 'style', - value: function style() { - return '\n \n '; - } - }, { - key: 'render', - value: function render() { - return '
\n \n
\n \n \n
\n \n
'; - } - }]); - - return Frame; - }(_omi2.default.Component); - - exports.default = Frame; - -/***/ }, -/* 2 */, -/* 3 */ -/***/ function(module, exports, __webpack_require__) { - - 'use strict'; - - Object.defineProperty(exports, "__esModule", { - value: true - }); - - var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); - - var _omi = __webpack_require__(2); - - var _omi2 = _interopRequireDefault(_omi); - - var _config = __webpack_require__(4); - - var _config2 = _interopRequireDefault(_config); - - var _highlightLines = __webpack_require__(5); - - var _highlightLines2 = _interopRequireDefault(_highlightLines); - - function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - - function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } - - function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; } - - function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } - - var tpl = __webpack_require__(6); - var css = __webpack_require__(7); - - var Content = function (_Omi$Component) { - _inherits(Content, _Omi$Component); - - function Content(data) { - _classCallCheck(this, Content); - - data = Object.assign({ - lan: 'cn', - name: 'installation' - }, data); - - var _this = _possibleConstructorReturn(this, (Content.__proto__ || Object.getPrototypeOf(Content)).call(this, data)); - - _this.md = new Remarkable({ html: true }); - return _this; - } - - _createClass(Content, [{ - key: 'getMarkDown', - value: function getMarkDown(name, lan) { - return __webpack_require__(8)("./" + lan + "/" + name + ".md"); - } - }, { - key: 'installed', - value: function installed() { - this.initCodeStyle(); - } - }, { - key: 'afterUpdate', - value: function afterUpdate() { - this.initCodeStyle(); - } - }, { - key: 'initCodeStyle', - value: function initCodeStyle() { - var _this2 = this; - - var codes = _omi2.default.$$("code"); - var codeHlNumArr = []; - codes.forEach(function (code) { - hljs.highlightBlock(code); - var arr = code.className.match(/{\S*}/); - var hllNums = null; - if (arr) { - var numArr = arr[0].replace(/[{|}]/g, '').split(','); - hllNums = _this2._arrToNumber(numArr); - } - codeHlNumArr.push(hllNums); - }); - - (0, _highlightLines2.default)(); - - codes.forEach(function (code, index) { - _this2._hll(code, codeHlNumArr[index]); - }); - } - }, { - key: '_arrToNumber', - value: function _arrToNumber(numArr) { - var arr = []; - numArr.forEach(function (item) { - if (item.indexOf('-') !== -1) { - var tempArr = item.split('-'); - var begin = Number(tempArr[0]); - var end = Number(tempArr[1]); - for (var i = begin; i < end + 1; i++) { - arr.push(i); - } - } else { - arr.push(Number(item)); - } - }); - return arr; - } - }, { - key: '_hll', - value: function _hll(code, hllNums) { - var spans = _omi2.default.$$('.line', code); - hllNums && hllNums.forEach(function (num) { - spans[num] && spans[num].classList.add('highlight'); - }); - } - }, { - key: 'render', - value: function render() { - this.data.html = this.md.render(this.getMarkDown(this.data.name, this.data.lan)); - return tpl; - } - }, { - key: 'style', - value: function style() { - return css; - } - }]); - - return Content; - }(_omi2.default.Component); - - exports.default = Content; - -/***/ }, -/* 4 */ -/***/ function(module, exports) { - - 'use strict'; - - Object.defineProperty(exports, "__esModule", { - value: true - }); - var config = { - menus: { - cn: [{ - active: true, - title: '快速开始', - currentIndex: 0, - list: [{ 'name': '安装', md: 'installation' }, { 'name': 'Hello World', md: 'hello_world' }, { 'name': '组件', md: 'components' }, { 'name': '组件通讯', md: 'communication' }, { 'name': '生命周期', md: 'lifecycle' }, { 'name': '事件处理', md: 'events' }, { 'name': '条件判断', md: 'condition' }, { 'name': '循环遍历', md: 'loop' }, { 'name': 'Store体系', md: 'store' }, { 'name': '表单', md: 'form' }, { 'name': '继承', md: 'inherit' }, { 'name': '模板切换', md: 'template' }, { 'name': '获取DOM节点', md: 'get_dom' }, { 'name': '插件体系', md: 'plugin' }, { 'name': 'Omi的理念', md: 'thinking_in_omi' }] - }], - en: [{ - title: 'QUICK START', - active: true, - currentIndex: 0, - list: [{ 'name': 'Installation', md: 'installation' }, { 'name': 'Hello World', md: 'hello_world' }, { 'name': 'Components', md: 'components' }, { 'name': 'Communication', md: 'communication' }, { 'name': 'Lifecycle', md: 'lifecycle' }, { 'name': 'Handling Events', md: 'events' }, { 'name': 'Conditional Rendering', md: 'condition' }, { 'name': 'Loop', md: 'loop' }, { 'name': 'Forms', md: 'form' }, { 'name': 'Inheritance', md: 'inherit' }, { 'name': 'Templates', md: 'template' }, { 'name': 'Get DOM', md: 'get_dom' }, { 'name': 'Plugin', md: 'plugin' }, { 'name': 'Thinking in Omi', md: 'thinking_in_omi' }] - }] - } - }; - - exports.default = config; - -/***/ }, -/* 5 */ -/***/ function(module, exports) { - - 'use strict'; - - Object.defineProperty(exports, "__esModule", { - value: true - }); - - // Iterates through `array`, running `callback` for each `array` element. - function forEach(array, callback) { - var i = -1, - length = array ? array.length : 0; - while (++i < length) { - callback(array[i]); - } - } - - function indexOf(array, elem) { - var i = -1, - length = array ? array.length : 0; - while (++i < length) { - if (array[i] === elem) { - return i; - } - } - } - function highlightLines() { - // TODO: mark as parsed. - forEach(document.querySelectorAll('pre code'), function (element) { - // Trim whitespace if the `data-trim` attribute is present. - if (element.hasAttribute('data-trim') && typeof element.innerHTML.trim == 'function') { - element.innerHTML = element.innerHTML.trim(); - } - - // Highlight code using highlight.js. - hljs.highlightBlock(element); - - // Split highlighted code into lines. - var openTags = [], - reHtmlTag = /<(\/?)span(?:\s+(?:class=(['"])hljs-.*?\2)?\s*|\s*)>/g; - element.innerHTML = element.innerHTML.replace(/(.*?)\r?\n/g, function (_, string) { - if (!string) { - return ' '; - } - var openTag, stringPrepend; - // Re-open all tags that were previously closed. - if (openTags.length) { - stringPrepend = openTags.join(''); - } - // Match all HTML `` tags. - reHtmlTag.lastIndex = 0; - while (openTag = reHtmlTag.exec(string)) { - // If it is a closing tag, remove the opening tag from the list. - if (openTag[1]) { - openTags.pop(); - } - // Otherwise if it is an opening tag, push it to the list. - else { - openTags.push(openTag[0]); - } - } - // Close all opened tags, so that strings can be wrapped with `span.line`. - if (openTags.length) { - string += Array(openTags.length + 1).join(''); - } - if (stringPrepend) { - string = stringPrepend + string; - } - return '' + string + ''; - }); - }); - } - - exports.default = highlightLines; - -/***/ }, -/* 6 */ -/***/ function(module, exports) { - - module.exports = "
{{{html}}}
" - -/***/ }, -/* 7 */ -/***/ function(module, exports) { - - module.exports = ".content{ width: 80%;}h3{ color:#444444;}pre{ border: 1px solid #eee; width: 100%;}li{ text-indent: 20px; list-style:disc inside ;}@media only screen and (max-width: 768px) { .content{ width: 100%; }}" - -/***/ }, -/* 8 */ -/***/ function(module, exports, __webpack_require__) { - - var map = { - "./cn/communication.md": 9, - "./cn/components.md": 10, - "./cn/condition.md": 11, - "./cn/events.md": 12, - "./cn/form.md": 13, - "./cn/get_dom.md": 14, - "./cn/hello_world.md": 15, - "./cn/inherit.md": 16, - "./cn/installation.md": 17, - "./cn/lifecycle.md": 18, - "./cn/loop.md": 19, - "./cn/plugin.md": 20, - "./cn/store.md": 21, - "./cn/template.md": 22, - "./cn/thinking_in_omi.md": 23, - "./en/communication.md": 24, - "./en/components.md": 25, - "./en/condition.md": 26, - "./en/events.md": 27, - "./en/form.md": 28, - "./en/get_dom.md": 29, - "./en/hello_world.md": 30, - "./en/inherit.md": 31, - "./en/installation.md": 32, - "./en/lifecycle.md": 33, - "./en/loop.md": 34, - "./en/plugin.md": 35, - "./en/template.md": 36, - "./en/thinking_in_omi.md": 37 - }; - function webpackContext(req) { - return __webpack_require__(webpackContextResolve(req)); - }; - function webpackContextResolve(req) { - return map[req] || (function() { throw new Error("Cannot find module '" + req + "'.") }()); - }; - webpackContext.keys = function webpackContextKeys() { - return Object.keys(map); - }; - webpackContext.resolve = webpackContextResolve; - module.exports = webpackContext; - webpackContext.id = 8; - - -/***/ }, -/* 9 */ -/***/ function(module, exports) { - - module.exports = "## 组件通讯\r\n\r\n[Omi框架](https://github.com/AlloyTeam/omi)组建间的通讯非常遍历灵活,因为有许多可选方案进行通讯:\r\n\r\n* 通过在组件上声明 data-* 传递给子节点 \r\n* 通过在组件上声明 data 传递给子节点 (支持复杂数据类型的映射)\r\n* 声明 group-data 传递(支持复杂数据类型的映射)\r\n* 完全面向对象,可以非常容易地拿到对象的实例,之后可以设置实例属性和调用实例的方法\r\n\r\n所以通讯变得畅通无阻,下面一一来举例说明。\r\n\r\n### data-*通讯 \r\n\r\n```js {36}\r\nclass Hello extends Omi.Component {\r\n constructor(data) {\r\n super(data);\r\n }\r\n \r\n style () {\r\n return `\r\n h1{\r\n \tcursor:pointer;\r\n }\r\n `;\r\n }\r\n \r\n handleClick(target, evt){\r\n alert(target.innerHTML);\r\n }\r\n \r\n render() {\r\n return `\r\n
\r\n \t

Hello ,{{name}}!

\r\n
\r\n \t\t`;\r\n }\r\n}\r\n\r\nOmi.makeHTML('Hello', Hello);\r\n\r\nclass App extends Omi.Component {\r\n constructor(data) {\r\n super(data);\r\n }\r\n \r\n render() {\r\n return `\r\n
\r\n \r\n
\r\n `;\r\n }\r\n}\r\n\r\nOmi.render(new App(),\"#container\");\r\n```\r\n\r\n一般data-*用来传递值类型,如string、number。值得注意的是,通过data-*接收到的数据类型都是string,需要自行转成number类型。\r\n通常情况下,data-*能满足我们的要求,但是遇到复杂的数据类型是没有办法通过大量data-*去表达,所以可以通过data通讯,请往下看。\r\n\r\n### data通讯 \r\n\r\n如上面代码所示,通过 data-name=\"Omi\"可以把name传递给子组件。下面的代码也可以达到同样的效果。\r\n\r\n```js {4,10}\r\n...\r\nclass App extends Omi.Component {\r\n constructor(data) {\r\n super(data);\r\n this.helloData = { name : 'Omi' };\r\n }\r\n \r\n render() {\r\n return `\r\n
\r\n \r\n
\r\n `;\r\n }\r\n}\r\n\r\nOmi.render(new App(),\"#container\");\r\n```\r\n\r\n使用data声明,会去组件的instance(也就是this)下找对应的属性,this下可以挂载任意复杂的对象。所以这也就突破了data-*的局限性。\r\n\r\n如果instance下面的某个属性下面的某个属性下面的某个数组的第一个元素的某个属性要作为data传递Hello怎么办?\r\n没关系,data声明是支持复杂类型的,使用方式如下:\r\n\r\n```js\r\n...\r\nclass App extends Omi.Component {\r\n constructor(data) {\r\n super(data);\r\n this.complexData ={\r\n a:{\r\n b:{\r\n c:[\r\n {\r\n e:[{\r\n name:'ComplexData Support1'\r\n },{\r\n name:'ComplexData Support2'\r\n }]\r\n },\r\n {\r\n name: 'ComplexData Support3'\r\n }\r\n ]\r\n }\r\n }\r\n };\r\n }\r\n \r\n render() {\r\n return `\r\n
\r\n \r\n
\r\n `;\r\n }\r\n}\r\n...\r\n```\r\n\r\n点击这里→data映射复杂数据\r\n\r\n### group-data通讯\r\n\r\ngroup-data专门是为了给一组组件批量传递data而设计。\r\n\r\n```js\r\nimport Hello from './hello.js';\r\n\r\n\r\nOmi.makeHTML('Hello', Hello);\r\n\r\nclass App extends Omi.Component {\r\n constructor(data) {\r\n super(data);\r\n this.testData = [{name: 'Omi'}, {name: 'dntzhang'}, {name: 'AlloyTeam'}];\r\n }\r\n\r\n render() {\r\n return `\r\n
\r\n \r\n \r\n \r\n
\r\n `;\r\n\r\n }\r\n}\r\n\r\nOmi.render(new App(),\"#container\");\r\n```\r\n\r\n只需要在声明的子组件上标记group-data,就会去当前组件的instance(也就是this)下面找对应的属性,然后根据当前的位置,和对应数组的位置会一一对应起来。\r\n\r\n运行结果如下:\r\n![](http://images2015.cnblogs.com/blog/105416/201702/105416-20170216110701535-1698390390.png)\r\n\r\n点击这里→group-data\r\n\r\n同样group-data支持复杂数据类型的映射,需要注意的是,group-data映射的终点必须是一个数组:\r\n\r\n```js\r\nimport Hello from './hello.js';\r\n\r\n\r\nOmi.makeHTML('Hello', Hello);\r\n\r\nclass App extends Omi.Component {\r\n constructor(data) {\r\n super(data);\r\n this.complexData ={\r\n a:{\r\n b:{\r\n c:[\r\n {\r\n e:[{\r\n name:'ComplexData Support1'\r\n },{\r\n name:'ComplexData Support2'\r\n }]\r\n },\r\n {\r\n name: 'ComplexData Support3'\r\n }\r\n ]\r\n }\r\n }\r\n };\r\n }\r\n\r\n render() {\r\n return `\r\n
\r\n \r\n \r\n
\r\n `;\r\n\r\n }\r\n}\r\n\r\nOmi.render(new App(),\"#container\");\r\n```\r\n\r\n点击这里→group-data映射复杂数据\r\n\r\n### 通过对象实例\r\n\r\n```js {7}\r\n...\r\nclass App extends Omi.Component {\r\n constructor(data) {\r\n super(data);\r\n }\r\n \r\n installed(){\r\n this.hello.data.name = \"Omi\";\r\n this.update()\r\n }\r\n \r\n render() {\r\n return `\r\n
\r\n \r\n
\r\n `;\r\n }\r\n}\r\n\r\nOmi.render(new App(),\"#container\");\r\n```\r\n\r\n### 通过omi-id\r\n\r\n```js {7,14}\r\n...\r\nclass App extends Omi.Component {\r\n constructor(data) {\r\n super(data);\r\n }\r\n \r\n installed(){\r\n Omi.get(\"hello\").data.name = \"Omi\";\r\n this.update()\r\n }\r\n \r\n render() {\r\n return `\r\n
\r\n \r\n
\r\n `;\r\n }\r\n}\r\n\r\nOmi.render(new App(),\"#container\");\r\n```\r\n\r\n通过在组件上声明omi-id,在程序任何地方拿到该对象的实例。这个可以算是跨任意组件通讯神器。\r\n\r\n" - -/***/ }, -/* 10 */ -/***/ function(module, exports) { - - module.exports = "## 组件\r\n\r\n[Omi框架](https://github.com/AlloyTeam/omi)完全基于组件体系设计,我们希望开发者可以像搭积木一样制作Web程序,一切皆是组件,组件也可以嵌套子组件形成新的组件,新的组件又可以当作子组件嵌套至任意组件形成新的组件...\r\n\r\n![](http://images2015.cnblogs.com/blog/105416/201702/105416-20170210093427338-1536910080.png)\r\n\r\n## 简单组件\r\n\r\n这里使用Todo的例子来讲解Omi组件体系的使用。\r\n\r\n```js\r\nclass Todo extends Omi.Component {\r\n constructor(data) {\r\n super(data);\r\n }\r\n \r\n add (evt) {\r\n evt.preventDefault();\r\n this.data.items.push(this.data.text);\r\n this.data.text = '';\r\n this.update();\r\n }\r\n\r\n style () {\r\n return `\r\n h3 { color:red; }\r\n button{ color:green;}\r\n `;\r\n }\r\n\r\n handleChange(target){\r\n this.data.text = target.value;\r\n }\r\n\r\n render () {\r\n return `
\r\n

TODO

\r\n
    {{#items}}
  • {{.}}
  • {{/items}}
\r\n
\r\n \r\n \r\n
\r\n
`;\r\n }\r\n}\r\n\r\nOmi.render(new Todo({ items: [] ,text : '' }),\"body\");\r\n```\r\n\r\n组件生成的HTML最终会插入到body中。上面的例子展示了Omi的部分特性:\r\n\r\n- data传递: new Todo(data,..)的data可以直接提供给render方法里的模板\r\n- 局部CSS: h3只对render里的h3生效,不会污染外面的h3;button也是同样的\r\n- 声明式事件绑定: onchange调用的就是组件内的handleChange,this可以拿到当然的DOM元素,还可以拿到当前的event\r\n- 需要手动调用update方法才能更新组件\r\n\r\n这里需要特别强调的是,为了更加的自由和灵活度。Omi没有内置数据变更的自动更新,需要开发者自己调用update方法。\r\n\r\n点击这里→在线试试\r\n\r\n## 组件嵌套\r\n\r\n如果页面超级简单的话,可以没有组件嵌套。但是绝大部分Web网页或者Web应用,需要嵌套定义的组件来完成所有的功能和展示。比如上面的Todo,我们也是可以抽取出List。\r\n这样让程序易维护、可扩展、方便复用。如,我们抽取出List:\r\n\r\n```js\r\nclass List extends Omi.Component {\r\n constructor(data) {\r\n super(data);\r\n }\r\n\r\n render () {\r\n return `
    {{#items}}
  • {{.}}
  • {{/items}}
`;\r\n }\r\n}\r\n```\r\n\r\n怎么使用这个List?我们需要使用Omi.makeHTML把List制作成可以声明式的标签,在render方法中就能直接使用该标签。如下所示:\r\n\r\n```js\r\nimport List from './list.js';\r\n\r\nOmi.makeHTML('List', List);\r\n\r\nclass Todo extends Omi.Component {\r\n constructor(data) {\r\n super(data);\r\n this.data.length = this.data.items.length;\r\n this.listData = { items : this.data.items };\r\n }\r\n\r\n add (evt) {\r\n evt.preventDefault();\r\n this.list.data.items.push(this.data.text);\r\n this.data.length = this.list.data.items.length;\r\n this.data.text = '';\r\n this.update();\r\n }\r\n\r\n style () {\r\n return `\r\n h3 { color:red; }\r\n button{ color:green;}\r\n `;\r\n }\r\n\r\n handleChange(target){\r\n this.data.text = target.value;\r\n }\r\n\r\n render () {\r\n return `
\r\n

TODO

\r\n \r\n
\r\n \r\n \r\n
\r\n
`;\r\n }\r\n}\r\n```\r\n\r\n* 第3行,通过makeHTML方法把组件制作成可以在render中使用的标签。当然Omi.makeHTML('List', List);也可以写在List组件的代码下面。\r\n* 第9行,在父组件上定义listData属性用来传递给子组件。\r\n* 第34行,在render方法中使用List组件。其中name方法可以让你在代码里通过this快速方法到该组件的实例。data=\"listData\"可以让你把this.listData传递给子组件。\r\n\r\n需要注意的是,父组件的this.listData会被通过Object.assign浅拷贝到子组件。\r\n这样做的目的主要是希望以后DOM的变更都尽量修改子组件自身的data,然后再调用其update方法,而不是去更改父组件的listData。\r\n\r\n关于Omi组件通讯其实有4种方案,这个后续教程会专门来讲。\r\n\r\n点击这里→在线试试\r\n" - -/***/ }, -/* 11 */ -/***/ function(module, exports) { - - module.exports = "## 条件判断\r\n\r\n我们经常需要根据不同的状态呈现不同的界面,比如有的用户是vip要显示vip的Logo。Omi有许多种方式满足你的要求。\r\n\r\n### 方式一\r\n\r\n```js\r\nclass ConditionTest extends Omi.Component {\r\n constructor(data) {\r\n super(data);\r\n }\r\n\r\n render () {\r\n return `{{#isVip}}\r\n
you are VIP.
\r\n {{/isVip}}\r\n {{^isVip}}\r\n
you are not VIP.
\r\n {{/isVip}}`;\r\n }\r\n}\r\n```\r\n\r\n上面完全使用mustachejs的条件判断的语法。当然Omi不强制你使用mustachejs。你可以是omi.lite.js,然后重写Omi.template方法去使用任意你喜爱的模板引擎。\r\n\r\n### 方式二\r\n\r\n```js\r\nclass ConditionTest extends Omi.Component {\r\n constructor(data) {\r\n super(data);\r\n }\r\n\r\n render () {\r\n if(this.data.isVip){\r\n return '
you are VIP.
';\r\n }else{\r\n return '
you are not VIP.
';\r\n }\r\n }\r\n}\r\n```\r\n\r\nrender就是提供了很好的可编程性,里面可以写任意js逻辑代码。对了,差点忘了,style方法里面也可以写js逻辑的。\r\n\r\n```js\r\nclass ConditionTest extends Omi.Component {\r\n constructor(data) {\r\n super(data);\r\n }\r\n\r\n style (){\r\n if(this.data.isVip){\r\n return 'div{ color : red; }';\r\n }else{\r\n return 'div{ color : green; }';\r\n }\r\n }\r\n\r\n render () {\r\n if(this.data.isVip){\r\n return '
you are VIP.
';\r\n }else{\r\n return '
you are not VIP.
';\r\n }\r\n }\r\n}\r\n```\r\n\r\n### 方式三\r\n\r\n```js\r\nclass ConditionTest extends Omi.Component {\r\n constructor(data) {\r\n super(data);\r\n }\r\n\r\n render() {\r\n return `\r\n ${this.data.isVip\r\n ?\"
you are VIP.
\"\r\n :\"
you are not VIP.
\"\r\n \t\t}\r\n `;\r\n }\r\n}\r\n```\r\n\r\n当然可以使用${ }里面写javascript代码进行输出。" - -/***/ }, -/* 12 */ -/***/ function(module, exports) { - - module.exports = "## 事件处理\r\n\r\nOmi的事件分内置事件和自定义事件。在内置事件处理方面巧妙地利用了浏览器自身的管线机制,可以通过event和this轻松拿到事件实例和触发该事件的元素。\r\n\r\n### 内置事件\r\n\r\n什么算内置事件?只要下面正则能匹配到就算内置事件。\r\n\r\n```js\r\non(abort|blur|cancel|canplay|canplaythrough|change|click|close|contextmenu|cuechange|dblclick|drag|dragend|dragenter|dragleave|dragover|dragstart|drop|durationchange|emptied|ended|error|focus|input|invalid|keydown|keypress|keyup|load|loadeddata|loadedmetadata|loadstart|mousedown|mouseenter|mouseleave|mousemove|mouseout|mouseover|mouseup|mousewheel|pause|play|playing|progress|ratechange|reset|resize|scroll|seeked|seeking|select|show|stalled|submit|suspend|timeupdate|toggle|volumechange|waiting|autocomplete|autocompleteerror|beforecopy|beforecut|beforepaste|copy|cut|paste|search|selectstart|wheel|webkitfullscreenchange|webkitfullscreenerror|touchstart|touchmove|touchend|touchcancel|pointerdown|pointerup|pointercancel|pointermove|pointerover|pointerout|pointerenter|pointerleave)\r\n```\r\n\r\n内置事件怎么绑定?如下所示:\r\n\r\n```js\r\nclass EventTest extends Omi.Component {\r\n constructor(data) {\r\n super(data);\r\n }\r\n\r\n handleClick(dom, evt){\r\n alert(dom.innerHTML);\r\n }\r\n\r\n render () {\r\n return `
Hello, Omi!
`;\r\n }\r\n}\r\n```\r\n\r\n### 自定义事件\r\n\r\n开发者自己定义的组件的事件,称为自定义事件,自定义事件必须以on开头,即onXXXX的格式,不然Omi识别不到。这里拿分页作为例子:\r\n\r\n```js\r\nimport Omi from '../../src/index.js';\r\nimport Pagination from './pagination.js';\r\nimport Content from './content.js';\r\n\r\nOmi.makeHTML('Pagination', Pagination);\r\nOmi.makeHTML('Content', Content);\r\n\r\nclass Main extends Omi.Component {\r\n constructor(data) {\r\n super(data);\r\n }\r\n\r\n installed(){\r\n this.content.goto(this.pagination.data.currentPage+1);\r\n }\r\n \r\n handlePageChange(index){\r\n this.content.goto(index+1);\r\n }\r\n\r\n render () {\r\n return `
\r\n

Pagination Example

\r\n \r\n \r\n
`;\r\n }\r\n}\r\n\r\nOmi.render( new Main(),'body');\r\n```\r\n\r\n如上面的onPageChange就是自定义事件,触发会执行handlePageChange。onPageChange方法是在Pagination中执行:\r\n\r\n```js\r\nimport Omi from '../../src/index.js';\r\n\r\nclass Pagination extends Omi.Component {\r\n ...\r\n ...\r\n ...\r\n linkTo: \"#\",\r\n prevText: \"Prev\",\r\n nextText: \"Next\",\r\n ellipseText: \"...\",\r\n prevShow: true,\r\n nextShow: true,\r\n onPageChange: function () { return false; }\r\n }, this.data);\r\n\r\n this.pageNum = Math.ceil(this.data.total / this.data.pageSize);\r\n }\r\n \r\n goto (index,evt) {\r\n evt.preventDefault();\r\n this.data.currentPage=index;\r\n this.update();\r\n this.data.onPageChange(index);\r\n }\r\n ...\r\n ...\r\n ...\r\n}\r\n```\r\n\r\n这里取了Pagination组件的部分代码。高亮的就是执行onPageChange的地方。\r\n\r\n### 相关地址\r\n\r\n* [演示地址](http://alloyteam.github.io/omi/example/pagination/)\r\n* [源码地址](https://github.com/AlloyTeam/omi/tree/master/example/pagination)\r\n" - -/***/ }, -/* 13 */ -/***/ function(module, exports) { - - module.exports = "## 表单\r\n\r\nOmi让一些表单操控起来更加方便,特别是select!\r\n\r\n### select标签\r\n\r\n以前,我们需要像如下的方式选中一个选项:\r\n\r\n```html\r\n\r\n```\r\n\r\n第三个option由于加上了selected,所有会被选中。这样带来的问题就是,开发者写的程序可能要操遍历每个option。而使用Omi,你只需要这样子:\r\n\r\n```html\r\n\r\n```\r\n\r\n这样就能达到同样的效果。比如你想选择第一项:\r\n\r\n```html\r\n\r\n```\r\n\r\n是不是非常方便?\r\n\r\n### 举个例子\r\n\r\n```js\r\nclass FormTest extends Omi.Component {\r\n constructor(data) {\r\n super(data);\r\n \r\n }\r\n\r\n handleChange(target){\r\n console.log(target.value)\r\n this.data.value = target.value;\r\n }\r\n\r\n handleSubmit(evt) {\r\n alert('Your favorite flavor is: ' + this.data.value);\r\n evt.preventDefault();\r\n }\r\n \r\n render () {\r\n return `\r\n
\r\n \r\n \r\n
`;\r\n }\r\n}\r\n\r\nOmi.render(new FormTest({ value: 'mango' }),'#container');\r\n```\r\n\r\n点击这里→在线试试" - -/***/ }, -/* 14 */ -/***/ function(module, exports) { - - module.exports = "## 获取DOM节点\r\n\r\n虽然绝大部分情况下,开发者不需要去查找获取DOM,但是还是有需要获取DOM的场景,所以Omi提供了方便获取DOM节点的方式。\r\n\r\n### ref和refs\r\n\r\n```js\r\nclass Hello extends Omi.Component {\r\n constructor(data) {\r\n super(data);\r\n }\r\n \r\n style () {\r\n return `\r\n h1{\r\n cursor:pointer;\r\n }\r\n `;\r\n }\r\n \r\n handleClick(){\r\n alert(this.refs.abc.innerHTML);\r\n }\r\n \r\n render() {\r\n return `\r\n
\r\n

Hello ,{{name}}!

\r\n
\r\n `;\r\n }\r\n}\r\n\r\nOmi.render(new Hello({ name : \"Omi\" }),\"#container\");\r\n```\r\n\r\n可以看到通过在HTML中标记ref为abc,那么就通过this.refs.abc访问到该DOM节点。\r\n\r\n点击这里→在线试试" - -/***/ }, -/* 15 */ -/***/ function(module, exports) { - - module.exports = "## Hello World\r\n\r\n你可以使用ES6+或者ES5的方式编写Omi程序来搭建你的Web程序。\r\n\r\n### Hello World with ES6+\r\n\r\n你可以使用 [webpack](https://webpack.github.io/) 打包工具,webpack会把你的模块代码打成一个很小的包,优化加载时间。使用[babel](http://babeljs.io/),让你立刻马上使用ES6+来编写你的web程序。你只需要在webpack配置的module设置好[babel-loader](https://github.com/babel/babel-loader)便可。\r\n\r\n一个Omi的简短的例子如下所示:\r\n\r\n```js\r\nimport Omi from './omi.js';\r\n\r\nclass Hello extends Omi.Component {\r\n constructor(data) {\r\n super(data);\r\n }\r\n \r\n style () {\r\n //注意,return中的包裹是可选的。主要是为了识别为JSX文件可以有CSS高亮。\r\n return `\r\n \r\n `;\r\n }\r\n \r\n handleClick(target, evt){\r\n alert(target.innerHTML);\r\n }\r\n \r\n render() {\r\n return `\r\n
\r\n

Hello ,{{name}}!

\r\n
\r\n `;\r\n }\r\n}\r\n\r\nOmi.render(new Hello({ name : \"Omi\" }),\"#container\");\r\n```\r\n\r\n组件生成的HTML最终会插入到#container中。上面的例子展示了Omi的部分特性:\r\n\r\n- data传递: new Hello(data,..)的data可以直接提供给render方法里的模板\r\n- 局部CSS: h1只对render里的h1生效,不会污染外面的h1\r\n- 声明式事件绑定: onclick调用的就是组件内的handleClick,this可以拿到当前的DOM元素,还可以拿到当前的event\r\n\r\n点击这里→在线试试\r\n\r\n你可以使用Omi.makeHTML来生成组件标签用于嵌套。\r\n```js\r\n Omi.makeHTML('Hello', Hello);\r\n```\r\n那么你就在其他组件中使用,如\r\n```js\r\n ...\r\n render() {\r\n return `\r\n
\r\n
Test
\r\n \r\n
\r\n `;\r\n }\r\n ...\r\n```\r\n\r\n点击这里→在线试试\r\n\r\n### Hello World with ES5\r\n\r\n当然Omi没有抛弃ES5的用户。你可以使用ES5的方式编写Omi。如,在你的HTML中引用omi.js:\r\n\r\n```html\r\n\r\n```\r\n\r\n然后:\r\n\r\n```js\r\nvar Hello = Omi.create(\"Hello\", {\r\n style: function () {\r\n return \"h1{ cursor:pointer }\";\r\n },\r\n \r\n handleClick: function (dom) {\r\n alert(dom.innerHTML)\r\n },\r\n \r\n render: function () {\r\n return '
\\\r\n

\\\r\n Hello ,{{name}}!\\\r\n

\\\r\n
'\r\n }\r\n});\r\n\r\nvar Test = Omi.create(\"Test\", {\r\n render: function () {\r\n return '
\\\r\n
Test
\\\r\n \\\r\n
'\r\n }\r\n});\r\n\r\nOmi.render(new Test(),'#container');\r\n```\r\n当然除了在HTML引入脚本,你还可以使用AMD、CMD或者CommonJS的方式引入Omi,这里就不再一一列举。\r\n\r\n需要注意的是,Omi.create的第一个参数Hello是用来生成Tag Name的。你可以在其他地方嵌入你的组件。如:\r\n\r\n```js\r\n ...\r\n render:function() {\r\n return '
\\\r\n \\\r\n
Test XXXX
\\\r\n \\\r\n
';\r\n }\r\n ...\r\n```\r\n\r\n点击这里→在线试试\r\n" - -/***/ }, -/* 16 */ -/***/ function(module, exports) { - - module.exports = "## 继承\r\n\r\n通过继承机制,可以利用已有的数据类型来定义新的数据类型。所定义的新的数据类型不仅拥有新定义的成员,而且还同时拥有旧的成员。我们称已存在的用来派生新类的类为基类,又称为父类。由已存在的类派生出的新类称为派生类,又称为子类。\r\n\r\n### 举个例子\r\n\r\n```js\r\nclass Hello extends Omi.Component {\r\n constructor(data) {\r\n super(data);\r\n }\r\n \r\n style () {\r\n return `\r\n div{\r\n cursor:pointer;\r\n }\r\n `;\r\n }\r\n \r\n handleClick(target, evt){\r\n alert(target.innerHTML);\r\n }\r\n \r\n render() {\r\n return '
Hello {{name}}!
'\r\n }\r\n}\r\n\r\nclass SubHello extends Hello {\r\n constructor(data) {\r\n super(data);\r\n }\r\n}\r\n\r\nOmi.render(new SubHello({ name : 'Omi' }),'#container');\r\n```\r\n\r\n点击这里→在线试试\r\n\r\n### ES5下的继承\r\n\r\n```js\r\nvar Hello = Omi.create(\"Hello\",{\r\n render:function(){\r\n return '
Hello {{name}}!
'\r\n }\r\n})\r\n\r\nvar SubHello = Omi.create(\"SubHello\",Hello,{ });\r\n\r\n\r\nOmi.render(new SubHello({ name : 'Omi' }),'#container');\r\n```\r\n\r\n点击这里→在线试试" - -/***/ }, -/* 17 */ -/***/ function(module, exports) { - - module.exports = "## 安装\n\n[Omi](https://github.com/AlloyTeam/omi)(读音 / [ˈomɪ] /, 汉字类似于 欧米) 是一款用于创建用户界面的组件化框架,开放并且现代,故得名:Omi。\n\n### 安装 Omi\n\n我们推荐使用 [npm](https://www.npmjs.com/) 来管理你的前端依赖.\n\n通过npm安装Omi,你只需要执行下面的命令:\n\n``` js\n$ npm install omi\n```\n\n## omi-cli\n\n你也可以通过omi-cli去初始化你的项目:\n\n``` js\n$ npm install omi-cli -g //安装cli\n$ omi init your_project_name //初始化项目,你也可以在一个空的文件夹下执行 omi init\n$ cd your_project_name //如果你是在空文件夹下执行的 omi init。请无视这条命令\n$ npm run dev //开发\n$ npm run dist //部署发布\n```" - -/***/ }, -/* 18 */ -/***/ function(module, exports) { - - module.exports = "## 生命周期\r\n\r\n|name |avatars |company | \r\n|---|---|---|\r\n| constructor | 构造函数 | new的时候 |\r\n| install | 初始化安装,这可以拿到用户传进的data进行处理 | 实例化 |\r\n| installed | 安装完成,HTML已经插入页面之后执行 | 实例化 |\r\n| uninstall | 卸载组件。执行remove方法会触发该事件 | 销毁时 |\r\n| beforeUpdate | 更新前 | 存在期 |\r\n| afterUpdate | 更新后 | 存在期 |\r\n\r\n## 示意图\r\n\r\n![lc](http://images2015.cnblogs.com/blog/105416/201703/105416-20170322083548924-1871234168.jpg)\r\n \r\n### 举个例子\r\n\r\n```js\r\nclass Timer extends Omi.Component {\r\n constructor(data) {\r\n super(data);\r\n }\r\n\r\n install () {\r\n this.data = {secondsElapsed: 0};\r\n }\r\n\r\n tick() {\r\n this.data.secondsElapsed++;\r\n this.update();\r\n }\r\n\r\n installed(){\r\n this.interval = setInterval(() => this.tick(), 1000);\r\n }\r\n\r\n uninstall() {\r\n clearInterval(this.interval);\r\n }\r\n\r\n\r\n style () {\r\n return `\r\n .num { color:red; }\r\n `;\r\n }\r\n\r\n render () {\r\n return `
Seconds Elapsed: {{secondsElapsed}}
`;\r\n }\r\n}\r\n```\r\n\r\n点击这里→在线试试\r\n" - -/***/ }, -/* 19 */ -/***/ function(module, exports) { - - module.exports = "## 循环遍历\r\n\r\n下面介绍mustache.js的方式和javascript遍历的方式。\r\n\r\n### 方式一\r\n\r\n```js\r\nclass List extends Omi.Component {\r\n constructor(data) {\r\n super(data);\r\n }\r\n\r\n render () {\r\n return `
\r\n
    \r\n {{#items}} \r\n
  • {{text}}
  • \r\n {{/items}}\r\n
\r\n
`;\r\n }\r\n}\r\n\r\nOmi.render(new List({\r\n items: [\r\n {id: 1, text: 'Omi'},\r\n {id: 2, text: 'dntzhang'},\r\n {id: 3, text: 'AlloyTeam'}\r\n ]\r\n}),\"body\");\r\n```\r\n\r\nmustache.js更详细的循环遍历使用可看[https://github.com/janl/mustache.js#non-empty-lists](https://github.com/janl/mustache.js#non-empty-lists)。 比如还支持:\r\n\r\n* 如果items的每一项是字符串,可以直接**{{.}}**的方式来输出每一项\r\n* 循环的时候调用定义好的函数\r\n\r\n点击这里→在线试试\r\n\r\n### 方式二\r\n\r\n既然ES6+了,当然可以使用${ }以及Array的map方法: \r\n\r\n```js\r\nclass List extends Omi.Component {\r\n constructor(data) {\r\n super(data);\r\n }\r\n\r\n render() {\r\n return `
\r\n
    \r\n ${this.data.items.map(item =>\r\n `
  • ${item.text}
  • `\r\n ).join('')}\r\n
\r\n
`;\r\n }\r\n}\r\n\r\nOmi.render(new List({\r\n items: [\r\n {id: 1, text: 'Omi'},\r\n {id: 2, text: 'dntzhang'},\r\n {id: 3, text: 'AlloyTeam'}\r\n ]\r\n}),\"body\");\r\n```\r\n\r\n你将在页面看到如下效果:\r\n\r\n![pv](http://images2015.cnblogs.com/blog/105416/201701/105416-20170122095724129-2059595233.png)\r\n\r\n点击这里→在线试试\r\n\r\n如果想在循环里加些判断呢?比如需要把id为偶数的隐藏起来:\r\n\r\n```js\r\nrender() {\r\n return `
\r\n
    \r\n ${this.data.items.map(item =>\r\n `
  • ${item.text}
  • `\r\n ).join('')}\r\n
\r\n
`;\r\n}\r\n```\r\n\r\n所以模板字符串还是非常方便,随着ES继续发展下去,模板引擎估计会慢慢消失。所以omi提供了 omi.lite.js 版本不包含任何模板引擎。" - -/***/ }, -/* 20 */ -/***/ function(module, exports) { - - module.exports = "## 插件体系\r\n\r\n[Omi](https://github.com/AlloyTeam/omi)是Web组件化框架,怎么又来了个插件的概念?\r\n\r\n可以这么理解: Omi插件体系可以赋予dom元素一些能力,并且可以和组件的实例产生关联。\r\n\r\n### omi-drag\r\n\r\n且看这个例子:\r\n\r\n点击这里→在线试试\r\n\r\n```js\r\nimport OmiDrag from './omi-drag.js';\r\n\r\nOmiDrag.init();\r\n\r\nclass App extends Omi.Component {\r\n constructor(data) {\r\n super(data);\r\n }\r\n\r\n render() {\r\n return `\r\n
\r\n
Drag Me
\r\n
\r\n `;\r\n\r\n }\r\n\r\n style(){\r\n return `\r\n .test{\r\n width:100px;\r\n height:100px;\r\n color:white;\r\n line-height:90px;\r\n text-align:center;\r\n background-color:#00BFF3;\r\n }\r\n `\r\n }\r\n}\r\n\r\nOmi.render(new App(),\"#container\");\r\n```\r\n\r\n如上面的代码所示,通过在div上标记omi-drag,这个div就能够被用户使用鼠标拖拽。我们称omi-drag.js为omi插件。\r\n是不是非常方便?那么这个omi-drag是怎么实现的?\r\n\r\n## Omi.extendPlugin\r\n\r\n核心方法: Omi.extendPlugin( pluginName, handler )\r\n\r\n下面的代码就是展示了如何通过 Omi.extendPlugin 赋予dom拖拽的能力:\r\n\r\n```js\r\n;(function () {\r\n\r\n var OmiDrag = {};\r\n var Omi = typeof require === 'function'\r\n ? require('omi')\r\n : window.Omi;\r\n\r\n OmiDrag.init = function(){\r\n Omi.extendPlugin('omi-drag',function(dom, instance){\r\n dom.style.cursor='move';\r\n var isMouseDown = false,\r\n preX = null,\r\n preY = null,\r\n currentX = null,\r\n currentY = null,\r\n translateX = 0,\r\n translateY = 0;\r\n\r\n dom.addEventListener('mousedown',function(evt){\r\n isMouseDown = true;\r\n preX = evt.pageX;\r\n preY = evt.pageY;\r\n evt.stopPropagation();\r\n },false);\r\n\r\n window.addEventListener('mousemove',function(evt){\r\n if(isMouseDown){\r\n currentX = evt.pageX;\r\n currentY = evt.pageY;\r\n if(preX != null){\r\n translateX += currentX - preX;\r\n translateY += currentY - preY;\r\n dom.style.transform = 'translateX('+translateX+'px) translateY('+translateY+'px)';\r\n }\r\n preX = currentX;\r\n preY = currentY;\r\n evt.preventDefault();\r\n }\r\n },false);\r\n\r\n window.addEventListener('mouseup',function(){\r\n isMouseDown = false;\r\n preX = preY = currentX = currentY = null;\r\n },false);\r\n });\r\n }\r\n\r\n OmiDrag.destroy = function(){\r\n delete Omi.plugins['omi-drag'];\r\n };\r\n\r\n if (typeof exports == \"object\") {\r\n module.exports = OmiDrag;\r\n } else if (typeof define == \"function\" && define.amd) {\r\n define([], function(){ return OmiDrag });\r\n } else {\r\n window.OmiDrag = OmiDrag;\r\n }\r\n\r\n})();\r\n```\r\n\r\n方法: Omi.extendPlugin( pluginName, handler )\r\n\r\n其中pluginName为插件的名称\r\n其中handler为处理器。handler可以拿到标记了pluginName的dom以及dom所在的组件的实例,即 dom 和 instance。\r\n\r\n通过 Omi.extendPlugin,可以赋予dom元素一些能力,也可以和组件的实例(instance)产生关联。\r\n但是上面的例子没有和instance产生关联,我们接下来试试:\r\n\r\n## 关联instance\r\n\r\n我们想在组件里面能够监听到move并且执行回调。如下:\r\n\r\n```js\r\n...\r\n...\r\nmoveHandler(){\r\n console.log('moving');\r\n}\r\n\r\nrender() {\r\n return `\r\n
\r\n
Drag Me
\r\n
\r\n `;\r\n}\r\n...\r\n```\r\n\r\n主要被拖动过程中,moveHandler就不断地被执行。插件代码需要修改:\r\n\r\n```js\r\n...\r\nwindow.addEventListener('mousemove',function(evt){\r\n if(isMouseDown){\r\n currentX = evt.pageX;\r\n currentY = evt.pageY;\r\n if(preX != null){\r\n translateX += currentX - preX;\r\n translateY += currentY - preY;\r\n dom.style.transform = 'translateX('+translateX+'px) translateY('+translateY+'px)';\r\n }\r\n preX = currentX;\r\n preY = currentY;\r\n evt.preventDefault();\r\n instance.moveHandler(evt);\r\n }\r\n},false);\r\n```\r\n\r\n我们在里面增加了instance.moveHandler(evt);方法,用来执行组件实例上的moveHandler方法。\r\n这样的话:就是组件的实例(instance)产生关联。但是还是有问题?如果标记了多个omi-drag 就会有问题!如:\r\n\r\n```js\r\n...\r\nrender() {\r\n return `\r\n
\r\n
Drag Me
\r\n
Drag Me
\r\n
\r\n `;\r\n}\r\n...\r\n```\r\n\r\n通常我们系统每个omi-drag都能对应一个回调函数,如:\r\n\r\n```js\r\n...\r\n...\r\nmoveHandlerA(){\r\n console.log('moving');\r\n}\r\n\r\nmoveHandlerB(){\r\n console.log('moving');\r\n}\r\n\r\nrender() {\r\n return `\r\n
\r\n
Drag Me A
\r\n
Drag Me B
\r\n
\r\n `;\r\n}\r\n...\r\n```\r\n\r\n怎么办?怎么实现?有办法!通过dom传递数据给插件。\r\n\r\n## 传递数据\r\n\r\n先来看最后实现的效果:\r\n\r\n```js\r\n...\r\n...\r\nmoveHandlerA(){\r\n console.log('moving');\r\n}\r\n\r\nmoveHandlerB(){\r\n console.log('moving');\r\n}\r\n\r\nrender() {\r\n return `\r\n
\r\n
Drag Me A
\r\n
Drag Me B
\r\n
\r\n `;\r\n}\r\n...\r\n```\r\n\r\nomi-drag修改的地方:\r\n\r\n```js\r\n...\r\nvar handlerName = dom.getAttribute('dragMove');\r\n\r\nwindow.addEventListener('mousemove',function(evt){\r\n if(isMouseDown){\r\n currentX = evt.pageX;\r\n currentY = evt.pageY;\r\n if(preX != null){\r\n translateX += currentX - preX;\r\n translateY += currentY - preY;\r\n dom.style.transform = 'translateX('+translateX+'px) translateY('+translateY+'px)';\r\n }\r\n preX = currentX;\r\n preY = currentY;\r\n evt.preventDefault();\r\n instance[handlerName](evt);\r\n }\r\n},false);\r\n...\r\n```\r\n\r\n* 通过 var handlerName = dom.getAttribute('dragMove') 拿到dom上声明的dragMove\r\n* 通过 instance[handlerName](evt) 去执行对应的方法\r\n\r\n点击这里→在线试试\r\n\r\n## 更多插件\r\n\r\n* [omi-finger](https://github.com/AlloyTeam/omi/tree/master/plugins/omi-finger) Omi的[AlloyFinger](https://github.com/AlloyTeam/AlloyFinger)插件,支持各种触摸事件和手势\r\n* [omi-transform](https://github.com/AlloyTeam/omi/tree/master/plugins/omi-transform) Omi的[transformjs](http://alloyteam.github.io/AlloyTouch/transformjs/)插件,快速方便地设置DOM的CSS3 Transform属性\r\n* [omi-touch](https://github.com/AlloyTeam/omi/tree/master/plugins/omi-touch) Omi的[AlloyTouch](https://github.com/AlloyTeam/AlloyTouch)插件,Omi项目的触摸运动解决方案(支持触摸滚动、旋转、翻页、选择等等)\r\n* [omi-jquery-date-picker](https://github.com/AlloyTeam/omi/tree/master/plugins/omi-jquery-date-picker) Omi的时间选择插件,支持各种时间或者时间区域选择\r\n" - -/***/ }, -/* 21 */ -/***/ function(module, exports) { - - module.exports = "## Store 体系\r\n\r\n先说说Store系统是干什么的!为什么要造这样一个东西?能够给系统架构带来什么?\r\n\r\n当我们组件之间,拥有共享的数据的时候,经常需要进行组件通讯。在Omi框架里,父组件传递数据给子组件非常方便:\r\n\r\n* 通过在组件上声明 data-* 或者 :data-* 传递给子节点\r\n* 通过在组件上声明 data 或者 :data 传递给子节点 (支持复杂数据类型的映射)\r\n* 声明 group-data 把数组里的data传给一堆组件传递(支持复杂数据类型的映射)\r\n\r\n注:上面带有冒号的是传递javascript表达式\r\n\r\n通过声明onXxx=\"xxxx\"可以让子组件内执行父组件的方法。具体的如下图所示:\r\n\r\n![](http://images2015.cnblogs.com/blog/105416/201703/105416-20170323100946955-1938506287.jpg)\r\n\r\n\r\n如果还不明白的话,那... 我就直接上代码了:\r\n\r\n```js\r\nclass Main extends Omi.Component {\r\n\r\n handlePageChange(index){\r\n this.content.goto(index+1)\r\n this.update()\r\n }\r\n\r\n render () {\r\n return `
\r\n

Pagination Example

\r\n \r\n \r\n
`;\r\n }\r\n}\r\n```\r\n\r\n上面的例子中,\r\n\r\n* 父组件的render方法里,通过 data-✽ 传递数据给子组件 Pagination\r\n* 通过onPageChange=\"handlePageChange\"实现子组件与父组件通讯\r\n\r\n详细代码可以点击: [分页例子地址](https://github.com/AlloyTeam/omi/tree/master/example/pagination)\r\n\r\n当然你也可以使用event emitter / pubsub库在组件之间通讯,比如这个只有 200b 的超小库[mitt](https://github.com/developit/mitt) 。但是需要注意mitt兼容到IE9+,Omi兼容IE8。但是,使用event emitter / pubsub库会对组件代码进行入侵,所以非常不建议在基础非业务组件使用这类代码库。\r\n\r\n虽然组件通讯非常方便,但是在真实的业务场景中,不仅仅是父子、爷孙、爷爷和堂兄、嫂子和堂弟...\r\nonXxx=\"xxxx\"就显得无能为力,力不从心了,各种数据传递、组件实例互操作、 emitter/pubsub或者循环依赖,让代码非常难看且难以维护。所以:\r\n\r\n\tOmi.Store是用来管理共享数据以及共享数据的逻辑 。\r\n\t\r\nOmi Store使用足够简便,对架构入侵性极极极小(3个极代表比极小还要小)。下面一步一步从todo的例子看下Store体系怎么使用。\r\n\t\r\n### 定义 Omi.Store\r\n\r\nOmi.Store是基类,我们可以继承Omi.Store来定义自己的Store,比如下面的TodoStore。\r\n\r\n```js\r\nimport Omi from 'omi'\r\n\r\nclass TodoStore extends Omi.Store {\r\n constructor(data , isReady) {\r\n super(isReady)\r\n\r\n this.data = Object.assign({\r\n items:[],\r\n length:0\r\n },data)\r\n\r\n this.data.length = this.data.items.length\r\n }\r\n\r\n add(value){\r\n this.data.items.push(value)\r\n this.data.length = this.data.items.length\r\n this.update()\r\n }\r\n\r\n clear(){\r\n this.data.items.length = 0\r\n this.data.length = 0\r\n this.update()\r\n }\r\n}\r\n\r\nexport default TodoStore\r\n```\r\n\r\nTodoStore定义了数据的基本格式和数据模型的逻辑。\r\n比如 this.data 就是数据的基本格式:\r\n\r\n```js\r\n{\r\n items:[],\r\n length:0\r\n}\r\n```\r\n\r\nadd和clear就是共享数据相关的逻辑。\r\n\r\n值得注意的是,在add和clear方法里都有调用this.update();这个是用来更新组件的,this.update并不会更新所有组件。但是他到底会更新哪些组件呢?等讲到store的addView方法你就明白了。\r\n\r\n### 创建 Omi.Store\r\n\r\n通过 new 关键字来使用TodoStore对象的实例。\r\n\r\n```js\r\nlet store = new TodoStore({ /* 初始化数据 */ ,/* 数据是否准备好 */ })\r\n```\r\n\r\n上面可以传入一些初始化配置信息,store里面便包含了整个应用程序共享的状态数据以及贡献数据逻辑方法(add,clear)。\r\n\r\n当然,这些初始化配置信息可能是异步拉取的。所以,有两种方法解决异步拉取store配置的问题:\r\n\r\n* 拉取数据,然后new TodoStore(),再Omi.render\r\n* 先let store = new TodoStore(),再Omi.render,组件内部监听store.ready,拉取数据更改store的data信息,然后执行store.beReady()\r\n\r\n\r\n### 根组件注入 store\r\n\r\n为了让组件树能够使用到 store,可以通过Omi.render的第三个参数给根组件注入 store:\r\n\r\n```js\r\nOmi.render(new Todo(),'body',{\r\n store: store\r\n});\r\n```\r\n\r\n当然ES2015已经允许你这样写了:\r\n\r\n```js\r\nOmi.render(new Todo(),'body',{\r\n store\r\n});\r\n```\r\n\r\n两份代码同样的效果。\r\n\r\n通过Omi.render注入之后,在组件树的**所有组件**都可以通过 this.$store 访问到 store。\r\n\r\n### 利用 beforeRender\r\n\r\n为什么要说beforeRender这个函数? 因为通过beforeRender转换store的data到组件的data,这样store的数据和组件的数据就解耦开了。\r\n\r\nbeforeRender是生命周期的一部分。且看下面这张图:\r\n\r\n![beforeRender](http://images2015.cnblogs.com/blog/105416/201703/105416-20170322083548924-1871234168.jpg)\r\n\r\n不管是实例化或者存在期间,在render之前,会去执行beforeRender方法。所以可以利用该方法写store的data到组件data的转换逻辑。比如:\r\n\r\n```js\r\nimport Omi from '../../src/index.js';\r\nimport List from './list.js';\r\n\r\nOmi.makeHTML('List', List);\r\n\r\nclass Todo extends Omi.Component {\r\n constructor(data) {\r\n super(data)\r\n }\r\n\r\n install(){\r\n this.$store.addView(this)\r\n }\r\n\r\n beforeRender(){\r\n this.data.length = this.$store.data.items.length\r\n }\r\n\r\n add (evt) {\r\n evt.preventDefault()\r\n let value = this.data.text\r\n this.data.text = ''\r\n this.$store.add(value)\r\n }\r\n\r\n style () {\r\n return `\r\n h3 { color:red; }\r\n button{ color:green;}\r\n `;\r\n }\r\n\r\n clear(){\r\n this.data.text = ''\r\n this.$store.clear()\r\n }\r\n\r\n handleChange(evt){\r\n this.data.text = evt.target.value\r\n }\r\n\r\n render () {\r\n return `
\r\n

TODO

\r\n \r\n \r\n
\r\n \r\n \r\n
\r\n\r\n
`;\r\n }\r\n}\r\n\r\nexport default Todo;\r\n```\r\n\r\n为什么要去写beforeRender方法?因为render只会使用this.data去渲染页面而不会去使用this.$store.data,所以需要把数据转移到组件的this.data下。这样组件既能使用自身的data,也能使用全局放this.$store.data了,不会耦合在一起。\r\n\r\n注意看上面的:\r\n\r\n```js\r\n install(){\r\n this.$store.addView(this)\r\n }\r\n```\r\n\r\n通过 addView 可以让 store 和 view(也就是组件的实例) 关联起来,以后store执行update方法的时候,关联的view都会自动更新!\r\n\r\n再看上面的子组件声明:\r\n\r\n```js\r\n\r\n```\r\n\r\n这样相当于把this.$store.data传递给了List组件。所以在List内部,就不再需要写beforeRender方法转换了。\r\n\r\n```js\r\nclass List extends Omi.Component {\r\n constructor(data) {\r\n super(data)\r\n }\r\n\r\n render () {\r\n return `
    {{#items}}
  • {{.}}
  • {{/items}}
`\r\n }\r\n}\r\n```\r\n\r\n\t这里需要特别强调,不需要把所有的数据提取到store里,只提取共享数据就好了,组件自身的数据还是放在组件自己进行管理。\r\n\r\n\r\n## 异步数据\r\n\r\n通常,在真实的业务需求中,数据并不是马上能够拿到。所以这里模拟的异步拉取的todo数据:\r\n\r\n```js\r\nlet todoStore = new TodoStore()\r\nsetTimeout(()=>{\r\n todoStore.data.items = [\"omi\",\"store\"];\r\n todoStore.data.length = todoStore.data.items.length\r\n todoStore.beReady();\r\n},2000)\r\n```\r\n\r\n上面的beReady就是代码已经准备就绪,在组件内部可以监听ready方法:\r\n\r\n```js\r\nclass Todo extends Omi.Component {\r\n constructor(data) {\r\n super(data)\r\n }\r\n\r\n install(){\r\n this.$store.addView(this)\r\n }\r\n\r\n installed(){\r\n this.$store.ready(()=>this.$store.update())\r\n }\r\n \r\n add (evt) {\r\n evt.preventDefault()\r\n if(!this.$store.isReady){\r\n return\r\n }\r\n let value = this.data.text\r\n this.data.text = ''\r\n this.$store.add(value)\r\n }\r\n```\r\n\r\n可以看到上面的add方法可以通过this.$store.isReady获取组件store是否准备就绪。\r\n\r\n## 源码地址\r\n\r\n* 更为详细的代码可以[点击这里](https://github.com/AlloyTeam/omi/tree/master/example/todo-store)\r\n* 异步拉取的代码可以[点击这里](https://github.com/AlloyTeam/omi/tree/master/example/todo-store-async)" - -/***/ }, -/* 22 */ -/***/ function(module, exports) { - - module.exports = "## 模板切换\r\n\r\nOmi有三个版本。其中的omi.js和omi.lite.js属于Web端使用的版本。\r\n\r\n* omi.js内置了[mustache.js](https://github.com/janl/mustache.js)作为模版引擎\r\n* omi.lite.js不包含任何模版引擎\r\n\r\nOmi不强制开发者使用mustache.js,你可以根据业务场景使用任意模板引擎或者不使用模板引擎。\r\n\r\n那么怎么使用别的模板引擎?下面拿[artTemplate](https://github.com/aui/artTemplate)作为例子。\r\n\r\n### 使用artTemplate\r\n\r\n```js\r\nOmi.template = function(tpl, data){\r\n return artTemplate.compile(tpl)(data);\r\n}\r\n```\r\n重写Omi.template方法,tpl为传入的模板,data为模板所需的数据,返回值为HTML。\r\n重写完毕后就能在render使用artTemplate的语法,如:\r\n\r\n```js\r\nclass List extends Omi.Component {\r\n constructor(data) {\r\n super(data);\r\n }\r\n\r\n style () {\r\n return `\r\n h1 { color:red; }\r\n li{ color:green;}\r\n `;\r\n }\r\n\r\n render () {\r\n return `

{{title}}

\r\n
    \r\n {{each list as value i}}\r\n
  • 索引 {{i + 1}} :{{value}}
  • \r\n {{/each}}\r\n
`;\r\n }\r\n}\r\n```\r\n\r\n### 相关地址\r\n\r\n* [演示地址](http://alloyteam.github.io/omi/example/artTemplate/)\r\n* [源码地址](https://github.com/AlloyTeam/omi/tree/master/example/artTemplate)" - -/***/ }, -/* 23 */ -/***/ function(module, exports) { - - module.exports = "## Omi的理念\n\nOmi的理念是基于面向对象编程体系,内建积木系统。\n 传统的单向数据流或者抛出event的组件通讯方式增加了系统的稳定性,但是丧失了灵活性。一定程度上也降低了组件的复用。所谓鱼和熊掌不可兼得。\n 面向对象体系需要多一个逻辑层,可以自由操作所有组件的instance,instance之间的逻辑关系构建出了整个程序。这样组件间的逻辑,通信,复用就全部迎刃而解。组件也更加单一职责,更松耦合。\n\n对比函数式编程、命令式编程与面向对象编程,可以归纳总结出下面几条:\n\n- 命令式编程干脆直接,利用循环条件等控制流程,强调执行过程\n- 命令式编程对硬件执行友好,运行更容易,却阻碍了复杂程序的设计\n- 函数式强调输入和输出,并非执行过程\n- 函数式倡导多个简单执行单元组合成复杂运算程序\n- 面向对象编程将对象作为程序的基本单元,更具有重用性、灵活性和扩展性\n\nJavascript是哪种类型的语言?现在ES6+已经有了class。那么他是面向对象语言?\n但是JS可以在任意地方定义函数并且当作把函数当作值来传递。那么他是函数式编程语言?\n所以,没有精准的定义,取决于你的用法和姿势。其次,Web组件化架构层面编程模型和语言层面编程模型是非常自由的关系。意思就是,你可以用Javascript构建函数式编程框架如React,也可以基于面向对象体系搭建Omi。\n\n### 函数式编程 VS 面向对象编程\n\n在UI组件框架层面,函数式编程的代表有React,Omi属于面向对象编程体系。那么他们各有什么优缺点?下面做了个对比(其实也是函数式编程与面向对象编程的对比):\n\n| | React | Omi |\n| ------------- |:-------------:|:-----:|\n| 组件通信 | ★★★★☆| ★★★★★ |\n| 稳定性 | ★★★★★ | ★★★★☆ |\n| 灵活性 | ★★★★☆| ★★★★★ |\n| 扩展性 | ★★★★☆ | ★★★★★ |\n| 测试性 | ★★★★★ | ★★★★☆ |\n| 文件大小 | ★★★☆☆ | ★★★★★ |\n| 功能特性 | ★★★☆☆ | ★★★★☆ |\n| DOM性能 | ★★★★★ | ★★★★☆ |\n| 动画性能 | ★★★★☆ | ★★★★★ |\n| 抽象复杂度 | ★★★★☆ | ★★★★★ |\n| 异步编程 | ★★★★★ | ★★★★☆ |\n\n可以看得出,鱼和熊掌不可兼得。面向对象编程更具有重用性、灵活性和扩展性,带来的问题就是更加难测试。\n具体来说,如函数式编程,其测试面积是state1 + state2 + ... + stateN;在面向对象编程中,其测试面积是state1×event1 + state2×event2 + ... + stateN×eventN。\n\n总结来说,更加推荐使用面向对象的方式去搭建UI组件化框架。\n\n
\n\n### 全文结束,感谢阅读。[开始Omi之旅吧!](https://github.com/AlloyTeam/omi) \n\n" - -/***/ }, -/* 24 */ -/***/ function(module, exports) { - - module.exports = "## Component Communication\r\n\r\nCommunication between [Omi](https://github.com/AlloyTeam/omi) components is very flexible, there are many options:\r\n\r\n- By declaring `data-*` on the component to pass data to child node\r\n- By declaring `data` on the component to pass data to child node (support complex data types mapping)\r\n- By declaring `group-data` (support complex data types mapping)\r\n- It's completely object-oriented, you can easily get the object instance, then you can set the instance of the property or call the instance of the method\r\n\r\nLet's see some examples.\r\n\r\n### Communicate by `data-*`\r\n\r\n```js\r\nclass Hello extends Omi.Component {\r\n constructor(data) {\r\n super(data);\r\n }\r\n \r\n style () {\r\n return `\r\n h1{\r\n \tcursor:pointer;\r\n }\r\n `;\r\n }\r\n \r\n handleClick(target, evt){\r\n alert(target.innerHTML);\r\n }\r\n \r\n render() {\r\n return `\r\n
\r\n \t

Hello ,{{name}}!

\r\n
\r\n \t\t`;\r\n }\r\n}\r\n\r\nOmi.makeHTML('Hello', Hello);\r\n\r\nclass App extends Omi.Component {\r\n constructor(data) {\r\n super(data);\r\n }\r\n \r\n render() {\r\n return `\r\n
\r\n \r\n
\r\n `;\r\n }\r\n}\r\n\r\nOmi.render(new App(),\"#container\");\r\n```\r\n\r\nGenerally `data-*` is used to pass value types such as string and number. It is worth noting that, through `data-*`, received data types are string. You need to manually transform it to the number type.\r\n\r\nNormally, communicate by `data-*` is enough, but sometimes we may need to use complex data types, then we can use `data` to communicate.\r\n\r\n### Communicate by `data`\r\n\r\nAs shown in the above code, name can be passed to the subcomponent by `data-name=\"Omi\"`. The following code can also achieve the same effect.\r\n\r\n```js\r\n...\r\nclass App extends Omi.Component {\r\n constructor(data) {\r\n super(data);\r\n this.helloData = { name : 'Omi' };\r\n }\r\n \r\n render() {\r\n return `\r\n
\r\n \r\n
\r\n `;\r\n }\r\n}\r\n\r\nOmi.render(new App(),\"#container\");\r\n```\r\n\r\nUse the `data` tag, it will find the property from the component instance (that is, this), this can be mounted with any complex objects. This also broke the limitations of `data-*`.\r\n\r\nThen how do we pass `data` that is in a deep depth of the instance to the Hello? No worries, `data` tag can be a complex statement:\r\n\r\n```js\r\n...\r\nclass App extends Omi.Component {\r\n constructor(data) {\r\n super(data);\r\n this.complexData ={\r\n a:{\r\n b:{\r\n c:[\r\n {\r\n e:[{\r\n name:'ComplexData Support1'\r\n },{\r\n name:'ComplexData Support2'\r\n }]\r\n },\r\n {\r\n name: 'ComplexData Support3'\r\n }\r\n ]\r\n }\r\n }\r\n };\r\n }\r\n \r\n render() {\r\n return `\r\n
\r\n \r\n
\r\n `;\r\n }\r\n}\r\n...\r\n```\r\n\r\nClick me for the complex data mapping\r\n\r\n### Communicate by `group-data`\r\n\r\n`group-data` can pass data to a group of components. \r\n\r\n```js\r\nimport Hello from './hello.js';\r\n\r\n\r\nOmi.makeHTML('Hello', Hello);\r\n\r\nclass App extends Omi.Component {\r\n constructor(data) {\r\n super(data);\r\n this.testData = [{name: 'Omi'}, {name: 'dntzhang'}, {name: 'AlloyTeam'}];\r\n }\r\n\r\n render() {\r\n return `\r\n
\r\n \r\n \r\n \r\n
\r\n `;\r\n\r\n }\r\n}\r\n\r\nOmi.render(new App(),\"#container\");\r\n```\r\n\r\nBy declaring a `group-data` tag in the sub-components, it will go to the current instance of the component (that is, `this`) to find the corresponding property. Then according to the current location, the data will pass to the positions one by one.\r\n\r\nThe results are as follows:\r\n\r\n![group-data results](http://images2015.cnblogs.com/blog/105416/201702/105416-20170216110701535-1698390390.png)\r\n\r\nClick me for the group-data example\r\n\r\nSimilarly, `group-data` supports the mapping of complex data types. It should be noted that the end of the group-data mapping must be an array:\r\n\r\n```js\r\nimport Hello from './hello.js';\r\n\r\n\r\nOmi.makeHTML('Hello', Hello);\r\n\r\nclass App extends Omi.Component {\r\n constructor(data) {\r\n super(data);\r\n this.complexData ={\r\n a:{\r\n b:{\r\n c:[\r\n {\r\n e:[{\r\n name:'ComplexData Support1'\r\n },{\r\n name:'ComplexData Support2'\r\n }]\r\n },\r\n {\r\n name: 'ComplexData Support3'\r\n }\r\n ]\r\n }\r\n }\r\n };\r\n }\r\n\r\n render() {\r\n return `\r\n
\r\n \r\n \r\n
\r\n `;\r\n\r\n }\r\n}\r\n\r\nOmi.render(new App(),\"#container\");\r\n```\r\n\r\nClick me for the complex group-data mapping\r\n\r\n### By object instance\r\n\r\n```js\r\n...\r\nclass App extends Omi.Component {\r\n constructor(data) {\r\n super(data);\r\n }\r\n \r\n installed(){\r\n this.hello.data.name = \"Omi\";\r\n this.update()\r\n }\r\n \r\n render() {\r\n return `\r\n
\r\n \r\n
\r\n `;\r\n }\r\n}\r\n\r\nOmi.render(new App(),\"#container\");\r\n```\r\n\r\n### By omi-id\r\n\r\n```js\r\n...\r\nclass App extends Omi.Component {\r\n constructor(data) {\r\n super(data);\r\n }\r\n \r\n installed(){\r\n Omi.get(\"hello\").data.name = \"Omi\";\r\n this.update()\r\n }\r\n \r\n render() {\r\n return `\r\n
\r\n \r\n
\r\n `;\r\n }\r\n}\r\n\r\nOmi.render(new App(),\"#container\");\r\n```\r\n\r\nBy declaring `omi-id` on the component, we can get the instance of the object anywhere in the program. This can be regarded as any component communication artifacts.\r\n\r\n" - -/***/ }, -/* 25 */ -/***/ function(module, exports) { - - module.exports = "## Components\r\n\r\n[Omi](https://github.com/AlloyTeam/omi) is based entirely on component architecture, which allows developers to build web applications like building blocks. Everything is components, components can be nested to create new components.\r\n\r\n![Omi Components System](http://images2015.cnblogs.com/blog/105416/201702/105416-20170210093427338-1536910080.png)\r\n\r\n### Simple Components\r\n\r\nLet's explore a simple Todo example to learn the components system in Omi.\r\n\r\n```js\r\nclass Todo extends Omi.Component {\r\n constructor(data) {\r\n super(data);\r\n }\r\n \r\n add (evt) {\r\n evt.preventDefault();\r\n this.data.items.push(this.data.text);\r\n this.data.text = '';\r\n this.update();\r\n }\r\n\r\n style () {\r\n return `\r\n h3 { color:red; }\r\n button{ color:green;}\r\n `;\r\n }\r\n\r\n handleChange(target){\r\n this.data.text = target.value;\r\n }\r\n\r\n render () {\r\n return `
\r\n

TODO

\r\n
    {{#items}}
  • {{.}}
  • {{/items}}
\r\n
\r\n \r\n \r\n
\r\n
`;\r\n }\r\n}\r\n\r\nOmi.render(new Todo({ items: [] ,text : '' }),\"body\");\r\n```\r\n\r\nThe HTML generated by the component will eventually be inserted into the body. The above example shows some of the features of Omi:\r\n\r\n- Data flow: `data` in `new Todo(data,..)` can be used directly in the template in render method.\r\n- Partial CSS: `h3` in `style()` only effect inside of render. It'll never pollute `h3` outside of this component. The same rule applies to `button`.\r\n- Declarative event binding: `onchange` will call `handleChange` that inside of the component. `this` refers to the current DOM element, `event` refers to the current DOM Event Object.\r\n- You need to manually call the `this.update()` method to update the component\r\n\r\nIt is important to note that, for more freedom and flexibility, Omi does not automatically update DOM while data changes. Developers need to call the `update` method manually.\r\n\r\nYou can also use [oba] (https://github.com/dntzhang/oba) or mobx to implement automatic updates.\r\n\r\nClick me for the live demo\r\n\r\n### Component Nesting\r\n\r\nIt's ok to not use nesting component if your page is super simple. However, for most of webpages and web applications, it is a necessary to define the nesting Components to implement complex features.\r\n\r\nFor instance, we can extract a `List` component form the Todo example. This brings maintainable, scalable and reuseable to our project:\r\n\r\n```js\r\nclass List extends Omi.Component {\r\n constructor(data) {\r\n super(data);\r\n }\r\n\r\n render () {\r\n return `
    {{#items}}
  • {{.}}
  • {{/items}}
`;\r\n }\r\n}\r\n```\r\n\r\nThen how to use this `List`? We need to use `Omi.makeHTML` to make the `List` to a tag which can be used in render method:\r\n\r\n```js\r\nimport List from './list.js';\r\n\r\nOmi.makeHTML('List', List);\r\n\r\nclass Todo extends Omi.Component {\r\n constructor(data) {\r\n super(data);\r\n this.data.length = this.data.items.length;\r\n this.listData = { items : this.data.items };\r\n }\r\n\r\n add (evt) {\r\n evt.preventDefault();\r\n this.list.data.items.push(this.data.text);\r\n this.data.length = this.list.data.items.length;\r\n this.data.text = '';\r\n this.update();\r\n }\r\n\r\n style () {\r\n return `\r\n h3 { color:red; }\r\n button{ color:green;}\r\n `;\r\n }\r\n\r\n handleChange(target){\r\n this.data.text = target.value;\r\n }\r\n\r\n render () {\r\n return `
\r\n

TODO

\r\n \r\n
\r\n \r\n \r\n
\r\n
`;\r\n }\r\n}\r\n```\r\n\r\n- In line 3, we use `makeHTML` to make the component to a tag which can be used in render method. Of course, `Omi.makeHTML('List', List);` can also be written in the end of List component.\r\n- In line 9, the parent component defines the 'listData' property\r\n- In line 34, we use List component in the render method. `name` attribute allows us easily find the instance of the component by using `this`.`data=\"listData\"` attribute allows us easily pass `this.listData` to the sub component from parent component.\r\n\r\nIt should be noted that the `data` passed from `data=\"listData\"` is cloned to the subcomponents by Object.assign(shallow copy) , which means if we want to change the DOM, we recommend that first update the `data` of the instance of subcomponent(not the parent component's `listData` ) and secondly call the `update` method.\r\n\r\nIn fact there are 4 way to communicate between components, it'll be explained later.\r\n\r\nClick me for the live demo\r\n" - -/***/ }, -/* 26 */ -/***/ function(module, exports) { - - module.exports = "## Conditional Rendering\r\n\r\nIn most case, we need to show different layouts according to different states. For example, some users are vip and we need to show vip logo for them. Omi has many ways to meet this kind of requirements.\r\n\r\n### First Option\r\n\r\n```js\r\nclass ConditionTest extends Omi.Component {\r\n constructor(data) {\r\n super(data);\r\n }\r\n\r\n render () {\r\n return `{{#isVip}}\r\n
you are VIP.
\r\n {{/isVip}}\r\n {{^isVip}}\r\n
you are not VIP.
\r\n {{/isVip}}`;\r\n }\r\n}\r\n```\r\n\r\nIn the above case, we use the condition in mustachejs for rendering. Of course Omi does not force you to use mustachejs. You can use omi.lite.js and then override the `Omi.template` method to use any of your favorite template engines.\r\n\r\n### Second Option\r\n\r\n```js\r\nclass ConditionTest extends Omi.Component {\r\n constructor(data) {\r\n super(data);\r\n }\r\n\r\n render () {\r\n if(this.data.isVip){\r\n return '
you are VIP.
';\r\n }else{\r\n return '
you are not VIP.
';\r\n }\r\n }\r\n}\r\n```\r\n\r\n`render` provides a very good programmability, which can write any js code inside. Oh, don't forget that `style` method can also have js code inside it.\r\n\r\n```js\r\nclass ConditionTest extends Omi.Component {\r\n constructor(data) {\r\n super(data);\r\n }\r\n\r\n style (){\r\n if(this.data.isVip){\r\n return 'div{ color : red; }';\r\n }else{\r\n return 'div{ color : green; }';\r\n }\r\n }\r\n\r\n render () {\r\n if(this.data.isVip){\r\n return '
you are VIP.
';\r\n }else{\r\n return '
you are not VIP.
';\r\n }\r\n }\r\n}\r\n```" - -/***/ }, -/* 27 */ -/***/ function(module, exports) { - - module.exports = "## Handling Events\r\n\r\nThere are two types of events in Omi, built-in events and custom events. Built-in events clever use of the browser's own pipeline mechanism, you can easily get events instance and the triggered event elements through `event` and `this`.\r\n\r\n### Built-in events\r\n\r\nWhat is the built-in event? As long as the it can match the following regular expression.\r\n\r\n```js\r\non(abort|blur|cancel|canplay|canplaythrough|change|click|close|contextmenu|cuechange|dblclick|drag|dragend|dragenter|dragleave|dragover|dragstart|drop|durationchange|emptied|ended|error|focus|input|invalid|keydown|keypress|keyup|load|loadeddata|loadedmetadata|loadstart|mousedown|mouseenter|mouseleave|mousemove|mouseout|mouseover|mouseup|mousewheel|pause|play|playing|progress|ratechange|reset|resize|scroll|seeked|seeking|select|show|stalled|submit|suspend|timeupdate|toggle|volumechange|waiting|autocomplete|autocompleteerror|beforecopy|beforecut|beforepaste|copy|cut|paste|search|selectstart|wheel|webkitfullscreenchange|webkitfullscreenerror|touchstart|touchmove|touchend|touchcancel|pointerdown|pointerup|pointercancel|pointermove|pointerover|pointerout|pointerenter|pointerleave)\r\n```\r\n\r\nHow to bind built-in events? As follows:\r\n\r\n```js\r\nclass EventTest extends Omi.Component {\r\n constructor(data) {\r\n super(data);\r\n }\r\n\r\n handleClick(dom, evt){\r\n alert(dom.innerHTML);\r\n }\r\n\r\n render () {\r\n return `
Hello, Omi!
`;\r\n }\r\n}\r\n```\r\n\r\n### Custom events\r\n\r\nEvents that defined by developers is the custom events. Here is the pagination example:\r\n\r\n```js\r\nimport Omi from '../../src/index.js';\r\nimport Pagination from './pagination.js';\r\nimport Content from './content.js';\r\n\r\nOmi.makeHTML('Pagination', Pagination);\r\nOmi.makeHTML('Content', Content);\r\n\r\nclass Main extends Omi.Component {\r\n constructor(data) {\r\n super(data);\r\n }\r\n\r\n installed(){\r\n this.content.goto(this.pagination.data.currentPage+1);\r\n }\r\n \r\n handlePageChange(index){\r\n this.content.goto(index+1);\r\n }\r\n\r\n render () {\r\n return `
\r\n

Pagination Example

\r\n \r\n \r\n
`;\r\n }\r\n}\r\n\r\nOmi.render( new Main(),'body');\r\n```\r\n\r\nAs we can see, the `onPageChange` is a custom event, `handlePageChange` will being executed when `onPageChange` is triggered. The `onPageChange` method is executed in `Pagination`:\r\n\r\n```js\r\nimport Omi from '../../src/index.js';\r\n\r\nclass Pagination extends Omi.Component {\r\n ...\r\n ...\r\n ...\r\n linkTo: \"#\",\r\n prevText: \"Prev\",\r\n nextText: \"Next\",\r\n ellipseText: \"...\",\r\n prevShow: true,\r\n nextShow: true,\r\n onPageChange: function () { return false; }\r\n }, this.data);\r\n\r\n this.pageNum = Math.ceil(this.data.total / this.data.pageSize);\r\n }\r\n \r\n goto (index,evt) {\r\n evt.preventDefault();\r\n this.data.currentPage=index;\r\n this.update();\r\n this.data.onPageChange(index);\r\n }\r\n ...\r\n ...\r\n ...\r\n}\r\n```\r\n\r\nThis is a part of `Pagination` code. Highlight is the place to execute `onPageChange`.\r\n\r\n### Links\r\n\r\n- [Demo](http://alloyteam.github.io/omi/example/pagination/)\r\n- [Source](https://github.com/AlloyTeam/omi/tree/master/example/pagination)" - -/***/ }, -/* 28 */ -/***/ function(module, exports) { - - module.exports = "## Forms\r\n\r\nIt's much more convenient to control forms in Omi, especially `\r\n \r\n \r\n \r\n \r\n\r\n```\r\n\r\nThe third option is selected because it is being set to `selected` attribute. The problem is that developers need to traversed each option. While using Omi, you can write code like this:\r\n\r\n```html\r\n\r\n```\r\n\r\nThis will achieve the same effect. For example, you want to choose the first item:\r\n\r\n```html\r\n\r\n```\r\n\r\nIsn't it very convenient?\r\n\r\n### For Example\r\n\r\n```js\r\nclass FormTest extends Omi.Component {\r\n constructor(data) {\r\n super(data);\r\n \r\n }\r\n\r\n handleChange(target){\r\n console.log(target.value)\r\n this.data.value = target.value;\r\n }\r\n\r\n handleSubmit(evt) {\r\n alert('Your favorite flavor is: ' + this.data.value);\r\n evt.preventDefault();\r\n }\r\n \r\n render () {\r\n return `\r\n
\r\n \r\n \r\n
`;\r\n }\r\n}\r\n\r\nOmi.render(new FormTest({ value: 'mango' }),'#container');\r\n```\r\n\r\nClick me for a live demo" - -/***/ }, -/* 29 */ -/***/ function(module, exports) { - - module.exports = "## Get DOM\r\n\r\nWhile most of the time, developers do not need to find the DOM, but sometimes is a need to get the DOM.\r\n\r\nOmi provides a way to get the DOM node.\r\n\r\n### ref and refs\r\n\r\n```js\r\nclass Hello extends Omi.Component {\r\n constructor(data) {\r\n super(data);\r\n }\r\n \r\n style () {\r\n return `\r\n h1{\r\n cursor:pointer;\r\n }\r\n `;\r\n }\r\n \r\n handleClick(){\r\n alert(this.refs.abc.innerHTML);\r\n }\r\n \r\n render() {\r\n return `\r\n
\r\n

Hello ,{{name}}!

\r\n
\r\n `;\r\n }\r\n}\r\n\r\nOmi.render(new Hello({ name : \"Omi\" }),\"#container\");\r\n```\r\n\r\nAs we can see, by referencing `ref` as `abc` in HTML, the DOM node can be accessed through `this.refs.abc`.\r\n\r\nClick me for the live demo\r\n" - -/***/ }, -/* 30 */ -/***/ function(module, exports) { - - module.exports = "## Hello World\r\n\r\n### Hello World with ES20XX \r\n\r\nWe recommend using a bundler like [webpack](https://webpack.github.io/) or [Browserify](http://browserify.org/) so you can write modular code and bundle it together into small packages to optimize load time.\r\n\r\nThe small Omi example looks like this:\r\n\r\n```js\r\nimport Omi from './omi.js';\r\n\r\nclass Hello extends Omi.Component {\r\n constructor(data) {\r\n super(data);\r\n }\r\n \r\n style () {\r\n return `\r\n h1{\r\n cursor:pointer;\r\n }\r\n `;\r\n }\r\n \r\n handleClick(target){\r\n alert(target.innerHTML);\r\n }\r\n \r\n render() {\r\n return `\r\n
\r\n

Hello ,{{name}}!

\r\n
\r\n `;\r\n }\r\n}\r\n\r\nOmi.render(new Hello({ name : \"Omi\" }),\"body\");\r\n```\r\n\r\nThis code renders into body element. \r\n\r\n### Hello World with ES5\r\n\r\n```html\r\n\r\n```\r\n\r\nthen:\r\n\r\n```js\r\nvar Hello = Omi.create(\"Hello\", {\r\n style: function () {\r\n return \"h1{ cursor:pointer }\";\r\n },\r\n \r\n handleClick: function (dom) {\r\n alert(dom.innerHTML)\r\n },\r\n \r\n render: function () {\r\n return '
\\\r\n

\\\r\n Hello ,{{name}}!\\\r\n

\\\r\n
'\r\n }\r\n});\r\n\r\nvar Test = Omi.create(\"Test\", {\r\n render: function () {\r\n return '
\\\r\n
Test
\\\r\n \\\r\n
'\r\n }\r\n});\r\n\r\nOmi.render(new Test(),'#container');\r\n```" - -/***/ }, -/* 31 */ -/***/ function(module, exports) { - - module.exports = "## Inheritance\r\n\r\nThrough the inheritance mechanism, we can define new classes base on old classes. The new classes not only have newly defined members, but also have old members at the same time.\r\n\r\nWe call the existing class the base class, also known as the parent class. And the new class derived from the existing class is called a derived class, also known as a subclass.\r\n\r\n### For Example\r\n\r\n```js\r\nclass Hello extends Omi.Component {\r\n constructor(data) {\r\n super(data);\r\n }\r\n \r\n style () {\r\n return `\r\n div{\r\n cursor:pointer;\r\n }\r\n `;\r\n }\r\n \r\n handleClick(target, evt){\r\n alert(target.innerHTML);\r\n }\r\n \r\n render() {\r\n return '
Hello {{name}}!
'\r\n }\r\n}\r\n\r\nclass SubHello extends Hello {\r\n constructor(data) {\r\n super(data);\r\n }\r\n}\r\n\r\nOmi.render(new SubHello({ name : 'Omi' }),'#container');\r\n```\r\n\r\nClick me for the live demo\r\n\r\n### inherit in ES5\r\n\r\n```js\r\nvar Hello = Omi.create(\"Hello\",{\r\n render:function(){\r\n return '
Hello {{name}}!
'\r\n }\r\n})\r\n\r\nvar SubHello = Omi.create(\"SubHello\",Hello,{ });\r\n\r\n\r\nOmi.render(new SubHello({ name : 'Omi' }),'#container');\r\n```\r\n\r\nClick me for the live demo" - -/***/ }, -/* 32 */ -/***/ function(module, exports) { - - module.exports = "## Installation\r\n\r\n[Omi](https://github.com/AlloyTeam/omi) is open and modern framework for building user interfaces.\r\n\r\n### Installing Omi\r\n\r\nWe recommend using [npm](https://www.npmjs.com/) for managing front-end dependencies. If you're new to package managers.\r\n\r\nTo install Omi with npm, run:\r\n\r\n``` js\r\n$ npm install omi\r\n```\r\n### omi-cli\r\n\r\n``` js\r\n$ npm install omi-cli -g \r\n$ omi init your_project_name \r\n$ cd your_project_name \r\n$ npm run dev \r\n$ npm run dist \r\n```" - -/***/ }, -/* 33 */ -/***/ function(module, exports) { - - module.exports = "## Lifecycle\r\n\r\n| Name | Meaning | Occasion |\r\n| :-------------: | :-------------: | :-----: |\r\n| constructor | The constructor | When new a constructor |\r\n| install | The installation. We can process the data that user pass | When instantiate |\r\n| installed | Complete the installation. It'll trigger after HTML being inserted to the page. Please note that it'll trigger when component being removed and restored | **Instantiation and existence** |\r\n| uninstall | Uninstall the component. It'll trigger when remove is executed | When destroy |\r\n| beforeUpdate | Before update | When existence |\r\n| afterUpdate | After update | When existence |\r\n\r\n## Illustration\r\n\r\n![lc](http://images2015.cnblogs.com/blog/105416/201703/105416-20170322084234049-1482108845.jpg)\r\n\r\nIt should be noted that the installed will be executed during the instantiation, which is not shown above. For example, it'll executed when a component is removed and restored, or when the new component is being added.\r\n\r\n### Examples\r\n\r\n```js\r\nclass Timer extends Omi.Component {\r\n constructor(data) {\r\n super(data);\r\n }\r\n\r\n install () {\r\n this.data = {secondsElapsed: 0};\r\n }\r\n\r\n tick() {\r\n this.data.secondsElapsed++;\r\n this.update();\r\n }\r\n\r\n installed(){\r\n this.interval = setInterval(() => this.tick(), 1000);\r\n }\r\n\r\n uninstall() {\r\n clearInterval(this.interval);\r\n }\r\n\r\n\r\n style () {\r\n return `\r\n .num { color:red; }\r\n `;\r\n }\r\n\r\n render () {\r\n return `
Seconds Elapsed: {{secondsElapsed}}
`;\r\n }\r\n}\r\n```\r\n\r\nClick me for the live demo" - -/***/ }, -/* 34 */ -/***/ function(module, exports) { - - module.exports = "## Loop\r\n\r\nThe following describes how to traverses in mustache.js and javascript.\r\n\r\n### First Option\r\n\r\n```js\r\nclass List extends Omi.Component {\r\n constructor(data) {\r\n super(data);\r\n }\r\n\r\n render () {\r\n return `
\r\n
    \r\n {{#items}} \r\n
  • {{text}}
  • \r\n {{/items}}\r\n
\r\n
`;\r\n }\r\n}\r\n\r\nOmi.render(new List({\r\n items: [\r\n {id: 1, text: 'Omi'},\r\n {id: 2, text: 'dntzhang'},\r\n {id: 3, text: 'AlloyTeam'}\r\n ]\r\n}),\"body\");\r\n```\r\n\r\nMustache.js more detailed loop traversal use can see \r\n\r\nFor more details for traversal in mustache.js please view [https://github.com/janl/mustache.js#non-empty-lists](https://github.com/janl/mustache.js#non-empty-lists).\r\n\r\nFor example, it also support:\r\n\r\n- If each item of items is a string, you can directly use **{{.}}** to output each item\r\n- Call the defined function when looping\r\n\r\nClick me for the live demo\r\n\r\n### Second Option\r\n\r\nOf course, you can also use template string inside the `map`:\r\n\r\n```js\r\nclass List extends Omi.Component {\r\n constructor(data) {\r\n super(data);\r\n }\r\n\r\n render() {\r\n return `
\r\n
    \r\n ${this.data.items.map(item =>\r\n `
  • ${item.text}
  • `\r\n ).join('')}\r\n
\r\n
`;\r\n }\r\n}\r\n\r\nOmi.render(new List({\r\n items: [\r\n {id: 1, text: 'Omi'},\r\n {id: 2, text: 'dntzhang'},\r\n {id: 3, text: 'AlloyTeam'}\r\n ]\r\n}),\"body\");\r\n```\r\n\r\nYou will see the following page:\r\n\r\n![pv](http://images2015.cnblogs.com/blog/105416/201701/105416-20170122095724129-2059595233.png)\r\n\r\nClick me for the live demo" - -/***/ }, -/* 35 */ -/***/ function(module, exports) { - - module.exports = "## Plugin\r\n\r\n[Omi](https://github.com/AlloyTeam/omi) is a componentized web framework. Then what is plugin?\r\n\r\nIt can be understood that the Omi plugin system can give the dom element some ability and can be associated with the instance of the components.\r\n\r\n### omi-drag\r\n\r\nLet's see this example:\r\n\r\nClick me for the live deme\r\n\r\n```js\r\nimport OmiDrag from './omi-drag.js';\r\n\r\nOmiDrag.init();\r\n\r\nclass App extends Omi.Component {\r\n constructor(data) {\r\n super(data);\r\n }\r\n\r\n render() {\r\n return `\r\n
\r\n
Drag Me
\r\n
\r\n `;\r\n\r\n }\r\n\r\n style(){\r\n return `\r\n .test{\r\n width:100px;\r\n height:100px;\r\n color:white;\r\n line-height:90px;\r\n text-align:center;\r\n background-color:#00BFF3;\r\n }\r\n `\r\n }\r\n}\r\n\r\nOmi.render(new App(),\"#container\");\r\n```\r\n\r\nAs shown above, by adding `omi-drag` attribute to the div, it can be dragged by the user using the mouse. We call omi-drag.js an omi plugin.\r\n\r\nIsn't it very convenient? So how did this omi-drag implement?\r\n\r\n如上面的代码所示,通过在div上标记omi-drag,这个div就能够被用户使用鼠标拖拽。我们称omi-drag.js为omi插件。\r\n是不是非常方便?那么这个omi-drag是怎么实现的?\r\n\r\n## Omi.extendPlugin\r\n\r\nCore method: Omi.extendPlugin( pluginName, handler )\r\n\r\nThe following code shows how to use `Omi.extendPlugin` to give dom the drap and drop ability:\r\n\r\n```js\r\n;(function () {\r\n\r\n var OmiDrag = {};\r\n var Omi = typeof require === 'function'\r\n ? require('omi')\r\n : window.Omi;\r\n\r\n OmiDrag.init = function(){\r\n Omi.extendPlugin('omi-drag',function(dom, instance){\r\n dom.style.cursor='move';\r\n var isMouseDown = false,\r\n preX = null,\r\n preY = null,\r\n currentX = null,\r\n currentY = null,\r\n translateX = 0,\r\n translateY = 0;\r\n\r\n dom.addEventListener('mousedown',function(evt){\r\n isMouseDown = true;\r\n preX = evt.pageX;\r\n preY = evt.pageY;\r\n evt.stopPropagation();\r\n },false);\r\n\r\n window.addEventListener('mousemove',function(evt){\r\n if(isMouseDown){\r\n currentX = evt.pageX;\r\n currentY = evt.pageY;\r\n if(preX != null){\r\n translateX += currentX - preX;\r\n translateY += currentY - preY;\r\n dom.style.transform = 'translateX('+translateX+'px) translateY('+translateY+'px)';\r\n }\r\n preX = currentX;\r\n preY = currentY;\r\n evt.preventDefault();\r\n }\r\n },false);\r\n\r\n window.addEventListener('mouseup',function(){\r\n isMouseDown = false;\r\n preX = preY = currentX = currentY = null;\r\n },false);\r\n });\r\n }\r\n\r\n OmiDrag.destroy = function(){\r\n delete Omi.plugins['omi-drag'];\r\n };\r\n\r\n if (typeof exports == \"object\") {\r\n module.exports = OmiDrag;\r\n } else if (typeof define == \"function\" && define.amd) {\r\n define([], function(){ return OmiDrag });\r\n } else {\r\n window.OmiDrag = OmiDrag;\r\n }\r\n\r\n})();\r\n```\r\n\r\nMethod: Omi.extendPlugin( pluginName, handler )\r\n\r\n`pluginName` is the name of the plugin.\r\n\r\n`handler` is the processor. The handler can get the dom which marked as the `pluginName` and the instance of the component.\r\n\r\nWith `Omi.extendPlugin`, we can give the dom some ability, and can also be associated with the component instance.\r\n\r\nThe above example is not associated with the instance, let's try it:\r\n\r\n## Associated with instance\r\n\r\nWe want to be able to listen to the `move` inside the component and perform a callback. As follows:\r\n\r\n```js\r\n...\r\n...\r\nmoveHandler(){\r\n console.log('moving');\r\n}\r\n\r\nrender() {\r\n return `\r\n
\r\n
Drag Me
\r\n
\r\n `;\r\n}\r\n...\r\n```\r\n\r\nIn this case, the `moveHandler` will be continually executed while dragging. We can modify some code to solve this issue:\r\n\r\n```js\r\n...\r\nwindow.addEventListener('mousemove',function(evt){\r\n if(isMouseDown){\r\n currentX = evt.pageX;\r\n currentY = evt.pageY;\r\n if(preX != null){\r\n translateX += currentX - preX;\r\n translateY += currentY - preY;\r\n dom.style.transform = 'translateX('+translateX+'px) translateY('+translateY+'px)';\r\n }\r\n preX = currentX;\r\n preY = currentY;\r\n evt.preventDefault();\r\n instance.moveHandler(evt);\r\n }\r\n},false);\r\n```\r\n\r\nWe add `instance.moveHandler(evt)` method to execute the `moveHandler` method of component instance.\r\n\r\nThis is how associated with instance works.\r\n\r\nHowever, this may still have an issue if we add `omi-drag` to a list of `div`:\r\n\r\n```js\r\n...\r\nrender() {\r\n return `\r\n
\r\n
Drag Me
\r\n
Drag Me
\r\n
\r\n `;\r\n}\r\n...\r\n```\r\n\r\nUsually each of our `omi-drag` can correspond to a callback function, such as:\r\n\r\n```js\r\n...\r\n...\r\nmoveHandlerA(){\r\n console.log('moving');\r\n}\r\n\r\nmoveHandlerB(){\r\n console.log('moving');\r\n}\r\n\r\nrender() {\r\n return `\r\n
\r\n
Drag Me A
\r\n
Drag Me B
\r\n
\r\n `;\r\n}\r\n...\r\n```\r\n\r\nHow to achieve this? We can pass the data to the plugin via dom.\r\n\r\n## Passing data\r\n\r\nLet's see the final code:\r\n\r\n```js\r\n...\r\n...\r\nmoveHandlerA(){\r\n console.log('moving');\r\n}\r\n\r\nmoveHandlerB(){\r\n console.log('moving');\r\n}\r\n\r\nrender() {\r\n return `\r\n
\r\n
Drag Me A
\r\n
Drag Me B
\r\n
\r\n `;\r\n}\r\n...\r\n```\r\n\r\nWhere `omi-drag` modified:\r\n\r\n```js\r\n...\r\nvar handlerName = dom.getAttribute('dragMove');\r\n\r\nwindow.addEventListener('mousemove',function(evt){\r\n if(isMouseDown){\r\n currentX = evt.pageX;\r\n currentY = evt.pageY;\r\n if(preX != null){\r\n translateX += currentX - preX;\r\n translateY += currentY - preY;\r\n dom.style.transform = 'translateX('+translateX+'px) translateY('+translateY+'px)';\r\n }\r\n preX = currentX;\r\n preY = currentY;\r\n evt.preventDefault();\r\n instance[handlerName](evt);\r\n }\r\n},false);\r\n...\r\n```\r\n\r\n- We use `var handlerName = dom.getAttribute('dragMove')` to get the `dragMove` of dom\r\n- We use `instance[handlerName](evt)` to execute the method\r\n\r\nClick me for the live demo\r\n\r\n## More plugins\r\n\r\n* [omi-finger](https://github.com/AlloyTeam/omi/tree/master/plugins/omi-finger) The [AlloyFinger](https://github.com/AlloyTeam/AlloyFinger) plugin for Omi, which support touch events and gustures\r\n* [omi-transform](https://github.com/AlloyTeam/omi/tree/master/plugins/omi-transform) The [transformjs](http://alloyteam.github.io/AlloyTouch/transformjs/) plugin for Omi, which can easily set CSS3 Transform to DOM\r\n* [omi-touch](https://github.com/AlloyTeam/omi/tree/master/plugins/omi-touch) The [AlloyTouch](https://github.com/AlloyTeam/AlloyTouch) plugin for Omi. The touch movement solution for Omi (support touch scroll, rotate, flip, select, etc.)\r\n* [omi-jquery-date-picker](https://github.com/AlloyTeam/omi/tree/master/plugins/omi-jquery-date-picker) The date picker plugin for Omi, which support choose any time zone\r\n" - -/***/ }, -/* 36 */ -/***/ function(module, exports) { - - module.exports = "## Templates\r\n\r\nThere are three types of Omi. omi.js and omi.lite.js is for web side.\r\n\r\n- omi.js has a built-in [mustache.js](https://github.com/janl/mustache.js) as the template engine\r\n- omi.lite.js doesn't have any template engines\r\n\r\nOmi does not force developers to use mustache.js, you can use any template engine based on business scenarios or do not use any template engines.\r\n\r\nHow to use other template engines? Let's see the [artTemplate](https://github.com/aui/artTemplate) example.\r\n\r\n### Use artTemplate\r\n\r\n```js\r\nOmi.template = function(tpl, data){\r\n return artTemplate.compile(tpl)(data);\r\n}\r\n```\r\n\r\nWe need to rewrite the `Omi.template` method, the `tpl` is the incoming template, the `data` is the required data for the template, and the return value is HTML.\r\n\r\nAfter rewriting, you can use the artTemplate syntax in `render`, such as:\r\n\r\n```js\r\nclass List extends Omi.Component {\r\n constructor(data) {\r\n super(data);\r\n }\r\n\r\n style () {\r\n return `\r\n h1 { color:red; }\r\n li{ color:green;}\r\n `;\r\n }\r\n\r\n render () {\r\n return `

{{title}}

\r\n
    \r\n {{each list as value i}}\r\n
  • # {{i + 1}} :{{value}}
  • \r\n {{/each}}\r\n
`;\r\n }\r\n}\r\n```\r\n\r\n### Links\r\n\r\n* [Demo Link](http://alloyteam.github.io/omi/example/artTemplate/)\r\n* [Source Code](https://github.com/AlloyTeam/omi/tree/master/example/artTemplate)" - -/***/ }, -/* 37 */ -/***/ function(module, exports) { - - module.exports = "## Thinking in Omi\r\n\r\nOmi is based on object-oriented programming, with plugin system.\r\n\r\nThe traditional one-way data flow or the event-throwing component communicating can increase the stability of the system, but it loses it's flexibility. To a certain extent also reduced the component reusing.\r\n\r\nObject-oriented system has an other logical layer, which let you control the instance of components. The logic between instances build the entire program.\r\n\r\nThen the issues like communication, reusing and logics between components are all solved.\r\n\r\n\r\nPlus, the component is also more single duty, more loosely coupled.\r\n\r\nFor functional programming, imperative programming and object-oriented programming, we can sum up the following list:\r\n\r\n- Imperative programming is well understood, we use loop and if-else condition to control processes, it emphasize the process of execution\r\n- Imperative programming is hardware friendly, easy to run, but hard to design complex program\r\n- Functional programming is all about input and output, not the process of execution\r\n- Functional programming advocates multiple simple execution units into complex operations\r\n- Object-oriented programming uses objects as the basic unit of the program, with more reusability, flexibility, and extensibility\r\n\r\nWhat kind of language is JavaScript? We have `class` in ES6+, so is JavaScript object-oriented language?\r\n\r\nJavaScript can pass a function as a argumant, so is JavaScript a functional language?\r\n\r\nThere are no right answer, it depands on how you use JavaScript.\r\n\r\nIt's free to chooce, you can use functional programming framework like React, or object-oriented framework like Omi. \r\n\r\n### Functional Programming VS Object-Oriented Programming\r\n\r\nIn the UI component framework scope, functional programming is represented by React, while Omi belongs to object-oriented programming.\r\n\r\nSo what are their strengths and weaknesses? The following is a comparison (in fact, functional programming and object-oriented programming comparison):\r\n\r\n| | React | Omi |\r\n| ------------- |:-------------:|:-----:|\r\n| Component communication | ★★★★☆| ★★★★★ |\r\n| Stability | ★★★★★ | ★★★★☆ |\r\n| Flexibility | ★★★★☆| ★★★★★ |\r\n| Scalability | ★★★★☆ | ★★★★★ |\r\n| Testability | ★★★★★ | ★★★★☆ |\r\n| File size | ★★★☆☆ | ★★★★★ |\r\n| Features | ★★★☆☆ | ★★★★☆ |\r\n| DOM performance | ★★★★★ | ★★★★☆ |\r\n| Animation performance | ★★★★☆ | ★★★★★ |\r\n| Abstract complexity | ★★★★☆ | ★★★★★ |\r\n| Asynchronous programming | ★★★★★ | ★★★★☆ |\r\n\r\nAs we can see, we can not have it both ways. Object-oriented programming is more reusable, flexible and scalable, the problem is more difficult to test.\r\n\r\nSpecifically, if the functional programming, the test area is state1 + state2 + ... + stateN; in object-oriented programming, the test area is state1 × event1 + state2 × event2 + ... + stateN × eventN.\r\n\r\nIn summary, it is more recommended to use the object-oriented programming to build UI component framework.\r\n\r\n
\r\n\r\n### The end. Thanks for reading. [Let's start the Omi journey](https://github.com/AlloyTeam/omi)!\r\n" - -/***/ }, -/* 38 */ -/***/ function(module, exports, __webpack_require__) { - - 'use strict'; - - Object.defineProperty(exports, "__esModule", { - value: true - }); - - var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); - - var _omi = __webpack_require__(2); - - var _omi2 = _interopRequireDefault(_omi); - - var _index = __webpack_require__(39); - - var _index2 = _interopRequireDefault(_index); - - var _config = __webpack_require__(4); - - var _config2 = _interopRequireDefault(_config); - - function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - - function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } - - function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; } - - function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } - - _omi2.default.makeHTML('List', _index2.default); - - var Sidebar = function (_Omi$Component) { - _inherits(Sidebar, _Omi$Component); - - function Sidebar(data) { - _classCallCheck(this, Sidebar); - - return _possibleConstructorReturn(this, (Sidebar.__proto__ || Object.getPrototypeOf(Sidebar)).call(this, data)); - } - - _createClass(Sidebar, [{ - key: 'install', - value: function install() { - this.data.items = _config2.default['menus'][this.data.lan]; - this.data.height = window.innerHeight - 45; - } - }, { - key: 'style', - value: function style() { - return __webpack_require__(42); - } - }, { - key: 'render', - value: function render() { - return __webpack_require__(43); - } - }]); - - return Sidebar; - }(_omi2.default.Component); - - exports.default = Sidebar; - -/***/ }, -/* 39 */ -/***/ function(module, exports, __webpack_require__) { - - 'use strict'; - - Object.defineProperty(exports, "__esModule", { - value: true - }); - - var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); - - var _omi = __webpack_require__(2); - - var _omi2 = _interopRequireDefault(_omi); - - function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - - function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } - - function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; } - - function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } - - var tpl = __webpack_require__(40); - var css = __webpack_require__(41); - - var List = function (_Omi$Component) { - _inherits(List, _Omi$Component); - - function List(data) { - _classCallCheck(this, List); - - var _this = _possibleConstructorReturn(this, (List.__proto__ || Object.getPrototypeOf(List)).call(this, data)); - - _omi2.default.mixIndexToArray(_this.data.list); - _this.data.currentIndex = 0; - var self = _this; - _this.data.isCurrent = function () { - return this.index === self.data.currentIndex && self.data.active; - }; - return _this; - } - - _createClass(List, [{ - key: 'goto', - value: function goto(name, index) { - var _this2 = this; - - _omi2.default.get('content').data.name = name; - _omi2.default.get('content').update(); - this.data.currentIndex = index; - this.parent.children.forEach(function (child, index) { - child.data.active = false; - if (child.id === _this2.id) { - _omi2.default.get('pager').activeIndex = index; - child.data.active = true; - } - child.update(); - }); - _omi2.default.get('pager').currentIndex = index; - _omi2.default.get('pager').update(); - document.body.scrollTop = 0; - } - }, { - key: 'render', - value: function render() { - return tpl; - } - }, { - key: 'style', - value: function style() { - return css; - } - }]); - - return List; - }(_omi2.default.Component); - - exports.default = List; - -/***/ }, -/* 40 */ -/***/ function(module, exports) { - - module.exports = "" - -/***/ }, -/* 41 */ -/***/ function(module, exports) { - - module.exports = "li.title{ font-size: 16px; font-weight: bold; margin-bottom:10px; margin-top:10px; text-indent: 23px;}li{ margin-bottom:3px; text-indent: 33px;}li a{ display:block; font-size:14px; height:20px; line-height:20px; color: #666;}li a.current{ background-color:#c3d4fc; color:white;}li a:hover{ background-color:#b3d4fc; color:white;}" - -/***/ }, -/* 42 */ -/***/ function(module, exports) { - - module.exports = "@media only screen and (max-width: 768px) { .list{ transform: translateX(-100%); background-color:white; -moz-transition: all .6s ease; -o-transition: all .6s ease; -webkit-transition: all .6s ease; transition: all .6s ease; } .list.show { -moz-transform: translateX(0%) translateZ(0); -ms-transform: translateX(0%) translateZ(0); -o-transform: translateX(0%) translateZ(0); -webkit-transform: translateX(0%) translateZ(0); transform: translateX(0%) translateZ(0); }}.list{ width:200px; text-indent: 20px; border-right: 1px solid #eee; overflow-x: hidden; overflow-y: auto; position:fixed; top:45px;}.version{ height:20px;}" - -/***/ }, -/* 43 */ -/***/ function(module, exports) { - - module.exports = "
{{#items}} {{/items}}
" - -/***/ }, -/* 44 */ -/***/ function(module, exports, __webpack_require__) { - - 'use strict'; - - Object.defineProperty(exports, "__esModule", { - value: true - }); - - var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); - - var _omi = __webpack_require__(2); - - var _omi2 = _interopRequireDefault(_omi); - - var _omiFinger = __webpack_require__(45); - - var _omiFinger2 = _interopRequireDefault(_omiFinger); - - function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - - function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } - - function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; } - - function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } - - var tpl = __webpack_require__(47); - var css = __webpack_require__(48); - - _omiFinger2.default.init(); - - var Head = function (_Omi$Component) { - _inherits(Head, _Omi$Component); - - function Head(data) { - _classCallCheck(this, Head); - - return _possibleConstructorReturn(this, (Head.__proto__ || Object.getPrototypeOf(Head)).call(this, data)); - } - - _createClass(Head, [{ - key: 'install', - value: function install() { - var _this2 = this; - - this.data.isEnLan = this.data.lan === 'en'; - document.body.addEventListener('touchend', function () { - setTimeout(function () { - _this2.removeClass(_omi2.default.get('sidebar').node, 'show'); - }, 300); - }, false); - } - }, { - key: 'toggleMenus', - value: function toggleMenus(evt) { - this.toggleClass(_omi2.default.get('sidebar').node, 'show'); - evt.stopPropagation(); - } - }, { - key: 'handleTouchEnd', - value: function handleTouchEnd(evt) { - evt.stopPropagation(); - } - }, { - key: 'toggleClass', - value: function toggleClass(element, className) { - if (!element || !className) { - return; - } - - var classString = element.className, - nameIndex = classString.indexOf(className); - if (nameIndex == -1) { - classString += ' ' + className; - } else { - classString = classString.substr(0, nameIndex) + classString.substr(nameIndex + className.length); - } - element.className = classString; - } - }, { - key: 'removeClass', - value: function removeClass(element, className) { - var classString = element.className, - nameIndex = classString.indexOf(className); - if (nameIndex !== -1) { - classString = classString.substr(0, nameIndex) + classString.substr(nameIndex + className.length); - } - element.className = classString; - } - }, { - key: 'style', - value: function style() { - return css; - } - }, { - key: 'render', - value: function render() { - return tpl; - } - }]); - - return Head; - }(_omi2.default.Component); - - exports.default = Head; - -/***/ }, -/* 45 */ -/***/ function(module, exports, __webpack_require__) { - - /*! - * omi-finger v0.1.3 by dntzhang - * Omi / AlloyFinger integration. Support touch and gesture events in your Omi project. - * Github: https://github.com/AlloyTeam/omi - * MIT Licensed. - */ - - ;(function () { - - var OmiFinger = {}; - var AlloyFinger = true - ? __webpack_require__(46) - : window.AlloyFinger; - var Omi = true - ? __webpack_require__(2) - : window.Omi; - - var noop = function(){ - - }; - - var getHandler = function(name, dom, instance) { - var value = dom.getAttribute(name); - if (value === null) { - return noop; - }else{ - return instance[value].bind(instance); - } - }; - - - OmiFinger.init = function(){ - Omi.extendPlugin('omi-finger',function(dom, instance){ - if(!instance.alloyFingerInstances)instance.alloyFingerInstances = []; - var len = instance.alloyFingerInstances.length; - var i = 0 ; - for(;i 1) r = 1; - return Math.acos(r); - } - - function cross(v1, v2) { - return v1.x * v2.y - v2.x * v1.y; - } - - function getRotateAngle(v1, v2) { - var angle = getAngle(v1, v2); - if (cross(v1, v2) > 0) { - angle *= -1; - } - - return angle * 180 / Math.PI; - } - - var HandlerAdmin = function(el) { - this.handlers = []; - this.el = el; - }; - - HandlerAdmin.prototype.add = function(handler) { - this.handlers.push(handler); - } - - HandlerAdmin.prototype.del = function(handler) { - if(!handler) this.handlers = []; - - for(var i=this.handlers.length; i>=0; i--) { - if(this.handlers[i] === handler) { - this.handlers.splice(i, 1); - } - } - } - - HandlerAdmin.prototype.dispatch = function() { - for(var i=0,len=this.handlers.length; i 0 && this.delta <= 250 && Math.abs(this.preTapPosition.x - this.x1) < 30 && Math.abs(this.preTapPosition.y - this.y1) < 30); - } - this.preTapPosition.x = this.x1; - this.preTapPosition.y = this.y1; - this.last = this.now; - var preV = this.preV, - len = evt.touches.length; - if (len > 1) { - this._cancelLongTap(); - this._cancelSingleTap(); - var v = { x: evt.touches[1].pageX - this.x1, y: evt.touches[1].pageY - this.y1 }; - preV.x = v.x; - preV.y = v.y; - this.pinchStartLen = getLen(preV); - this.multipointStart.dispatch(evt); - } - this.longTapTimeout = setTimeout(function () { - this.longTap.dispatch(evt); - }.bind(this), 750); - }, - move: function (evt) { - if (!evt.touches) return; - var preV = this.preV, - len = evt.touches.length, - currentX = evt.touches[0].pageX, - currentY = evt.touches[0].pageY; - this.isDoubleTap = false; - if (len > 1) { - var v = { x: evt.touches[1].pageX - currentX, y: evt.touches[1].pageY - currentY }; - - if (preV.x !== null) { - if (this.pinchStartLen > 0) { - evt.scale = getLen(v) / this.pinchStartLen; - this.pinch.dispatch(evt); - } - - evt.angle = getRotateAngle(v, preV); - this.rotate.dispatch(evt); - } - preV.x = v.x; - preV.y = v.y; - } else { - if (this.x2 !== null) { - evt.deltaX = currentX - this.x2; - evt.deltaY = currentY - this.y2; - - } else { - evt.deltaX = 0; - evt.deltaY = 0; - } - this.pressMove.dispatch(evt); - } - - this.touchMove.dispatch(evt); - - this._cancelLongTap(); - this.x2 = currentX; - this.y2 = currentY; - if (len > 1) { - evt.preventDefault(); - } - }, - end: function (evt) { - if (!evt.changedTouches) return; - this._cancelLongTap(); - var self = this; - if (evt.touches.length < 2) { - this.multipointEnd.dispatch(evt); - } - this.touchEnd.dispatch(evt); - //swipe - if ((this.x2 && Math.abs(this.x1 - this.x2) > 30) || - (this.y2 && Math.abs(this.y1 - this.y2) > 30)) { - evt.direction = this._swipeDirection(this.x1, this.x2, this.y1, this.y2); - this.swipeTimeout = setTimeout(function () { - self.swipe.dispatch(evt); - - }, 0) - } else { - this.tapTimeout = setTimeout(function () { - self.tap.dispatch(evt); - // trigger double tap immediately - if (self.isDoubleTap) { - self.doubleTap.dispatch(evt); - clearTimeout(self.singleTapTimeout); - self.isDoubleTap = false; - } - }, 0) - - if (!self.isDoubleTap) { - self.singleTapTimeout = setTimeout(function () { - self.singleTap.dispatch(evt); - }, 250); - } - } - - this.preV.x = 0; - this.preV.y = 0; - this.scale = 1; - this.pinchStartLen = null; - this.x1 = this.x2 = this.y1 = this.y2 = null; - }, - cancel: function (evt) { - clearTimeout(this.singleTapTimeout); - clearTimeout(this.tapTimeout); - clearTimeout(this.longTapTimeout); - clearTimeout(this.swipeTimeout); - this.touchCancel.dispatch(evt); - }, - _cancelLongTap: function () { - clearTimeout(this.longTapTimeout); - }, - _cancelSingleTap: function () { - clearTimeout(this.singleTapTimeout); - }, - _swipeDirection: function (x1, x2, y1, y2) { - return Math.abs(x1 - x2) >= Math.abs(y1 - y2) ? (x1 - x2 > 0 ? 'Left' : 'Right') : (y1 - y2 > 0 ? 'Up' : 'Down') - }, - - on: function(evt, handler) { - if(this[evt]) { - this[evt].add(handler); - } - }, - - off: function(evt, handler) { - if(this[evt]) { - this[evt].del(handler); - } - }, - - destroy: function() { - if(this.singleTapTimeout) clearTimeout(this.singleTapTimeout); - if(this.tapTimeout) clearTimeout(this.tapTimeout); - if(this.longTapTimeout) clearTimeout(this.longTapTimeout); - if(this.swipeTimeout) clearTimeout(this.swipeTimeout); - - this.element.removeEventListener("touchstart", this.start); - this.element.removeEventListener("touchmove", this.move); - this.element.removeEventListener("touchend", this.end); - this.element.removeEventListener("touchcancel", this.cancel); - - this.rotate.del(); - this.touchStart.del(); - this.multipointStart.del(); - this.multipointEnd.del(); - this.pinch.del(); - this.swipe.del(); - this.tap.del(); - this.doubleTap.del(); - this.longTap.del(); - this.singleTap.del(); - this.pressMove.del(); - this.touchMove.del(); - this.touchEnd.del(); - this.touchCancel.del(); - - this.preV = this.pinchStartLen = this.scale = this.isDoubleTap = this.delta = this.last = this.now = this.tapTimeout = this.singleTapTimeout = this.longTapTimeout = this.swipeTimeout = this.x1 = this.x2 = this.y1 = this.y2 = this.preTapPosition = this.rotate = this.touchStart = this.multipointStart = this.multipointEnd = this.pinch = this.swipe = this.tap = this.doubleTap = this.longTap = this.singleTap = this.pressMove = this.touchMove = this.touchEnd = this.touchCancel = null; - - return null; - } - }; - - if (true) { - module.exports = AlloyFinger; - } else { - window.AlloyFinger = AlloyFinger; - } - })(); - - -/***/ }, -/* 47 */ -/***/ function(module, exports) { - - module.exports = "
\"\"
Omi
" - -/***/ }, -/* 48 */ -/***/ function(module, exports) { - - module.exports = ".head{ position:fixed; height:45px; line-height: 45px; border-bottom: 1px solid #eee; width:100%; background-color:#303030; z-index:100;}ul,li{ display: inline-block;}.logo_box{ width:100px; display: inline-block; text-align:center; line-height: 60px;}.menu a,.logo_box a{ display: inline-block; height:45px; color:#ddd;}.menu{ position: absolute; right:20px;}.menu li{ margin-left:15px;}.logo_box a{ font-size: 34px; font-weight: bold; color: #00bff3; padding: 0px 15px; line-height: 45px; cursor: pointer;}.menu a:hover{ color: white;}.m_menu{ position:fixed; display:none;}@media only screen and (max-width: 768px) { .menu li{ display:none; } .menu .m_show{ display:block; } .logo_box{ display:inline-block; } .head{ text-align:center; } .m_menu{ top:0; left:0; display:block; width:50px; height:50px; padding-top: 6px; } .m_menu img{ width:30px; }}" - -/***/ }, -/* 49 */ -/***/ function(module, exports, __webpack_require__) { - - 'use strict'; - - Object.defineProperty(exports, "__esModule", { - value: true - }); - - var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); - - var _omi = __webpack_require__(2); - - var _omi2 = _interopRequireDefault(_omi); - - var _config = __webpack_require__(4); - - var _config2 = _interopRequireDefault(_config); - - var _omiFinger = __webpack_require__(45); - - var _omiFinger2 = _interopRequireDefault(_omiFinger); - - function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - - function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } - - function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; } - - function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } - - _omiFinger2.default.init(); - - var Pager = function (_Omi$Component) { - _inherits(Pager, _Omi$Component); - - function Pager(data) { - _classCallCheck(this, Pager); - - var _this = _possibleConstructorReturn(this, (Pager.__proto__ || Object.getPrototypeOf(Pager)).call(this, data)); - - _this.activeIndex = 0; - _this.currentIndex = 0; - return _this; - } - - _createClass(Pager, [{ - key: 'updatePager', - value: function updatePager() { - this.data.preMd = null; - this.data.preName = null; - this.data.nextMd = null; - this.data.nextName = null; - var item = _config2.default.menus[this.data.lan][this.activeIndex]; - - var pre = item.list[this.currentIndex - 1]; - if (pre) { - this.data.preMd = pre.md; - this.data.preName = pre.name; - } - var next = item.list[this.currentIndex + 1]; - if (next) { - this.data.nextMd = next.md; - this.data.nextName = next.name; - } - } - }, { - key: 'goto', - value: function goto(name, dir) { - var sidebar = _omi2.default.get('sidebar'); - if (dir === 'next') { - sidebar.children[this.activeIndex].goto(name, ++this.currentIndex); - } else { - sidebar.children[this.activeIndex].goto(name, --this.currentIndex); - } - this.update(); - } - }, { - key: 'handleTap', - value: function handleTap(evt) { - var dir = evt.target.getAttribute('data-dir'); - var name = evt.target.getAttribute('data-name'); - this.goto(name, dir); - } - }, { - key: 'isMobile', - value: function isMobile() { - var browser = { - versions: function () { - var u = navigator.userAgent, - app = navigator.appVersion; - return { //移动终端浏览器版本信息 - trident: u.indexOf('Trident') > -1, //IE内核 - presto: u.indexOf('Presto') > -1, //opera内核 - webKit: u.indexOf('AppleWebKit') > -1, //苹果、谷歌内核 - gecko: u.indexOf('Gecko') > -1 && u.indexOf('KHTML') == -1, //火狐内核 - mobile: !!u.match(/AppleWebKit.*Mobile.*/), //是否为移动终端 - ios: !!u.match(/\(i[^;]+;( U;)? CPU.+Mac OS X/), //ios终端 - android: u.indexOf('Android') > -1 || u.indexOf('Linux') > -1, //android终端或者uc浏览器 - iPhone: u.indexOf('iPhone') > -1, //是否为iPhone或者QQHD浏览器 - iPad: u.indexOf('iPad') > -1, //是否iPad - webApp: u.indexOf('Safari') == -1 //是否web应该程序,没有头部与底部 - }; - }(), - language: (navigator.browserLanguage || navigator.language).toLowerCase() - }; - - if (browser.versions.mobile || browser.versions.ios || browser.versions.android || browser.versions.iPhone || browser.versions.iPad) { - return true; - } - return false; - } - }, { - key: 'render', - value: function render() { - this.updatePager(); - if (this.isMobile()) { - return '\n
\n {{#preName}} \u2190{{preName}}{{/preName}}\n {{#nextName}} {{/nextName}}\n
'; - } else { - return '\n
\n {{#preName}} \u2190{{preName}}{{/preName}}\n {{#nextName}} {{/nextName}}\n
'; - } - } - }, { - key: 'style', - value: function style() { - return __webpack_require__(50); - } - }]); - - return Pager; - }(_omi2.default.Component); - - exports.default = Pager; - -/***/ }, -/* 50 */ -/***/ function(module, exports) { - - module.exports = ".pager { width:85%; height:80px; line-height:80px; position: relative; font-size:16px;}@media only screen and (max-width: 768px) { .pager { width:100%; }}.pre{ position: absolute; left:10px; top:10px;}.next{ position: absolute; right:10px; top:10px;}" - -/***/ } -]); \ No newline at end of file diff --git a/website/js/omi.b9df77fe.js b/website/js/omi.b9df77fe.js deleted file mode 100644 index 07cca0223..000000000 --- a/website/js/omi.b9df77fe.js +++ /dev/null @@ -1,2638 +0,0 @@ -webpackJsonp([2],[ -/* 0 */ -/***/ function(module, exports, __webpack_require__) { - - module.exports = __webpack_require__(2); - - -/***/ }, -/* 1 */, -/* 2 */ -/***/ function(module, exports, __webpack_require__) { - - /*! - * Omi v0.4.3 By dntzhang - * Github: https://github.com/AlloyTeam/omi - * MIT Licensed. - */ - (function webpackUniversalModuleDefinition(root, factory) { - if(true) - module.exports = factory(); - else if(typeof define === 'function' && define.amd) - define([], factory); - else if(typeof exports === 'object') - exports["Omi"] = factory(); - else - root["Omi"] = factory(); - })(this, function() { - return /******/ (function(modules) { // webpackBootstrap - /******/ // The module cache - /******/ var installedModules = {}; - - /******/ // The require function - /******/ function __webpack_require__(moduleId) { - - /******/ // Check if module is in cache - /******/ if(installedModules[moduleId]) - /******/ return installedModules[moduleId].exports; - - /******/ // Create a new module (and put it into the cache) - /******/ var module = installedModules[moduleId] = { - /******/ exports: {}, - /******/ id: moduleId, - /******/ loaded: false - /******/ }; - - /******/ // Execute the module function - /******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__); - - /******/ // Flag the module as loaded - /******/ module.loaded = true; - - /******/ // Return the exports of the module - /******/ return module.exports; - /******/ } - - - /******/ // expose the modules object (__webpack_modules__) - /******/ __webpack_require__.m = modules; - - /******/ // expose the module cache - /******/ __webpack_require__.c = installedModules; - - /******/ // __webpack_public_path__ - /******/ __webpack_require__.p = ""; - - /******/ // Load entry module and return exports - /******/ return __webpack_require__(0); - /******/ }) - /************************************************************************/ - /******/ ([ - /* 0 */ - /***/ function(module, exports, __webpack_require__) { - - 'use strict'; - - var _omi = __webpack_require__(1); - - var _omi2 = _interopRequireDefault(_omi); - - var _mustache = __webpack_require__(2); - - var _mustache2 = _interopRequireDefault(_mustache); - - var _component = __webpack_require__(3); - - var _component2 = _interopRequireDefault(_component); - - function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; } - - _omi2['default'].template = _mustache2['default'].render; - - _omi2['default'].Component = _component2['default']; - if (window.Omi) { - module.exports = window.Omi; - } else { - window.Omi = _omi2['default']; - module.exports = _omi2['default']; - } - - /***/ }, - /* 1 */ - /***/ function(module, exports) { - - "use strict"; - - var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; - - var Omi = {}; - Omi.instances = {}; - Omi._instanceId = 0; - Omi.getInstanceId = function () { - return Omi._instanceId++; - }; - Omi.customTags = []; - Omi.mapping = {}; - - Omi.STYLEPREFIX = "omi_style_"; - Omi.STYLESCOPEDPREFIX = "omi_scoped_"; - - //fix ie bug - if (typeof Object.assign != 'function') { - Object.assign = function (target) { - 'use strict'; - - if (target == null) { - throw new TypeError('Cannot convert undefined or null to object'); - } - - target = Object(target); - for (var index = 1; index < arguments.length; index++) { - var source = arguments[index]; - if (source != null) { - for (var key in source) { - if (Object.prototype.hasOwnProperty.call(source, key)) { - target[key] = source[key]; - } - } - } - } - return target; - }; - } - - /** - * Shim for "fixing" IE's lack of support (IE < 9) for applying slice - * on host objects like NamedNodeMap, NodeList, and HTMLCollection - * (technically, since host objects have been implementation-dependent, - * at least before ES6, IE hasn't needed to work this way). - * Also works on strings, fixes IE < 9 to allow an explicit undefined - * for the 2nd argument (as in Firefox), and prevents errors when - * called on other DOM objects. - */ - (function () { - 'use strict'; - - var _slice = Array.prototype.slice; - - try { - // Can't be used with DOM elements in IE < 9 - _slice.call(document.documentElement); - } catch (e) { - // Fails in IE < 9 - // This will work for genuine arrays, array-like objects, - // NamedNodeMap (attributes, entities, notations), - // NodeList (e.g., getElementsByTagName), HTMLCollection (e.g., childNodes), - // and will not fail on other DOM objects (as do DOM elements in IE < 9) - Array.prototype.slice = function (begin, end) { - // IE < 9 gets unhappy with an undefined end argument - end = typeof end !== 'undefined' ? end : this.length; - - // For native Array objects, we use the native slice function - if (Object.prototype.toString.call(this) === '[object Array]') { - return _slice.call(this, begin, end); - } - - // For array like object we handle it ourselves. - var i, - cloned = [], - size, - len = this.length; - - // Handle negative value for "begin" - var start = begin || 0; - start = start >= 0 ? start : len + start; - - // Handle negative value for "end" - var upTo = end ? end : len; - if (end < 0) { - upTo = len + end; - } - - // Actual expected size of the slice - size = upTo - start; - - if (size > 0) { - cloned = new Array(size); - if (this.charAt) { - for (i = 0; i < size; i++) { - cloned[i] = this.charAt(start + i); - } - } else { - for (i = 0; i < size; i++) { - cloned[i] = this[start + i]; - } - } - } - - return cloned; - }; - } - })(); - - var _createClass = function () { - function defineProperties(target, props) { - for (var i = 0; i < props.length; i++) { - var descriptor = props[i];descriptor.enumerable = descriptor.enumerable || false;descriptor.configurable = true;if ("value" in descriptor) descriptor.writable = true;Object.defineProperty(target, descriptor.key, descriptor); - } - }return function (Constructor, protoProps, staticProps) { - if (protoProps) defineProperties(Constructor.prototype, protoProps);if (staticProps) defineProperties(Constructor, staticProps);return Constructor; - }; - }(); - - function _classCallCheck(instance, Constructor) { - if (!(instance instanceof Constructor)) { - throw new TypeError("Cannot call a class as a function"); - } - } - - function _possibleConstructorReturn(self, call) { - if (!self) { - throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); - }return call && ((typeof call === "undefined" ? "undefined" : _typeof(call)) === "object" || typeof call === "function") ? call : self; - } - - function _inherits(subClass, superClass) { - if (typeof superClass !== "function" && superClass !== null) { - throw new TypeError("Super expression must either be null or a function, not " + (typeof superClass === "undefined" ? "undefined" : _typeof(superClass))); - }subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } });if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; - } - - function toArr(obj) { - var arr = []; - for (var key in obj) { - if (obj.hasOwnProperty(key)) { - arr.push({ key: key, value: obj[key] }); - } - } - return arr; - } - - Omi.create = function (tagName, parent, setting) { - var u_setting = parent, - u_parent = Omi.Component; - if (arguments.length > 2) { - u_setting = setting; - u_parent = parent; - } - Omi[tagName] = function (parent) { - _inherits(Obj, parent); - - function Obj(data, server) { - _classCallCheck(this, Obj); - this.___omi_constructor_name = tagName; - return _possibleConstructorReturn(this, (Obj.__proto__ || Object.getPrototypeOf(Obj)).call(this, data, server)); - } - - _createClass(Obj, toArr(u_setting)); - - return Obj; - }(u_parent); - - Omi.customTags.push(tagName); - - return Omi[tagName]; - }; - - Omi.mixIndex = function (array, key) { - var len = array.length, - indexName = key || "index"; - for (var i = 0; i < len; i++) { - var item = array[i]; - if ((typeof item === "undefined" ? "undefined" : _typeof(item)) === "object") { - item[indexName] = i; - } else { - array[i] = { value: item }; - array[i][indexName] = i; - } - } - return array; - }; - - Omi.$ = function (selector, context) { - if (context) { - return context.querySelector(selector); - } else { - return document.querySelector(selector); - } - }; - - Omi.$$ = function (selector, context) { - if (context) { - return Array.prototype.slice.call(context.querySelectorAll(selector)); - } else { - return Array.prototype.slice.call(document.querySelectorAll(selector)); - } - }; - - Omi.getClassFromString = function (str) { - if (str.indexOf('.') !== 0) { - var arr = str.split('.'); - var len = arr.length; - var current = Omi[arr[0]]; - for (var i = 1; i < len; i++) { - current = current[arr[i]]; - } - return current; - } else { - return Omi[str]; - } - }; - - //��ǰ��Component�ľ�̬�������Ƶ�omi��������Ȼmakehtml ��ie��child���ʲ������׵ľ�̬���� - Omi.makeHTML = function (name, ctor) { - Omi[name] = ctor; - Omi.customTags.push(name); - }; - - Omi.render = function (component, renderTo, increment) { - component.renderTo = typeof renderTo === "string" ? document.querySelector(renderTo) : renderTo; - component._omi_increment = increment; - component.install(); - component._render(true); - component._childrenInstalled(component); - component.installed(); - return component; - }; - - Omi.get = function (name) { - return Omi.mapping[name]; - }; - - Omi.plugins = {}; - - Omi.extendPlugin = function (name, handler) { - Omi.plugins[name] = handler; - }; - - Omi.getParameters = function (dom, instance, types) { - var data = {}; - var noop = function noop() {}; - var methodMapping = { - stringType: function stringType(value) { - return value; - }, - numberType: function numberType(value) { - return Number(value); - }, - booleanType: function booleanType(value) { - if (value === 'true') { - return true; - } else if (value === 'false') { - return false; - } else { - return Boolean(value); - } - }, - functionType: function functionType(value) { - if (value) { - var handler = instance[value.replace(/Omi.instances\[\d\]./, '')]; - if (handler) { - return handler.bind(instance); - } else { - console.warn('You do not define [ ' + value + ' ] method in following component'); - console.warn(instance); - } - } else { - return noop; - } - } - }; - Object.keys(types).forEach(function (type) { - types[type].forEach(function (name) { - var attr = dom.getAttribute(name); - if (attr !== null) { - data[name] = methodMapping[type](attr); - } - }); - }); - - return data; - }; - - Omi.mixIndexToArray = function (arr, indexName) { - arr.forEach(function (item, index) { - item[indexName || 'index'] = index; - }); - }; - - module.exports = Omi; - - /***/ }, - /* 2 */ - /***/ function(module, exports, __webpack_require__) { - - var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;'use strict'; - - var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; - - /*! - * mustache.js - Logic-less {{mustache}} templates with JavaScript - * http://github.com/janl/mustache.js - */ - - /*global define: false Mustache: true*/ - - (function defineMustache(global, factory) { - if (( false ? 'undefined' : _typeof(exports)) === 'object' && exports && typeof exports.nodeName !== 'string') { - factory(exports); // CommonJS - } else if (true) { - !(__WEBPACK_AMD_DEFINE_ARRAY__ = [exports], __WEBPACK_AMD_DEFINE_FACTORY__ = (factory), __WEBPACK_AMD_DEFINE_RESULT__ = (typeof __WEBPACK_AMD_DEFINE_FACTORY__ === 'function' ? (__WEBPACK_AMD_DEFINE_FACTORY__.apply(exports, __WEBPACK_AMD_DEFINE_ARRAY__)) : __WEBPACK_AMD_DEFINE_FACTORY__), __WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__)); // AMD - } else { - global.Mustache = {}; - factory(global.Mustache); // script, wsh, asp - } - })(undefined, function mustacheFactory(mustache) { - - var objectToString = Object.prototype.toString; - var isArray = Array.isArray || function isArrayPolyfill(object) { - return objectToString.call(object) === '[object Array]'; - }; - - function isFunction(object) { - return typeof object === 'function'; - } - - /** - * More correct typeof string handling array - * which normally returns typeof 'object' - */ - function typeStr(obj) { - return isArray(obj) ? 'array' : typeof obj === 'undefined' ? 'undefined' : _typeof(obj); - } - - function escapeRegExp(string) { - return string.replace(/[\-\[\]{}()*+?.,\\\^$|#\s]/g, '\\$&'); - } - - /** - * Null safe way of checking whether or not an object, - * including its prototype, has a given property - */ - function hasProperty(obj, propName) { - return obj != null && (typeof obj === 'undefined' ? 'undefined' : _typeof(obj)) === 'object' && propName in obj; - } - - // Workaround for https://issues.apache.org/jira/browse/COUCHDB-577 - // See https://github.com/janl/mustache.js/issues/189 - var regExpTest = RegExp.prototype.test; - function testRegExp(re, string) { - return regExpTest.call(re, string); - } - - var nonSpaceRe = /\S/; - function isWhitespace(string) { - return !testRegExp(nonSpaceRe, string); - } - - var entityMap = { - '&': '&', - '<': '<', - '>': '>', - '"': '"', - "'": ''', - '/': '/', - '`': '`', - '=': '=' - }; - - function escapeHtml(string) { - return String(string).replace(/[&<>"'`=\/]/g, function fromEntityMap(s) { - return entityMap[s]; - }); - } - - var whiteRe = /\s*/; - var spaceRe = /\s+/; - var equalsRe = /\s*=/; - var curlyRe = /\s*\}/; - var tagRe = /#|\^|\/|>|\{|&|=|!/; - - /** - * Breaks up the given `template` string into a tree of tokens. If the `tags` - * argument is given here it must be an array with two string values: the - * opening and closing tags used in the template (e.g. [ "<%", "%>" ]). Of - * course, the default is to use mustaches (i.e. mustache.tags). - * - * A token is an array with at least 4 elements. The first element is the - * mustache symbol that was used inside the tag, e.g. "#" or "&". If the tag - * did not contain a symbol (i.e. {{myValue}}) this element is "name". For - * all text that appears outside a symbol this element is "text". - * - * The second element of a token is its "value". For mustache tags this is - * whatever else was inside the tag besides the opening symbol. For text tokens - * this is the text itself. - * - * The third and fourth elements of the token are the start and end indices, - * respectively, of the token in the original template. - * - * Tokens that are the root node of a subtree contain two more elements: 1) an - * array of tokens in the subtree and 2) the index in the original template at - * which the closing tag for that section begins. - */ - function parseTemplate(template, tags) { - if (!template) return []; - - var sections = []; // Stack to hold section tokens - var tokens = []; // Buffer to hold the tokens - var spaces = []; // Indices of whitespace tokens on the current line - var hasTag = false; // Is there a {{tag}} on the current line? - var nonSpace = false; // Is there a non-space char on the current line? - - // Strips all whitespace tokens array for the current line - // if there was a {{#tag}} on it and otherwise only space. - function stripSpace() { - if (hasTag && !nonSpace) { - while (spaces.length) { - delete tokens[spaces.pop()]; - } - } else { - spaces = []; - } - - hasTag = false; - nonSpace = false; - } - - var openingTagRe, closingTagRe, closingCurlyRe; - function compileTags(tagsToCompile) { - if (typeof tagsToCompile === 'string') tagsToCompile = tagsToCompile.split(spaceRe, 2); - - if (!isArray(tagsToCompile) || tagsToCompile.length !== 2) throw new Error('Invalid tags: ' + tagsToCompile); - - openingTagRe = new RegExp(escapeRegExp(tagsToCompile[0]) + '\\s*'); - closingTagRe = new RegExp('\\s*' + escapeRegExp(tagsToCompile[1])); - closingCurlyRe = new RegExp('\\s*' + escapeRegExp('}' + tagsToCompile[1])); - } - - compileTags(tags || mustache.tags); - - var scanner = new Scanner(template); - - var start, type, value, chr, token, openSection; - while (!scanner.eos()) { - start = scanner.pos; - - // Match any text between tags. - value = scanner.scanUntil(openingTagRe); - - if (value) { - for (var i = 0, valueLength = value.length; i < valueLength; ++i) { - chr = value.charAt(i); - - if (isWhitespace(chr)) { - spaces.push(tokens.length); - } else { - nonSpace = true; - } - - tokens.push(['text', chr, start, start + 1]); - start += 1; - - // Check for whitespace on the current line. - if (chr === '\n') stripSpace(); - } - } - - // Match the opening tag. - if (!scanner.scan(openingTagRe)) break; - - hasTag = true; - - // Get the tag type. - type = scanner.scan(tagRe) || 'name'; - scanner.scan(whiteRe); - - // Get the tag value. - if (type === '=') { - value = scanner.scanUntil(equalsRe); - scanner.scan(equalsRe); - scanner.scanUntil(closingTagRe); - } else if (type === '{') { - value = scanner.scanUntil(closingCurlyRe); - scanner.scan(curlyRe); - scanner.scanUntil(closingTagRe); - type = '&'; - } else { - value = scanner.scanUntil(closingTagRe); - } - - // Match the closing tag. - if (!scanner.scan(closingTagRe)) throw new Error('Unclosed tag at ' + scanner.pos); - - token = [type, value, start, scanner.pos]; - tokens.push(token); - - if (type === '#' || type === '^') { - sections.push(token); - } else if (type === '/') { - // Check section nesting. - openSection = sections.pop(); - - if (!openSection) throw new Error('Unopened section "' + value + '" at ' + start); - - if (openSection[1] !== value) throw new Error('Unclosed section "' + openSection[1] + '" at ' + start); - } else if (type === 'name' || type === '{' || type === '&') { - nonSpace = true; - } else if (type === '=') { - // Set the tags for the next time around. - compileTags(value); - } - } - - // Make sure there are no open sections when we're done. - openSection = sections.pop(); - - if (openSection) throw new Error('Unclosed section "' + openSection[1] + '" at ' + scanner.pos); - - return nestTokens(squashTokens(tokens)); - } - - /** - * Combines the values of consecutive text tokens in the given `tokens` array - * to a single token. - */ - function squashTokens(tokens) { - var squashedTokens = []; - - var token, lastToken; - for (var i = 0, numTokens = tokens.length; i < numTokens; ++i) { - token = tokens[i]; - - if (token) { - if (token[0] === 'text' && lastToken && lastToken[0] === 'text') { - lastToken[1] += token[1]; - lastToken[3] = token[3]; - } else { - squashedTokens.push(token); - lastToken = token; - } - } - } - - return squashedTokens; - } - - /** - * Forms the given array of `tokens` into a nested tree structure where - * tokens that represent a section have two additional items: 1) an array of - * all tokens that appear in that section and 2) the index in the original - * template that represents the end of that section. - */ - function nestTokens(tokens) { - var nestedTokens = []; - var collector = nestedTokens; - var sections = []; - - var token, section; - for (var i = 0, numTokens = tokens.length; i < numTokens; ++i) { - token = tokens[i]; - - switch (token[0]) { - case '#': - case '^': - collector.push(token); - sections.push(token); - collector = token[4] = []; - break; - case '/': - section = sections.pop(); - section[5] = token[2]; - collector = sections.length > 0 ? sections[sections.length - 1][4] : nestedTokens; - break; - default: - collector.push(token); - } - } - - return nestedTokens; - } - - /** - * A simple string scanner that is used by the template parser to find - * tokens in template strings. - */ - function Scanner(string) { - this.string = string; - this.tail = string; - this.pos = 0; - } - - /** - * Returns `true` if the tail is empty (end of string). - */ - Scanner.prototype.eos = function eos() { - return this.tail === ''; - }; - - /** - * Tries to match the given regular expression at the current position. - * Returns the matched text if it can match, the empty string otherwise. - */ - Scanner.prototype.scan = function scan(re) { - var match = this.tail.match(re); - - if (!match || match.index !== 0) return ''; - - var string = match[0]; - - this.tail = this.tail.substring(string.length); - this.pos += string.length; - - return string; - }; - - /** - * Skips all text until the given regular expression can be matched. Returns - * the skipped string, which is the entire tail if no match can be made. - */ - Scanner.prototype.scanUntil = function scanUntil(re) { - var index = this.tail.search(re), - match; - - switch (index) { - case -1: - match = this.tail; - this.tail = ''; - break; - case 0: - match = ''; - break; - default: - match = this.tail.substring(0, index); - this.tail = this.tail.substring(index); - } - - this.pos += match.length; - - return match; - }; - - /** - * Represents a rendering context by wrapping a view object and - * maintaining a reference to the parent context. - */ - function Context(view, parentContext) { - this.view = view; - this.cache = { '.': this.view }; - this.parent = parentContext; - } - - /** - * Creates a new context using the given view with this context - * as the parent. - */ - Context.prototype.push = function push(view) { - return new Context(view, this); - }; - - /** - * Returns the value of the given name in this context, traversing - * up the context hierarchy if the value is absent in this context's view. - */ - Context.prototype.lookup = function lookup(name) { - var cache = this.cache; - - var value; - if (cache.hasOwnProperty(name)) { - value = cache[name]; - } else { - var context = this, - names, - index, - lookupHit = false; - - while (context) { - if (name.indexOf('.') > 0) { - value = context.view; - names = name.split('.'); - index = 0; - - /** - * Using the dot notion path in `name`, we descend through the - * nested objects. - * - * To be certain that the lookup has been successful, we have to - * check if the last object in the path actually has the property - * we are looking for. We store the result in `lookupHit`. - * - * This is specially necessary for when the value has been set to - * `undefined` and we want to avoid looking up parent contexts. - **/ - while (value != null && index < names.length) { - if (index === names.length - 1) lookupHit = hasProperty(value, names[index]); - - value = value[names[index++]]; - } - } else { - value = context.view[name]; - lookupHit = hasProperty(context.view, name); - } - - if (lookupHit) break; - - context = context.parent; - } - - cache[name] = value; - } - - if (isFunction(value)) value = value.call(this.view); - - return value; - }; - - /** - * A Writer knows how to take a stream of tokens and render them to a - * string, given a context. It also maintains a cache of templates to - * avoid the need to parse the same template twice. - */ - function Writer() { - this.cache = {}; - } - - /** - * Clears all cached templates in this writer. - */ - Writer.prototype.clearCache = function clearCache() { - this.cache = {}; - }; - - /** - * Parses and caches the given `template` and returns the array of tokens - * that is generated from the parse. - */ - Writer.prototype.parse = function parse(template, tags) { - var cache = this.cache; - var tokens = cache[template]; - - if (tokens == null) tokens = cache[template] = parseTemplate(template, tags); - - return tokens; - }; - - /** - * High-level method that is used to render the given `template` with - * the given `view`. - * - * The optional `partials` argument may be an object that contains the - * names and templates of partials that are used in the template. It may - * also be a function that is used to load partial templates on the fly - * that takes a single argument: the name of the partial. - */ - Writer.prototype.render = function render(template, view, partials) { - var tokens = this.parse(template); - var context = view instanceof Context ? view : new Context(view); - return this.renderTokens(tokens, context, partials, template); - }; - - /** - * Low-level method that renders the given array of `tokens` using - * the given `context` and `partials`. - * - * Note: The `originalTemplate` is only ever used to extract the portion - * of the original template that was contained in a higher-order section. - * If the template doesn't use higher-order sections, this argument may - * be omitted. - */ - Writer.prototype.renderTokens = function renderTokens(tokens, context, partials, originalTemplate) { - var buffer = ''; - - var token, symbol, value; - for (var i = 0, numTokens = tokens.length; i < numTokens; ++i) { - value = undefined; - token = tokens[i]; - symbol = token[0]; - - if (symbol === '#') value = this.renderSection(token, context, partials, originalTemplate);else if (symbol === '^') value = this.renderInverted(token, context, partials, originalTemplate);else if (symbol === '>') value = this.renderPartial(token, context, partials, originalTemplate);else if (symbol === '&') value = this.unescapedValue(token, context);else if (symbol === 'name') value = this.escapedValue(token, context);else if (symbol === 'text') value = this.rawValue(token); - - if (value !== undefined) buffer += value; - } - - return buffer; - }; - - Writer.prototype.renderSection = function renderSection(token, context, partials, originalTemplate) { - var self = this; - var buffer = ''; - var value = context.lookup(token[1]); - - // This function is used to render an arbitrary template - // in the current context by higher-order sections. - function subRender(template) { - return self.render(template, context, partials); - } - - if (!value) return; - - if (isArray(value)) { - for (var j = 0, valueLength = value.length; j < valueLength; ++j) { - buffer += this.renderTokens(token[4], context.push(value[j]), partials, originalTemplate); - } - } else if ((typeof value === 'undefined' ? 'undefined' : _typeof(value)) === 'object' || typeof value === 'string' || typeof value === 'number') { - buffer += this.renderTokens(token[4], context.push(value), partials, originalTemplate); - } else if (isFunction(value)) { - if (typeof originalTemplate !== 'string') throw new Error('Cannot use higher-order sections without the original template'); - - // Extract the portion of the original template that the section contains. - value = value.call(context.view, originalTemplate.slice(token[3], token[5]), subRender); - - if (value != null) buffer += value; - } else { - buffer += this.renderTokens(token[4], context, partials, originalTemplate); - } - return buffer; - }; - - Writer.prototype.renderInverted = function renderInverted(token, context, partials, originalTemplate) { - var value = context.lookup(token[1]); - - // Use JavaScript's definition of falsy. Include empty arrays. - // See https://github.com/janl/mustache.js/issues/186 - if (!value || isArray(value) && value.length === 0) return this.renderTokens(token[4], context, partials, originalTemplate); - }; - - Writer.prototype.renderPartial = function renderPartial(token, context, partials) { - if (!partials) return; - - var value = isFunction(partials) ? partials(token[1]) : partials[token[1]]; - if (value != null) return this.renderTokens(this.parse(value), context, partials, value); - }; - - Writer.prototype.unescapedValue = function unescapedValue(token, context) { - var value = context.lookup(token[1]); - if (value != null) return value; - }; - - Writer.prototype.escapedValue = function escapedValue(token, context) { - var value = context.lookup(token[1]); - if (value != null) return mustache.escape(value); - }; - - Writer.prototype.rawValue = function rawValue(token) { - return token[1]; - }; - - mustache.name = 'mustache.js'; - mustache.version = '2.3.0'; - mustache.tags = ['{{', '}}']; - - // All high-level mustache.* functions use this writer. - var defaultWriter = new Writer(); - - /** - * Clears all cached templates in the default writer. - */ - mustache.clearCache = function clearCache() { - return defaultWriter.clearCache(); - }; - - /** - * Parses and caches the given template in the default writer and returns the - * array of tokens it contains. Doing this ahead of time avoids the need to - * parse templates on the fly as they are rendered. - */ - mustache.parse = function parse(template, tags) { - return defaultWriter.parse(template, tags); - }; - - /** - * Renders the `template` with the given `view` and `partials` using the - * default writer. - */ - mustache.render = function render(template, view, partials) { - if (typeof template !== 'string') { - throw new TypeError('Invalid template! Template should be a "string" ' + 'but "' + typeStr(template) + '" was given as the first ' + 'argument for mustache#render(template, view, partials)'); - } - - return defaultWriter.render(template, view, partials); - }; - - // This is here for backwards compatibility with 0.4.x., - /*eslint-disable */ // eslint wants camel cased function name - mustache.to_html = function to_html(template, view, partials, send) { - /*eslint-enable*/ - - var result = mustache.render(template, view, partials); - - if (isFunction(send)) { - send(result); - } else { - return result; - } - }; - - // Export the escaping function so that the user may override it. - // See https://github.com/janl/mustache.js/issues/244 - mustache.escape = escapeHtml; - - // Export these mainly for testing, but also for advanced usage. - mustache.Scanner = Scanner; - mustache.Context = Context; - mustache.Writer = Writer; - - return mustache; - }); - - /***/ }, - /* 3 */ - /***/ function(module, exports, __webpack_require__) { - - 'use strict'; - - Object.defineProperty(exports, "__esModule", { - value: true - }); - - var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); - - var _omi = __webpack_require__(1); - - var _omi2 = _interopRequireDefault(_omi); - - var _style = __webpack_require__(4); - - var _style2 = _interopRequireDefault(_style); - - var _event = __webpack_require__(5); - - var _event2 = _interopRequireDefault(_event); - - var _morphdom = __webpack_require__(6); - - var _morphdom2 = _interopRequireDefault(_morphdom); - - var _html2json = __webpack_require__(7); - - var _html2json2 = _interopRequireDefault(_html2json); - - function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; } - - function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } - - var Component = function () { - function Component(data, server) { - _classCallCheck(this, Component); - - //re render the server-side rendering html on the client-side - var type = Object.prototype.toString.call(data); - var isReRendering = type !== '[object Object]' && type !== '[object Undefined]'; - if (isReRendering) { - this.renderTo = typeof data === "string" ? document.querySelector(data) : data; - this._hidden = this.renderTo.querySelector('.omi_scoped__hidden_data'); - this.id = this._hidden.dataset.omiId; - this.data = JSON.parse(this._hidden.value); - } else { - this.data = data || {}; - this._omi_server_rendering = server; - this.id = this._omi_server_rendering ? 1000000 + _omi2['default'].getInstanceId() : _omi2['default'].getInstanceId(); - } - this.refs = {}; - this.children = []; - this.childrenData = []; - this.HTML = null; - this._addedItems = []; - this._omi_order = []; - _omi2['default'].instances[this.id] = this; - this.dataFirst = true; - this._omi_scoped_attr = _omi2['default'].STYLESCOPEDPREFIX + this.id; - //this.BODY_ELEMENT = document.createElement('body'); - this._preCSS = null; - this._omiGroupDataCounter = {}; - if (this._omi_server_rendering || isReRendering) { - this.install(); - this._render(true); - this._childrenInstalled(this); - this.installed(); - } - } - - _createClass(Component, [{ - key: 'install', - value: function install() {} - }, { - key: 'installed', - value: function installed() {} - }, { - key: 'uninstall', - value: function uninstall() {} - }, { - key: 'afterUpdate', - value: function afterUpdate() {} - }, { - key: 'beforeUpdate', - value: function beforeUpdate() {} - }, { - key: 'render', - value: function render() {} - }, { - key: 'style', - value: function style() {} - }, { - key: 'update', - value: function update() { - this.beforeUpdate(); - this._childrenBeforeUpdate(this); - if (this.renderTo) { - this._render(); - } else { - // update child node - if (this._omi_removed) { - var hdNode = this._createHiddenNode(); - this.node.parentNode.replaceChild(hdNode, this.node); - this.node = hdNode; - } else { - (0, _morphdom2['default'])(this.node, (0, _event2['default'])(this._childRender(this._omiChildStr), this.id)); - - this.node = document.querySelector("[" + this._omi_scoped_attr + "]"); - this._queryElements(this); - this._fixForm(); - } - } - //update added components - this._renderAddedChildren(); - this._childrenAfterUpdate(this); - this.afterUpdate(); - } - }, { - key: '_childrenBeforeUpdate', - value: function _childrenBeforeUpdate(root) { - var _this = this; - - root.children.forEach(function (child) { - child.beforeUpdate(); - _this._childrenBeforeUpdate(child); - }); - } - }, { - key: '_childrenAfterUpdate', - value: function _childrenAfterUpdate(root) { - var _this2 = this; - - root.children.forEach(function (child) { - _this2._childrenAfterUpdate(child); - child.afterUpdate(); - }); - } - }, { - key: 'setData', - value: function setData(data, update) { - this.data = data; - if (update) { - this.update(); - } - } - }, { - key: 'removeChild', - value: function removeChild(indexOrChild) { - var child = indexOrChild; - if (typeof indexOrChild === 'number') { - child = this.children[indexOrChild]; - } - - child.remove(); - } - }, { - key: 'restoreChild', - value: function restoreChild(indexOrChild) { - var child = indexOrChild; - if (typeof indexOrChild === 'number') { - child = this.children[indexOrChild]; - } - - child.restore(); - } - }, { - key: 'setComponentOrder', - value: function setComponentOrder(arr) { - var _this3 = this; - - arr.forEach(function (item, index) { - _this3._omi_order[index] = item; - }); - this.update(); - } - //beforeBegin,beforeEnd,afterBegin,afterEnd - - }, { - key: 'addComponent', - value: function addComponent(position, el, component) { - this._addedItems.push({ position: position, el: el, component: component }); - this.update(); - } - }, { - key: 'removeComponent', - value: function removeComponent(component) { - for (var i = 0, len = this._addedItems.length; i < len; i++) { - if (component.id === this._addedItems[i].component.id) { - this._addedItems.splice(i, 1); - break; - } - } - this.update(); - } - }, { - key: 'remove', - value: function remove() { - this._omi_removed = true; - this.update(); - this.uninstall(); - } - }, { - key: 'restore', - value: function restore() { - this._omi_removed = false; - this.update(); - this.installed(); - } - }, { - key: '_renderAddedChildren', - value: function _renderAddedChildren() { - var _this4 = this; - - this._addedItems.forEach(function (item) { - var target = typeof item.el === "string" ? _this4.node.querySelector(item.el) : item.el; - item.component.install(); - item.component._render(true); - item.component.installed(); - item.component._childrenInstalled(item.component); - target.insertAdjacentHTML(item.position, item.component.HTML); - }); - this.children.forEach(function (child) { - child._renderAddedChildren(); - }); - } - }, { - key: '_render', - value: function _render(isFirst) { - var _this5 = this; - - if (this._omi_removed) { - var node = this._createHiddenNode(); - if (!isFirst) { - this.node.parentNode.replaceChild(node, this.node); - this.node = node; - } else if (this.renderTo) { - this.renderTo.appendChild(node); - } - return; - } - this._generateHTMLCSS(); - this._extractChildren(this); - if (isFirst) { - this.children.forEach(function (item, index) { - _this5._omi_order[index] = index; - }); - } - this.children.forEach(function (item, index) { - _this5.HTML = _this5.HTML.replace(item._omiChildStr, _this5.children[_this5._omi_order[index]].HTML); - }); - this.HTML = (0, _event2['default'])(this.HTML, this.id); - if (isFirst) { - if (this.renderTo) { - if (this._omi_increment) { - this.renderTo.insertAdjacentHTML('beforeend', this.HTML); - } else { - this.renderTo.innerHTML = this.HTML; - } - } - } else { - if (this.HTML !== "") { - (0, _morphdom2['default'])(this.node, this.HTML); - } else { - (0, _morphdom2['default'])(this.node, this._createHiddenNode()); - } - } - //get node prop from parent node - if (this.renderTo) { - this.node = document.querySelector("[" + this._omi_scoped_attr + "]"); - this._queryElements(this); - this._fixForm(); - } - } - }, { - key: '_childRender', - value: function _childRender(childStr, isFirst) { - var _this6 = this; - - if (this._omi_removed) { - this.HTML = ''; - return this.HTML; - } - //childStr = childStr.replace("", ">"); - this._mergeData(childStr); - this._generateHTMLCSS(); - this._extractChildren(this); - if (isFirst) { - this.children.forEach(function (item, index) { - _this6._omi_order[index] = index; - }); - } - this.children.forEach(function (item, index) { - _this6.HTML = _this6.HTML.replace(item._omiChildStr, _this6.children[_this6._omi_order[index]].HTML); - }); - this.HTML = (0, _event2['default'])(this.HTML, this.id); - return this.HTML; - } - }, { - key: '_queryElements', - value: function _queryElements(current) { - current._mixRefs(); - current._execPlugins(); - current.children.forEach(function (item) { - item.node = current.node.querySelector("[" + _omi2['default'].STYLESCOPEDPREFIX + item.id + "]"); - //recursion get node prop from parent node - current._queryElements(item); - }); - } - }, { - key: '_mixRefs', - value: function _mixRefs() { - var _this7 = this; - - var nodes = _omi2['default'].$$('*[ref]', this.node); - nodes.forEach(function (node) { - if (node.hasAttribute(_this7._omi_scoped_attr)) { - _this7.refs[node.getAttribute('ref')] = node; - } - }); - var attr = this.node.getAttribute('ref'); - if (attr) { - this.refs[attr] = this.node; - } - } - }, { - key: '_execPlugins', - value: function _execPlugins() { - var _this8 = this; - - Object.keys(_omi2['default'].plugins).forEach(function (item) { - var nodes = _omi2['default'].$$('*[' + item + ']', _this8.node); - nodes.forEach(function (node) { - if (node.hasAttribute(_this8._omi_scoped_attr)) { - _omi2['default'].plugins[item](node, _this8); - } - }); - if (_this8.node.hasAttribute(item)) { - _omi2['default'].plugins[item](_this8.node, _this8); - } - }); - } - }, { - key: '_childrenInstalled', - value: function _childrenInstalled(root) { - var _this9 = this; - - root.children.forEach(function (child) { - _this9._childrenInstalled(child); - child.installed(); - }); - } - }, { - key: '_fixForm', - value: function _fixForm() { - - _omi2['default'].$$('input', this.node).forEach(function (element) { - var type = element.type.toLowerCase(); - if (element.getAttribute('value') === '') { - element.value = ''; - } - if (type === 'checked' || type === 'radio') { - if (element.hasAttribute('checked')) { - element.checked = 'checked'; - } else { - element.checked = false; - } - } - }); - - _omi2['default'].$$('textarea', this.node).forEach(function (textarea) { - textarea.value = textarea.getAttribute('value'); - }); - - _omi2['default'].$$('select', this.node).forEach(function (select) { - var value = select.getAttribute('value'); - if (value) { - _omi2['default'].$$('option', select).forEach(function (option) { - if (value === option.getAttribute('value')) { - option.setAttribute('selected', 'selected'); - } - }); - } else { - var firstOption = _omi2['default'].$$('option', select)[0]; - firstOption && firstOption.setAttribute('selected', 'selected'); - } - }); - } - }, { - key: '_replaceTags', - value: function _replaceTags(array, html) { - var str = array.join("|"); - var reg = new RegExp('<(' + str + '+)((?:\\s+[a-zA-Z_:][-a-zA-Z0-9_:.]*(?:\\s*=\\s*(?:(?:"[^"]*")|(?:\'[^\']*\')|[^>\\s]+))?)*)\\s*(\\/?)>', 'g'); - return html.replace(reg, function (m, a) { - var d = m.length - 2; - if (d >= 0 && m.lastIndexOf('/>') === m.length - 2) { - return m.replace('<' + a, ''; - } else if (m.lastIndexOf('>') === m.length - 1) { - return m.replace('<' + a, ''; - } - }); - } - }, { - key: '_createHiddenNode', - value: function _createHiddenNode() { - var hdNode = document.createElement("input"); - hdNode.setAttribute("type", "hidden"); - hdNode.setAttribute(this._omi_scoped_attr, ''); - return hdNode; - } - }, { - key: '_mergeData', - value: function _mergeData(childStr) { - if (this.dataFirst) { - this.data = Object.assign({}, this._getDataset(childStr), this.data); - } else { - this.data = Object.assign({}, this.data, this._getDataset(childStr)); - } - } - }, { - key: '_generateHTMLCSS', - value: function _generateHTMLCSS() { - this.CSS = (this.style() || '').replace(/<\/?style>/g, ''); - if (this.CSS) { - this.CSS = _style2['default'].scoper(this.CSS, "[" + this._omi_scoped_attr + "]"); - if (this.CSS !== this._preCSS && !this._omi_server_rendering) { - _style2['default'].addStyle(this.CSS, this.id); - this._preCSS = this.CSS; - } - } - var tpl = this.render(); - this.HTML = this._scopedAttr(_omi2['default'].template(tpl ? tpl : "", this.data), this._omi_scoped_attr).trim(); - if (this._omi_server_rendering) { - this.HTML = '\r\n\r\n' + this.HTML; - this.HTML += '\r\n\r\n'; - } - } - }, { - key: '_scopedAttr', - value: function _scopedAttr(html, id) { - return html.replace(/<[^/]([A-Za-z]*)[^>]*>/g, function (m) { - var str = m.split(" ")[0].replace(">", ""); - return m.replace(str, str + " " + id); - }); - } - }, { - key: '_getDataset', - value: function _getDataset(childStr) { - var _this10 = this; - - var json = (0, _html2json2['default'])(childStr); - var attr = json.child[0].attr; - Object.keys(attr).forEach(function (key) { - if (key.indexOf('data-') === 0) { - _this10._dataset[_this10._capitalize(key.replace('data-', ''))] = attr[key]; - } - }); - return this._dataset; - } - }, { - key: '_capitalize', - value: function _capitalize(str) { - str = str.toLowerCase(); - str = str.replace(/\b\w+\b/g, function (word) { - return word.substring(0, 1).toUpperCase() + word.substring(1); - }).replace(/-/g, ''); - return str.substring(0, 1).toLowerCase() + str.substring(1); - } - }, { - key: '_extractPropertyFromString', - value: function _extractPropertyFromString(str, instance) { - var arr = str.replace(/['|"|\]]/g, '').replace(/\[/g, '.').split('.'); - var current = instance; - arr.forEach(function (prop) { - current = current[prop]; - }); - arr = null; - return current; - } - }, { - key: '_extractChildren', - value: function _extractChildren(child) { - var _this11 = this; - - if (_omi2['default'].customTags.length > 0) { - child.HTML = this._replaceTags(_omi2['default'].customTags, child.HTML); - } - var arr = child.HTML.match(/][\s\S]*?tag=['|"](\S*)['|"][\s\S]*?><\/child>/g); - - if (arr) { - arr.forEach(function (childStr, i) { - var json = (0, _html2json2['default'])(childStr); - var attr = json.child[0].attr; - var name = attr.tag; - delete attr.tag; - var cmi = _this11.children[i]; - //if not first time to invoke _extractChildren method - if (cmi && cmi.___omi_constructor_name === name) { - cmi._childRender(childStr); - } else { - (function () { - var baseData = {}; - var dataset = {}; - var dataFromParent = {}; - var groupData = {}; - var omiID = null; - var instanceName = null; - Object.keys(attr).forEach(function (key) { - var value = attr[key]; - if (key.indexOf('on') === 0) { - var handler = child[value]; - if (handler) { - baseData[key] = handler.bind(child); - } - } else if (key === 'omi-id') { - omiID = value; - } else if (key === 'name') { - instanceName = value; - } else if (key === 'group-data') { - if (child._omiGroupDataCounter.hasOwnProperty(value)) { - child._omiGroupDataCounter[value]++; - } else { - child._omiGroupDataCounter[value] = 0; - } - groupData = _this11._extractPropertyFromString(value, child)[child._omiGroupDataCounter[value]]; - } else if (key.indexOf('data-') === 0) { - dataset[_this11._capitalize(key.replace('data-', ''))] = value; - } else if (key === 'data') { - dataFromParent = _this11._extractPropertyFromString(value, child); - } - }); - - var ChildClass = _omi2['default'].getClassFromString(name); - if (!ChildClass) throw "Can't find Class called [" + name + "]"; - var sub_child = new ChildClass(Object.assign(baseData, child.childrenData[i], dataset, dataFromParent, groupData), false); - sub_child._omiChildStr = childStr; - sub_child.parent = child; - sub_child.___omi_constructor_name = name; - sub_child._dataset = {}; - sub_child.install(); - - omiID && (_omi2['default'].mapping[omiID] = sub_child); - instanceName && (child[instanceName] = sub_child); - - if (!cmi) { - child.children.push(sub_child); - } else { - child.children[i] = sub_child; - } - - sub_child._childRender(childStr, true); - })(); - } - }); - } - } - }]); - - return Component; - }(); - - exports['default'] = Component; - - /***/ }, - /* 4 */ - /***/ function(module, exports, __webpack_require__) { - - "use strict"; - - Object.defineProperty(exports, "__esModule", { - value: true - }); - - var _omi = __webpack_require__(1); - - var _omi2 = _interopRequireDefault(_omi); - - function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { "default": obj }; } - - //many thanks to https://github.com/thomaspark/scoper/ - function scoper(css, prefix) { - var re = new RegExp("([^\r\n,{}]+)(,(?=[^}]*{)|\s*{)", "g"); - css = css.replace(re, function (g0, g1, g2) { - - if (g1.match(/^\s*(@media|@keyframes|to|from|@font-face)/)) { - return g1 + g2; - } - - if (g1.match(/:scope/)) { - g1 = g1.replace(/([^\s]*):scope/, function (h0, h1) { - if (h1 === "") { - return "> *"; - } else { - return "> " + h1; - } - }); - } - - g1 = g1.replace(/^(\s*)/, g1.trim() + prefix + "," + "$1" + prefix + " ").replace(/\s+/g, ' '); - return g1 + g2; - }); - - return css; - } - - function addStyle(cssText, id) { - var ele = document.getElementById(_omi2["default"].STYLEPREFIX + id), - head = document.getElementsByTagName('head')[0]; - if (ele && ele.parentNode === head) { - head.removeChild(ele); - } - - var someThingStyles = document.createElement('style'); - head.appendChild(someThingStyles); - someThingStyles.setAttribute('type', 'text/css'); - someThingStyles.setAttribute('id', _omi2["default"].STYLEPREFIX + id); - if (!!window.ActiveXObject) { - someThingStyles.styleSheet.cssText = cssText; - } else { - someThingStyles.textContent = cssText; - } - } - - exports["default"] = { - scoper: scoper, - addStyle: addStyle - }; - - /***/ }, - /* 5 */ - /***/ function(module, exports) { - - 'use strict'; - - Object.defineProperty(exports, "__esModule", { - value: true - }); - function exchange(str, a, b) { - return str.split(a).map(function (item) { - return item.replace(new RegExp(b, 'g'), a); - }).join(b); - } - - function safeDoubleQuote(str) { - return JSON.stringify(str).replace(/(^"|"$)/g, ''); - } - - function safeSingleQuote(str) { - str = exchange(str, "'", '"'); - return exchange(safeDoubleQuote(str), "'", '"'); - } - - function escapeHtml(unsafe) { - return unsafe.replace(/&/g, "&").replace(//g, ">").replace(/"/g, """).replace(/'/g, "'"); - } - - function endsWith(str, end) { - if (String.prototype.endsWith) { - return String.prototype.endsWith.call(str, end); - } else { - return str.substr(str.length - 1, 1) === end; - } - } - - function scopedEvent(tpl, id) { - return tpl.replace(/<[\s\S]*?[^=]>/g, function (item) { - return item.replace(/on(abort|blur|cancel|canplay|canplaythrough|change|click|close|contextmenu|cuechange|dblclick|drag|dragend|dragenter|dragleave|dragover|dragstart|drop|durationchange|emptied|ended|error|focus|input|invalid|keydown|keypress|keyup|load|loadeddata|loadedmetadata|loadstart|mousedown|mouseenter|mouseleave|mousemove|mouseout|mouseover|mouseup|mousewheel|pause|play|playing|progress|ratechange|reset|resize|scroll|seeked|seeking|select|show|stalled|submit|suspend|timeupdate|toggle|volumechange|waiting|autocomplete|autocompleteerror|beforecopy|beforecut|beforepaste|copy|cut|paste|search|selectstart|wheel|webkitfullscreenchange|webkitfullscreenerror|touchstart|touchmove|touchend|touchcancel|pointerdown|pointerup|pointercancel|pointermove|pointerover|pointerout|pointerenter|pointerleave|Abort|Blur|Cancel|CanPlay|CanPlayThrough|Change|Click|Close|ContextMenu|CueChange|DblClick|Drag|DragEnd|DragEnter|DragLeave|DragOver|DragStart|Drop|DurationChange|Emptied|Ended|Error|Focus|Input|Invalid|KeyDown|KeyPress|KeyUp|Load|LoadedData|LoadedMetadata|LoadStart|MouseDown|MouseEnter|MouseLeave|MouseMove|MouseOut|MouseOver|MouseUp|MouseWheel|Pause|Play|Playing|Progress|RateChange|Reset|Resize|Scroll|Seeked|Seeking|Select|Show|Stalled|Submit|Suspend|TimeUpdate|Toggle|VolumeChange|Waiting|AutoComplete|AutoCompleteError|BeforeCopy|BeforeCut|BeforePaste|Copy|Cut|Paste|Search|SelectStart|Wheel|WebkitFullScreenChange|WebkitFullScreenError|TouchStart|TouchMove|TouchEnd|TouchCancel|PointerDown|PointerUp|PointerCancel|PointerMove|PointerOver|PointerOut|PointerEnter|PointerLeave)=('|"|{)([\s\S]*)('|"|})/g, function (eventStr, eventName, open, str, close) { - if (str.indexOf('Omi.instances[') === 0 || str.indexOf('new Function(') === 0) { - return eventStr; - } - if (open === '{') { - // JSX-like event bind - var funcBody = '(' + str + ').bind(Omi.instances[' + id + '])(event)'; - var result = 'on' + eventName + '="new Function(\'event\', \'' + escapeHtml(safeSingleQuote(funcBody)) + '\')(event)"'; - return result.split('\n').map(function (line) { - return endsWith(line, ';') ? line : line + ';'; - }).join(''); - } else { - if (!str.match(/.*?\(.*?\)/)) { - // if is not JSX-like event and is not a function call (func(xxx, ttt)) - return eventStr; - } - } - return eventStr.replace(/=(['|"])/, '=$1Omi.instances[' + id + '].'); - }); - }); - }; - - exports['default'] = scopedEvent; - - /***/ }, - /* 6 */ - /***/ function(module, exports, __webpack_require__) { - - var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_RESULT__;'use strict'; - - var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; - - (function (global, factory) { - ( false ? 'undefined' : _typeof(exports)) === 'object' && typeof module !== 'undefined' ? module.exports = factory() : true ? !(__WEBPACK_AMD_DEFINE_FACTORY__ = (factory), __WEBPACK_AMD_DEFINE_RESULT__ = (typeof __WEBPACK_AMD_DEFINE_FACTORY__ === 'function' ? (__WEBPACK_AMD_DEFINE_FACTORY__.call(exports, __webpack_require__, exports, module)) : __WEBPACK_AMD_DEFINE_FACTORY__), __WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__)) : global.morphdom = factory(); - })(undefined, function () { - 'use strict'; - - var range; // Create a range object for efficently rendering strings to elements. - var NS_XHTML = 'http://www.w3.org/1999/xhtml'; - - var doc = typeof document === 'undefined' ? undefined : document; - - var testEl = doc ? doc.body || doc.createElement('div') : {}; - - // Fixes - // (IE7+ support) <=IE7 does not support el.hasAttribute(name) - var actualHasAttributeNS; - - if (testEl.hasAttributeNS) { - actualHasAttributeNS = function actualHasAttributeNS(el, namespaceURI, name) { - return el.hasAttributeNS(namespaceURI, name); - }; - } else if (testEl.hasAttribute) { - actualHasAttributeNS = function actualHasAttributeNS(el, namespaceURI, name) { - return el.hasAttribute(name); - }; - } else { - actualHasAttributeNS = function actualHasAttributeNS(el, namespaceURI, name) { - return el.getAttributeNode(namespaceURI, name) != null; - }; - } - - var hasAttributeNS = actualHasAttributeNS; - - function toElement(str) { - if (!range && doc.createRange) { - range = doc.createRange(); - range.selectNode(doc.body); - } - - var fragment; - if (range && range.createContextualFragment) { - fragment = range.createContextualFragment(str); - } else { - fragment = doc.createElement('body'); - fragment.innerHTML = str; - } - return fragment.childNodes[0]; - } - - /** - * Returns true if two node's names are the same. - * - * NOTE: We don't bother checking `namespaceURI` because you will never find two HTML elements with the same - * nodeName and different namespace URIs. - * - * @param {Element} a - * @param {Element} b The target element - * @return {boolean} - */ - function compareNodeNames(fromEl, toEl) { - var fromNodeName = fromEl.nodeName; - var toNodeName = toEl.nodeName; - - if (fromNodeName === toNodeName) { - return true; - } - - if (toEl.actualize && fromNodeName.charCodeAt(0) < 91 && /* from tag name is upper case */ - toNodeName.charCodeAt(0) > 90 /* target tag name is lower case */) { - // If the target element is a virtual DOM node then we may need to normalize the tag name - // before comparing. Normal HTML elements that are in the "http://www.w3.org/1999/xhtml" - // are converted to upper case - return fromNodeName === toNodeName.toUpperCase(); - } else { - return false; - } - } - - /** - * Create an element, optionally with a known namespace URI. - * - * @param {string} name the element name, e.g. 'div' or 'svg' - * @param {string} [namespaceURI] the element's namespace URI, i.e. the value of - * its `xmlns` attribute or its inferred namespace. - * - * @return {Element} - */ - function createElementNS(name, namespaceURI) { - return !namespaceURI || namespaceURI === NS_XHTML ? doc.createElement(name) : doc.createElementNS(namespaceURI, name); - } - - /** - * Copies the children of one DOM element to another DOM element - */ - function moveChildren(fromEl, toEl) { - var curChild = fromEl.firstChild; - while (curChild) { - var nextChild = curChild.nextSibling; - toEl.appendChild(curChild); - curChild = nextChild; - } - return toEl; - } - - function morphAttrs(fromNode, toNode) { - var attrs = toNode.attributes; - var i; - var attr; - var attrName; - var attrNamespaceURI; - var attrValue; - var fromValue; - - for (i = attrs.length - 1; i >= 0; --i) { - attr = attrs[i]; - attrName = attr.name; - attrNamespaceURI = attr.namespaceURI; - attrValue = attr.value; - - if (attrNamespaceURI) { - attrName = attr.localName || attrName; - fromValue = fromNode.getAttributeNS(attrNamespaceURI, attrName); - - if (fromValue !== attrValue) { - fromNode.setAttributeNS(attrNamespaceURI, attrName, attrValue); - } - } else { - fromValue = fromNode.getAttribute(attrName); - - if (fromValue !== attrValue) { - fromNode.setAttribute(attrName, attrValue); - } - } - } - - // Remove any extra attributes found on the original DOM element that - // weren't found on the target element. - attrs = fromNode.attributes; - - for (i = attrs.length - 1; i >= 0; --i) { - attr = attrs[i]; - if (attr.specified !== false) { - attrName = attr.name; - attrNamespaceURI = attr.namespaceURI; - - if (attrNamespaceURI) { - attrName = attr.localName || attrName; - - if (!hasAttributeNS(toNode, attrNamespaceURI, attrName)) { - fromNode.removeAttributeNS(attrNamespaceURI, attrName); - } - } else { - if (!hasAttributeNS(toNode, null, attrName)) { - fromNode.removeAttribute(attrName); - } - } - } - } - } - - function syncBooleanAttrProp(fromEl, toEl, name) { - if (fromEl[name] !== toEl[name]) { - fromEl[name] = toEl[name]; - if (fromEl[name]) { - fromEl.setAttribute(name, ''); - } else { - fromEl.removeAttribute(name, ''); - } - } - } - - var specialElHandlers = { - /** - * Needed for IE. Apparently IE doesn't think that "selected" is an - * attribute when reading over the attributes using selectEl.attributes - */ - OPTION: function OPTION(fromEl, toEl) { - syncBooleanAttrProp(fromEl, toEl, 'selected'); - }, - /** - * The "value" attribute is special for the element since it sets - * the initial value. Changing the "value" attribute without changing the - * "value" property will have no effect since it is only used to the set the - * initial value. Similar for the "checked" attribute, and "disabled". - */ - INPUT: function INPUT(fromEl, toEl) { - syncBooleanAttrProp(fromEl, toEl, 'checked'); - syncBooleanAttrProp(fromEl, toEl, 'disabled'); - - if (fromEl.value !== toEl.value) { - fromEl.value = toEl.value; - } - - if (!hasAttributeNS(toEl, null, 'value')) { - fromEl.removeAttribute('value'); - } - }, - - TEXTAREA: function TEXTAREA(fromEl, toEl) { - var newValue = toEl.value; - if (fromEl.value !== newValue) { - fromEl.value = newValue; - } - - if (fromEl.firstChild) { - // Needed for IE. Apparently IE sets the placeholder as the - // node value and vise versa. This ignores an empty update. - if (newValue === '' && fromEl.firstChild.nodeValue === fromEl.placeholder) { - return; - } - - fromEl.firstChild.nodeValue = newValue; - } - }, - SELECT: function SELECT(fromEl, toEl) { - if (!hasAttributeNS(toEl, null, 'multiple')) { - var selectedIndex = -1; - var i = 0; - var curChild = toEl.firstChild; - while (curChild) { - var nodeName = curChild.nodeName; - if (nodeName && nodeName.toUpperCase() === 'OPTION') { - if (hasAttributeNS(curChild, null, 'selected')) { - selectedIndex = i; - break; - } - i++; - } - curChild = curChild.nextSibling; - } - - fromEl.selectedIndex = i; - } - } - }; - - var ELEMENT_NODE = 1; - var TEXT_NODE = 3; - var COMMENT_NODE = 8; - - function noop() {} - - function defaultGetNodeKey(node) { - return node.id; - } - - function morphdomFactory(morphAttrs) { - - return function morphdom(fromNode, toNode, options) { - if (!options) { - options = {}; - } - - if (typeof toNode === 'string') { - if (fromNode.nodeName === '#document' || fromNode.nodeName === 'HTML') { - var toNodeHtml = toNode; - toNode = doc.createElement('html'); - toNode.innerHTML = toNodeHtml; - } else { - toNode = toElement(toNode); - } - } - - var getNodeKey = options.getNodeKey || defaultGetNodeKey; - var onBeforeNodeAdded = options.onBeforeNodeAdded || noop; - var onNodeAdded = options.onNodeAdded || noop; - var onBeforeElUpdated = options.onBeforeElUpdated || noop; - var onElUpdated = options.onElUpdated || noop; - var onBeforeNodeDiscarded = options.onBeforeNodeDiscarded || noop; - var onNodeDiscarded = options.onNodeDiscarded || noop; - var onBeforeElChildrenUpdated = options.onBeforeElChildrenUpdated || noop; - var childrenOnly = options.childrenOnly === true; - - // This object is used as a lookup to quickly find all keyed elements in the original DOM tree. - var fromNodesLookup = {}; - var keyedRemovalList; - - function addKeyedRemoval(key) { - if (keyedRemovalList) { - keyedRemovalList.push(key); - } else { - keyedRemovalList = [key]; - } - } - - function walkDiscardedChildNodes(node, skipKeyedNodes) { - if (node.nodeType === ELEMENT_NODE) { - var curChild = node.firstChild; - while (curChild) { - - var key = undefined; - - if (skipKeyedNodes && (key = getNodeKey(curChild))) { - // If we are skipping keyed nodes then we add the key - // to a list so that it can be handled at the very end. - addKeyedRemoval(key); - } else { - // Only report the node as discarded if it is not keyed. We do this because - // at the end we loop through all keyed elements that were unmatched - // and then discard them in one final pass. - onNodeDiscarded(curChild); - if (curChild.firstChild) { - walkDiscardedChildNodes(curChild, skipKeyedNodes); - } - } - - curChild = curChild.nextSibling; - } - } - } - - /** - * Removes a DOM node out of the original DOM - * - * @param {Node} node The node to remove - * @param {Node} parentNode The nodes parent - * @param {Boolean} skipKeyedNodes If true then elements with keys will be skipped and not discarded. - * @return {undefined} - */ - function removeNode(node, parentNode, skipKeyedNodes) { - if (onBeforeNodeDiscarded(node) === false) { - return; - } - - if (parentNode) { - parentNode.removeChild(node); - } - - onNodeDiscarded(node); - walkDiscardedChildNodes(node, skipKeyedNodes); - } - - // // TreeWalker implementation is no faster, but keeping this around in case this changes in the future - // function indexTree(root) { - // var treeWalker = document.createTreeWalker( - // root, - // NodeFilter.SHOW_ELEMENT); - // - // var el; - // while((el = treeWalker.nextNode())) { - // var key = getNodeKey(el); - // if (key) { - // fromNodesLookup[key] = el; - // } - // } - // } - - // // NodeIterator implementation is no faster, but keeping this around in case this changes in the future - // - // function indexTree(node) { - // var nodeIterator = document.createNodeIterator(node, NodeFilter.SHOW_ELEMENT); - // var el; - // while((el = nodeIterator.nextNode())) { - // var key = getNodeKey(el); - // if (key) { - // fromNodesLookup[key] = el; - // } - // } - // } - - function indexTree(node) { - if (node.nodeType === ELEMENT_NODE) { - var curChild = node.firstChild; - while (curChild) { - var key = getNodeKey(curChild); - if (key) { - fromNodesLookup[key] = curChild; - } - - // Walk recursively - indexTree(curChild); - - curChild = curChild.nextSibling; - } - } - } - - indexTree(fromNode); - - function handleNodeAdded(el) { - onNodeAdded(el); - - var curChild = el.firstChild; - while (curChild) { - var nextSibling = curChild.nextSibling; - - var key = getNodeKey(curChild); - if (key) { - var unmatchedFromEl = fromNodesLookup[key]; - if (unmatchedFromEl && compareNodeNames(curChild, unmatchedFromEl)) { - curChild.parentNode.replaceChild(unmatchedFromEl, curChild); - morphEl(unmatchedFromEl, curChild); - } - } - - handleNodeAdded(curChild); - curChild = nextSibling; - } - } - - function morphEl(fromEl, toEl, childrenOnly) { - var toElKey = getNodeKey(toEl); - var curFromNodeKey; - - if (toElKey) { - // If an element with an ID is being morphed then it is will be in the final - // DOM so clear it out of the saved elements collection - delete fromNodesLookup[toElKey]; - } - - if (toNode.isSameNode && toNode.isSameNode(fromNode)) { - return; - } - - if (!childrenOnly) { - if (onBeforeElUpdated(fromEl, toEl) === false) { - return; - } - - morphAttrs(fromEl, toEl); - onElUpdated(fromEl); - - if (onBeforeElChildrenUpdated(fromEl, toEl) === false) { - return; - } - } - - if (fromEl.nodeName !== 'TEXTAREA') { - var curToNodeChild = toEl.firstChild; - var curFromNodeChild = fromEl.firstChild; - var curToNodeKey; - - var fromNextSibling; - var toNextSibling; - var matchingFromEl; - - outer: while (curToNodeChild) { - toNextSibling = curToNodeChild.nextSibling; - curToNodeKey = getNodeKey(curToNodeChild); - - while (curFromNodeChild) { - fromNextSibling = curFromNodeChild.nextSibling; - - if (curToNodeChild.isSameNode && curToNodeChild.isSameNode(curFromNodeChild)) { - curToNodeChild = toNextSibling; - curFromNodeChild = fromNextSibling; - continue outer; - } - - curFromNodeKey = getNodeKey(curFromNodeChild); - - var curFromNodeType = curFromNodeChild.nodeType; - - var isCompatible = undefined; - - if (curFromNodeType === curToNodeChild.nodeType) { - if (curFromNodeType === ELEMENT_NODE) { - // Both nodes being compared are Element nodes - - if (curToNodeKey) { - // The target node has a key so we want to match it up with the correct element - // in the original DOM tree - if (curToNodeKey !== curFromNodeKey) { - // The current element in the original DOM tree does not have a matching key so - // let's check our lookup to see if there is a matching element in the original - // DOM tree - if (matchingFromEl = fromNodesLookup[curToNodeKey]) { - if (curFromNodeChild.nextSibling === matchingFromEl) { - // Special case for single element removals. To avoid removing the original - // DOM node out of the tree (since that can break CSS transitions, etc.), - // we will instead discard the current node and wait until the next - // iteration to properly match up the keyed target element with its matching - // element in the original tree - isCompatible = false; - } else { - // We found a matching keyed element somewhere in the original DOM tree. - // Let's moving the original DOM node into the current position and morph - // it. - - // NOTE: We use insertBefore instead of replaceChild because we want to go through - // the `removeNode()` function for the node that is being discarded so that - // all lifecycle hooks are correctly invoked - fromEl.insertBefore(matchingFromEl, curFromNodeChild); - - fromNextSibling = curFromNodeChild.nextSibling; - - if (curFromNodeKey) { - // Since the node is keyed it might be matched up later so we defer - // the actual removal to later - addKeyedRemoval(curFromNodeKey); - } else { - // NOTE: we skip nested keyed nodes from being removed since there is - // still a chance they will be matched up later - removeNode(curFromNodeChild, fromEl, true /* skip keyed nodes */); - } - - curFromNodeChild = matchingFromEl; - } - } else { - // The nodes are not compatible since the "to" node has a key and there - // is no matching keyed node in the source tree - isCompatible = false; - } - } - } else if (curFromNodeKey) { - // The original has a key - isCompatible = false; - } - - isCompatible = isCompatible !== false && compareNodeNames(curFromNodeChild, curToNodeChild); - if (isCompatible) { - // We found compatible DOM elements so transform - // the current "from" node to match the current - // target DOM node. - morphEl(curFromNodeChild, curToNodeChild); - } - } else if (curFromNodeType === TEXT_NODE || curFromNodeType == COMMENT_NODE) { - // Both nodes being compared are Text or Comment nodes - isCompatible = true; - // Simply update nodeValue on the original node to - // change the text value - curFromNodeChild.nodeValue = curToNodeChild.nodeValue; - } - } - - if (isCompatible) { - // Advance both the "to" child and the "from" child since we found a match - curToNodeChild = toNextSibling; - curFromNodeChild = fromNextSibling; - continue outer; - } - - // No compatible match so remove the old node from the DOM and continue trying to find a - // match in the original DOM. However, we only do this if the from node is not keyed - // since it is possible that a keyed node might match up with a node somewhere else in the - // target tree and we don't want to discard it just yet since it still might find a - // home in the final DOM tree. After everything is done we will remove any keyed nodes - // that didn't find a home - if (curFromNodeKey) { - // Since the node is keyed it might be matched up later so we defer - // the actual removal to later - addKeyedRemoval(curFromNodeKey); - } else { - // NOTE: we skip nested keyed nodes from being removed since there is - // still a chance they will be matched up later - removeNode(curFromNodeChild, fromEl, true /* skip keyed nodes */); - } - - curFromNodeChild = fromNextSibling; - } - - // If we got this far then we did not find a candidate match for - // our "to node" and we exhausted all of the children "from" - // nodes. Therefore, we will just append the current "to" node - // to the end - if (curToNodeKey && (matchingFromEl = fromNodesLookup[curToNodeKey]) && compareNodeNames(matchingFromEl, curToNodeChild)) { - fromEl.appendChild(matchingFromEl); - morphEl(matchingFromEl, curToNodeChild); - } else { - var onBeforeNodeAddedResult = onBeforeNodeAdded(curToNodeChild); - if (onBeforeNodeAddedResult !== false) { - if (onBeforeNodeAddedResult) { - curToNodeChild = onBeforeNodeAddedResult; - } - - if (curToNodeChild.actualize) { - curToNodeChild = curToNodeChild.actualize(fromEl.ownerDocument || doc); - } - fromEl.appendChild(curToNodeChild); - handleNodeAdded(curToNodeChild); - } - } - - curToNodeChild = toNextSibling; - curFromNodeChild = fromNextSibling; - } - - // We have processed all of the "to nodes". If curFromNodeChild is - // non-null then we still have some from nodes left over that need - // to be removed - while (curFromNodeChild) { - fromNextSibling = curFromNodeChild.nextSibling; - if (curFromNodeKey = getNodeKey(curFromNodeChild)) { - // Since the node is keyed it might be matched up later so we defer - // the actual removal to later - addKeyedRemoval(curFromNodeKey); - } else { - // NOTE: we skip nested keyed nodes from being removed since there is - // still a chance they will be matched up later - removeNode(curFromNodeChild, fromEl, true /* skip keyed nodes */); - } - curFromNodeChild = fromNextSibling; - } - } - - var specialElHandler = specialElHandlers[fromEl.nodeName]; - if (specialElHandler) { - specialElHandler(fromEl, toEl); - } - } // END: morphEl(...) - - var morphedNode = fromNode; - var morphedNodeType = morphedNode.nodeType; - var toNodeType = toNode.nodeType; - - if (!childrenOnly) { - // Handle the case where we are given two DOM nodes that are not - // compatible (e.g.
--> or
--> TEXT) - if (morphedNodeType === ELEMENT_NODE) { - if (toNodeType === ELEMENT_NODE) { - if (!compareNodeNames(fromNode, toNode)) { - onNodeDiscarded(fromNode); - morphedNode = moveChildren(fromNode, createElementNS(toNode.nodeName, toNode.namespaceURI)); - } - } else { - // Going from an element node to a text node - morphedNode = toNode; - } - } else if (morphedNodeType === TEXT_NODE || morphedNodeType === COMMENT_NODE) { - // Text or comment node - if (toNodeType === morphedNodeType) { - morphedNode.nodeValue = toNode.nodeValue; - return morphedNode; - } else { - // Text node to something else - morphedNode = toNode; - } - } - } - - if (morphedNode === toNode) { - // The "to node" was not compatible with the "from node" so we had to - // toss out the "from node" and use the "to node" - onNodeDiscarded(fromNode); - } else { - morphEl(morphedNode, toNode, childrenOnly); - - // We now need to loop over any keyed nodes that might need to be - // removed. We only do the removal if we know that the keyed node - // never found a match. When a keyed node is matched up we remove - // it out of fromNodesLookup and we use fromNodesLookup to determine - // if a keyed node has been matched up or not - if (keyedRemovalList) { - for (var i = 0, len = keyedRemovalList.length; i < len; i++) { - var elToRemove = fromNodesLookup[keyedRemovalList[i]]; - if (elToRemove) { - removeNode(elToRemove, elToRemove.parentNode, false); - } - } - } - } - - if (!childrenOnly && morphedNode !== fromNode && fromNode.parentNode) { - if (morphedNode.actualize) { - morphedNode = morphedNode.actualize(fromNode.ownerDocument || doc); - } - // If we had to swap out the from node with a new node because the old - // node was not compatible with the target node then we need to - // replace the old DOM node in the original DOM tree. This is only - // possible if the original DOM node was part of a DOM tree which - // we know is the case if it has a parent node. - fromNode.parentNode.replaceChild(morphedNode, fromNode); - } - - return morphedNode; - }; - } - - var morphdom = morphdomFactory(morphAttrs); - - return morphdom; - }); - - /***/ }, - /* 7 */ - /***/ function(module, exports) { - - "use strict"; - - Object.defineProperty(exports, "__esModule", { - value: true - }); - /* - * html2json for omi - * https://github.com/AlloyTeam/omi - * - * Original code by John Resig (ejohn.org) - * http://ejohn.org/blog/pure-javascript-html-parser/ - * Original code by Erik Arvidsson, Mozilla Public License - * http://erik.eae.net/simplehtmlparser/simplehtmlparser.js - * Original code by Jxck - * https://github.com/Jxck/html2json - */ - - // Regular Expressions for parsing tags and attributes - var startTag = /^<([-A-Za-z0-9_]+)((?:\s+[a-zA-Z_:][-a-zA-Z0-9_:.]*(?:\s*=\s*(?:(?:"[^"]*")|(?:'[^']*')|[^>\s]+))?)*)\s*(\/?)>/, - endTag = /^<\/([-A-Za-z0-9_]+)[^>]*>/, - attr = /([a-zA-Z_:][-a-zA-Z0-9_:.]*)(?:\s*=\s*(?:(?:"((?:\\.|[^"])*)")|(?:'((?:\\.|[^'])*)')|([^>\s]+)))?/g; - - var HTMLParser = function HTMLParser(html, handler) { - var index, - chars, - match, - stack = [], - last = html; - stack.last = function () { - return this[this.length - 1]; - }; - - while (html) { - chars = true; - - // Make sure we're not in a script or style element - if (!stack.last()) { - - if (html.indexOf("]*>"), function (all, text) { - - if (handler.chars) handler.chars(text); - - return ""; - }); - - parseEndTag("", stack.last()); - } - - if (html == last) throw "Parse Error: " + html; - last = html; - } - - // Clean up any remaining tags - parseEndTag(); - - function parseStartTag(tag, tagName, rest, unary) { - tagName = tagName.toLowerCase(); - - unary = !!unary; - - if (!unary) stack.push(tagName); - - if (handler.start) { - var attrs = []; - - rest.replace(attr, function (match, name) { - var value = arguments[2] ? arguments[2] : arguments[3] ? arguments[3] : arguments[4] ? arguments[4] : ""; - - attrs.push({ - name: name, - value: value, - escaped: value.replace(/(^|[^\\])"/g, '$1\\\"') //" - }); - }); - - if (handler.start) handler.start(tagName, attrs, unary); - } - } - - function parseEndTag(tag, tagName) { - // If no tag name is provided, clean shop - if (!tagName) var pos = 0; - - // Find the closest opened tag of the same type - else for (var pos = stack.length - 1; pos >= 0; pos--) { - if (stack[pos] == tagName) break; - }if (pos >= 0) { - // Close all the open elements, up the stack - for (var i = stack.length - 1; i >= pos; i--) { - if (handler.end) handler.end(stack[i]); - } // Remove the open elements from the stack - stack.length = pos; - } - } - }; - - var DEBUG = false; - var debug = DEBUG ? console.log.bind(console) : function () {}; - - // Production steps of ECMA-262, Edition 5, 15.4.4.21 - // Reference: http://es5.github.io/#x15.4.4.21 - if (!Array.prototype.reduce) { - Array.prototype.reduce = function (callback /*, initialValue*/) { - 'use strict'; - - if (this == null) { - throw new TypeError('Array.prototype.reduce called on null or undefined'); - } - if (typeof callback !== 'function') { - throw new TypeError(callback + ' is not a function'); - } - var t = Object(this), - len = t.length >>> 0, - k = 0, - value; - if (arguments.length == 2) { - value = arguments[1]; - } else { - while (k < len && !(k in t)) { - k++; - } - if (k >= len) { - throw new TypeError('Reduce of empty array with no initial value'); - } - value = t[k++]; - } - for (; k < len; k++) { - if (k in t) { - value = callback(value, t[k], k, t); - } - } - return value; - }; - } - - var html2json = function html2json(html) { - - var bufArray = []; - var results = { - node: 'root', - child: [] - }; - HTMLParser(html, { - start: function start(tag, attrs, unary) { - debug(tag, attrs, unary); - // node for this element - var node = { - node: 'element', - tag: tag - }; - if (attrs.length !== 0) { - node.attr = attrs.reduce(function (pre, attr) { - var name = attr.name; - var value = attr.value; - - pre[name] = value; - return pre; - }, {}); - } - if (unary) { - // if this tag dosen't have end tag - // like - // add to parents - var parent = bufArray[0] || results; - if (parent.child === undefined) { - parent.child = []; - } - parent.child.push(node); - } else { - bufArray.unshift(node); - } - }, - end: function end(tag) { - debug(tag); - // merge into parent tag - var node = bufArray.shift(); - if (node.tag !== tag) console.error('invalid state: mismatch end tag'); - - if (bufArray.length === 0) { - results.child.push(node); - } else { - var parent = bufArray[0]; - if (parent.child === undefined) { - parent.child = []; - } - parent.child.push(node); - } - }, - chars: function chars(text) { - debug(text); - var node = { - node: 'text', - text: text - }; - if (bufArray.length === 0) { - results.child.push(node); - } else { - var parent = bufArray[0]; - if (parent.child === undefined) { - parent.child = []; - } - parent.child.push(node); - } - } - }); - return results; - }; - - exports["default"] = html2json; - - /***/ } - /******/ ]) - }); - ; - -/***/ } -]); \ No newline at end of file diff --git a/website/js/vendor.7788bc23.js b/website/js/vendor.76cd4b98.js similarity index 98% rename from website/js/vendor.7788bc23.js rename to website/js/vendor.76cd4b98.js index 88bae6ab5..bbec4a681 100644 --- a/website/js/vendor.7788bc23.js +++ b/website/js/vendor.76cd4b98.js @@ -76,7 +76,7 @@ /******/ script.charset = 'utf-8'; /******/ script.async = true; -/******/ script.src = __webpack_require__.p + "" + chunkId + "." + ({"0":"docs-cn","1":"docs-en","2":"omi"}[chunkId]||chunkId) + "." + {"0":"8b99c3b2","1":"78edfa73","2":"b9df77fe"}[chunkId] + ".js"; +/******/ script.src = __webpack_require__.p + "" + chunkId + "." + ({"0":"docs-cn","1":"docs-en","2":"omi"}[chunkId]||chunkId) + "." + {"0":"d9e1e610","1":"6a3d3922","2":"461a076c"}[chunkId] + ".js"; /******/ head.appendChild(script); /******/ } /******/ }; diff --git a/website/js/vendor.99e5de52.js b/website/js/vendor.99e5de52.js deleted file mode 100644 index 1faa9fcfa..000000000 --- a/website/js/vendor.99e5de52.js +++ /dev/null @@ -1,200 +0,0 @@ -/******/ (function(modules) { // webpackBootstrap -/******/ // install a JSONP callback for chunk loading -/******/ var parentJsonpFunction = window["webpackJsonp"]; -/******/ window["webpackJsonp"] = function webpackJsonpCallback(chunkIds, moreModules) { -/******/ // add "moreModules" to the modules object, -/******/ // then flag all "chunkIds" as loaded and fire callback -/******/ var moduleId, chunkId, i = 0, callbacks = []; -/******/ for(;i < chunkIds.length; i++) { -/******/ chunkId = chunkIds[i]; -/******/ if(installedChunks[chunkId]) -/******/ callbacks.push.apply(callbacks, installedChunks[chunkId]); -/******/ installedChunks[chunkId] = 0; -/******/ } -/******/ for(moduleId in moreModules) { -/******/ modules[moduleId] = moreModules[moduleId]; -/******/ } -/******/ if(parentJsonpFunction) parentJsonpFunction(chunkIds, moreModules); -/******/ while(callbacks.length) -/******/ callbacks.shift().call(null, __webpack_require__); -/******/ if(moreModules[0]) { -/******/ installedModules[0] = 0; -/******/ return __webpack_require__(0); -/******/ } -/******/ }; - -/******/ // The module cache -/******/ var installedModules = {}; - -/******/ // object to store loaded and loading chunks -/******/ // "0" means "already loaded" -/******/ // Array means "loading", array contains callbacks -/******/ var installedChunks = { -/******/ 3:0 -/******/ }; - -/******/ // The require function -/******/ function __webpack_require__(moduleId) { - -/******/ // Check if module is in cache -/******/ if(installedModules[moduleId]) -/******/ return installedModules[moduleId].exports; - -/******/ // Create a new module (and put it into the cache) -/******/ var module = installedModules[moduleId] = { -/******/ exports: {}, -/******/ id: moduleId, -/******/ loaded: false -/******/ }; - -/******/ // Execute the module function -/******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__); - -/******/ // Flag the module as loaded -/******/ module.loaded = true; - -/******/ // Return the exports of the module -/******/ return module.exports; -/******/ } - -/******/ // This file contains only the entry chunk. -/******/ // The chunk loading function for additional chunks -/******/ __webpack_require__.e = function requireEnsure(chunkId, callback) { -/******/ // "0" is the signal for "already loaded" -/******/ if(installedChunks[chunkId] === 0) -/******/ return callback.call(null, __webpack_require__); - -/******/ // an array means "currently loading". -/******/ if(installedChunks[chunkId] !== undefined) { -/******/ installedChunks[chunkId].push(callback); -/******/ } else { -/******/ // start chunk loading -/******/ installedChunks[chunkId] = [callback]; -/******/ var head = document.getElementsByTagName('head')[0]; -/******/ var script = document.createElement('script'); -/******/ script.type = 'text/javascript'; -/******/ script.charset = 'utf-8'; -/******/ script.async = true; - -/******/ script.src = __webpack_require__.p + "" + chunkId + "." + ({"0":"docs-cn","1":"docs-en","2":"omi"}[chunkId]||chunkId) + "." + {"0":"aef27307","1":"b820c139","2":"b9df77fe"}[chunkId] + ".js"; -/******/ head.appendChild(script); -/******/ } -/******/ }; - -/******/ // expose the modules object (__webpack_modules__) -/******/ __webpack_require__.m = modules; - -/******/ // expose the module cache -/******/ __webpack_require__.c = installedModules; - -/******/ // __webpack_public_path__ -/******/ __webpack_require__.p = ""; - -/******/ // Load entry module and return exports -/******/ return __webpack_require__(0); -/******/ }) -/************************************************************************/ -/******/ ({ - -/***/ 0: -/***/ function(module, exports, __webpack_require__) { - - module.exports = __webpack_require__(51); - - -/***/ }, - -/***/ 51: -/***/ function(module, exports) { - - "use strict"; - - /*! @source http://purl.eligrey.com/github/classList.js/blob/master/classList.js */ - "document" in self && ("classList" in document.createElement("_") && (!document.createElementNS || "classList" in document.createElementNS("http://www.w3.org/2000/svg", "g")) ? !function () { - "use strict"; - var t = document.createElement("_");if (t.classList.add("c1", "c2"), !t.classList.contains("c2")) { - var e = function e(t) { - var e = DOMTokenList.prototype[t];DOMTokenList.prototype[t] = function (t) { - var n, - i = arguments.length;for (n = 0; i > n; n++) { - t = arguments[n], e.call(this, t); - } - }; - };e("add"), e("remove"); - }if (t.classList.toggle("c3", !1), t.classList.contains("c3")) { - var n = DOMTokenList.prototype.toggle;DOMTokenList.prototype.toggle = function (t, e) { - return 1 in arguments && !this.contains(t) == !e ? e : n.call(this, t); - }; - }t = null; - }() : !function (t) { - "use strict"; - if ("Element" in t) { - var e = "classList", - n = "prototype", - i = t.Element[n], - s = Object, - r = String[n].trim || function () { - return this.replace(/^\s+|\s+$/g, ""); - }, - o = Array[n].indexOf || function (t) { - for (var e = 0, n = this.length; n > e; e++) { - if (e in this && this[e] === t) return e; - }return -1; - }, - c = function c(t, e) { - this.name = t, this.code = DOMException[t], this.message = e; - }, - a = function a(t, e) { - if ("" === e) throw new c("SYNTAX_ERR", "An invalid or illegal string was specified");if (/\s/.test(e)) throw new c("INVALID_CHARACTER_ERR", "String contains an invalid character");return o.call(t, e); - }, - l = function l(t) { - for (var e = r.call(t.getAttribute("class") || ""), n = e ? e.split(/\s+/) : [], i = 0, s = n.length; s > i; i++) { - this.push(n[i]); - }this._updateClassName = function () { - t.setAttribute("class", this.toString()); - }; - }, - u = l[n] = [], - h = function h() { - return new l(this); - };if (c[n] = Error[n], u.item = function (t) { - return this[t] || null; - }, u.contains = function (t) { - return t += "", -1 !== a(this, t); - }, u.add = function () { - var t, - e = arguments, - n = 0, - i = e.length, - s = !1;do { - t = e[n] + "", -1 === a(this, t) && (this.push(t), s = !0); - } while (++n < i);s && this._updateClassName(); - }, u.remove = function () { - var t, - e, - n = arguments, - i = 0, - s = n.length, - r = !1;do { - for (t = n[i] + "", e = a(this, t); -1 !== e;) { - this.splice(e, 1), r = !0, e = a(this, t); - } - } while (++i < s);r && this._updateClassName(); - }, u.toggle = function (t, e) { - t += "";var n = this.contains(t), - i = n ? e !== !0 && "remove" : e !== !1 && "add";return i && this[i](t), e === !0 || e === !1 ? e : !n; - }, u.toString = function () { - return this.join(" "); - }, s.defineProperty) { - var f = { get: h, enumerable: !0, configurable: !0 };try { - s.defineProperty(i, e, f); - } catch (d) { - void 0 !== d.number && -2146823252 !== d.number || (f.enumerable = !1, s.defineProperty(i, e, f)); - } - } else s[n].__defineGetter__ && i.__defineGetter__(e, h); - } - }(self)); - -/***/ } - -/******/ }); \ No newline at end of file diff --git a/website/js/vendor.bc2f6e70.js b/website/js/vendor.bc2f6e70.js deleted file mode 100644 index 7a966407f..000000000 --- a/website/js/vendor.bc2f6e70.js +++ /dev/null @@ -1,200 +0,0 @@ -/******/ (function(modules) { // webpackBootstrap -/******/ // install a JSONP callback for chunk loading -/******/ var parentJsonpFunction = window["webpackJsonp"]; -/******/ window["webpackJsonp"] = function webpackJsonpCallback(chunkIds, moreModules) { -/******/ // add "moreModules" to the modules object, -/******/ // then flag all "chunkIds" as loaded and fire callback -/******/ var moduleId, chunkId, i = 0, callbacks = []; -/******/ for(;i < chunkIds.length; i++) { -/******/ chunkId = chunkIds[i]; -/******/ if(installedChunks[chunkId]) -/******/ callbacks.push.apply(callbacks, installedChunks[chunkId]); -/******/ installedChunks[chunkId] = 0; -/******/ } -/******/ for(moduleId in moreModules) { -/******/ modules[moduleId] = moreModules[moduleId]; -/******/ } -/******/ if(parentJsonpFunction) parentJsonpFunction(chunkIds, moreModules); -/******/ while(callbacks.length) -/******/ callbacks.shift().call(null, __webpack_require__); -/******/ if(moreModules[0]) { -/******/ installedModules[0] = 0; -/******/ return __webpack_require__(0); -/******/ } -/******/ }; - -/******/ // The module cache -/******/ var installedModules = {}; - -/******/ // object to store loaded and loading chunks -/******/ // "0" means "already loaded" -/******/ // Array means "loading", array contains callbacks -/******/ var installedChunks = { -/******/ 3:0 -/******/ }; - -/******/ // The require function -/******/ function __webpack_require__(moduleId) { - -/******/ // Check if module is in cache -/******/ if(installedModules[moduleId]) -/******/ return installedModules[moduleId].exports; - -/******/ // Create a new module (and put it into the cache) -/******/ var module = installedModules[moduleId] = { -/******/ exports: {}, -/******/ id: moduleId, -/******/ loaded: false -/******/ }; - -/******/ // Execute the module function -/******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__); - -/******/ // Flag the module as loaded -/******/ module.loaded = true; - -/******/ // Return the exports of the module -/******/ return module.exports; -/******/ } - -/******/ // This file contains only the entry chunk. -/******/ // The chunk loading function for additional chunks -/******/ __webpack_require__.e = function requireEnsure(chunkId, callback) { -/******/ // "0" is the signal for "already loaded" -/******/ if(installedChunks[chunkId] === 0) -/******/ return callback.call(null, __webpack_require__); - -/******/ // an array means "currently loading". -/******/ if(installedChunks[chunkId] !== undefined) { -/******/ installedChunks[chunkId].push(callback); -/******/ } else { -/******/ // start chunk loading -/******/ installedChunks[chunkId] = [callback]; -/******/ var head = document.getElementsByTagName('head')[0]; -/******/ var script = document.createElement('script'); -/******/ script.type = 'text/javascript'; -/******/ script.charset = 'utf-8'; -/******/ script.async = true; - -/******/ script.src = __webpack_require__.p + "" + chunkId + "." + ({"0":"docs-cn","1":"docs-en","2":"omi"}[chunkId]||chunkId) + "." + {"0":"af59252f","1":"c02b58b9","2":"461a076c"}[chunkId] + ".js"; -/******/ head.appendChild(script); -/******/ } -/******/ }; - -/******/ // expose the modules object (__webpack_modules__) -/******/ __webpack_require__.m = modules; - -/******/ // expose the module cache -/******/ __webpack_require__.c = installedModules; - -/******/ // __webpack_public_path__ -/******/ __webpack_require__.p = ""; - -/******/ // Load entry module and return exports -/******/ return __webpack_require__(0); -/******/ }) -/************************************************************************/ -/******/ ({ - -/***/ 0: -/***/ function(module, exports, __webpack_require__) { - - module.exports = __webpack_require__(51); - - -/***/ }, - -/***/ 51: -/***/ function(module, exports) { - - "use strict"; - - /*! @source http://purl.eligrey.com/github/classList.js/blob/master/classList.js */ - "document" in self && ("classList" in document.createElement("_") && (!document.createElementNS || "classList" in document.createElementNS("http://www.w3.org/2000/svg", "g")) ? !function () { - "use strict"; - var t = document.createElement("_");if (t.classList.add("c1", "c2"), !t.classList.contains("c2")) { - var e = function e(t) { - var e = DOMTokenList.prototype[t];DOMTokenList.prototype[t] = function (t) { - var n, - i = arguments.length;for (n = 0; i > n; n++) { - t = arguments[n], e.call(this, t); - } - }; - };e("add"), e("remove"); - }if (t.classList.toggle("c3", !1), t.classList.contains("c3")) { - var n = DOMTokenList.prototype.toggle;DOMTokenList.prototype.toggle = function (t, e) { - return 1 in arguments && !this.contains(t) == !e ? e : n.call(this, t); - }; - }t = null; - }() : !function (t) { - "use strict"; - if ("Element" in t) { - var e = "classList", - n = "prototype", - i = t.Element[n], - s = Object, - r = String[n].trim || function () { - return this.replace(/^\s+|\s+$/g, ""); - }, - o = Array[n].indexOf || function (t) { - for (var e = 0, n = this.length; n > e; e++) { - if (e in this && this[e] === t) return e; - }return -1; - }, - c = function c(t, e) { - this.name = t, this.code = DOMException[t], this.message = e; - }, - a = function a(t, e) { - if ("" === e) throw new c("SYNTAX_ERR", "An invalid or illegal string was specified");if (/\s/.test(e)) throw new c("INVALID_CHARACTER_ERR", "String contains an invalid character");return o.call(t, e); - }, - l = function l(t) { - for (var e = r.call(t.getAttribute("class") || ""), n = e ? e.split(/\s+/) : [], i = 0, s = n.length; s > i; i++) { - this.push(n[i]); - }this._updateClassName = function () { - t.setAttribute("class", this.toString()); - }; - }, - u = l[n] = [], - h = function h() { - return new l(this); - };if (c[n] = Error[n], u.item = function (t) { - return this[t] || null; - }, u.contains = function (t) { - return t += "", -1 !== a(this, t); - }, u.add = function () { - var t, - e = arguments, - n = 0, - i = e.length, - s = !1;do { - t = e[n] + "", -1 === a(this, t) && (this.push(t), s = !0); - } while (++n < i);s && this._updateClassName(); - }, u.remove = function () { - var t, - e, - n = arguments, - i = 0, - s = n.length, - r = !1;do { - for (t = n[i] + "", e = a(this, t); -1 !== e;) { - this.splice(e, 1), r = !0, e = a(this, t); - } - } while (++i < s);r && this._updateClassName(); - }, u.toggle = function (t, e) { - t += "";var n = this.contains(t), - i = n ? e !== !0 && "remove" : e !== !1 && "add";return i && this[i](t), e === !0 || e === !1 ? e : !n; - }, u.toString = function () { - return this.join(" "); - }, s.defineProperty) { - var f = { get: h, enumerable: !0, configurable: !0 };try { - s.defineProperty(i, e, f); - } catch (d) { - void 0 !== d.number && -2146823252 !== d.number || (f.enumerable = !1, s.defineProperty(i, e, f)); - } - } else s[n].__defineGetter__ && i.__defineGetter__(e, h); - } - }(self)); - -/***/ } - -/******/ }); \ No newline at end of file diff --git a/website/js/vendor.f74de2a5.js b/website/js/vendor.f74de2a5.js deleted file mode 100644 index bd9af06cd..000000000 --- a/website/js/vendor.f74de2a5.js +++ /dev/null @@ -1,200 +0,0 @@ -/******/ (function(modules) { // webpackBootstrap -/******/ // install a JSONP callback for chunk loading -/******/ var parentJsonpFunction = window["webpackJsonp"]; -/******/ window["webpackJsonp"] = function webpackJsonpCallback(chunkIds, moreModules) { -/******/ // add "moreModules" to the modules object, -/******/ // then flag all "chunkIds" as loaded and fire callback -/******/ var moduleId, chunkId, i = 0, callbacks = []; -/******/ for(;i < chunkIds.length; i++) { -/******/ chunkId = chunkIds[i]; -/******/ if(installedChunks[chunkId]) -/******/ callbacks.push.apply(callbacks, installedChunks[chunkId]); -/******/ installedChunks[chunkId] = 0; -/******/ } -/******/ for(moduleId in moreModules) { -/******/ modules[moduleId] = moreModules[moduleId]; -/******/ } -/******/ if(parentJsonpFunction) parentJsonpFunction(chunkIds, moreModules); -/******/ while(callbacks.length) -/******/ callbacks.shift().call(null, __webpack_require__); -/******/ if(moreModules[0]) { -/******/ installedModules[0] = 0; -/******/ return __webpack_require__(0); -/******/ } -/******/ }; - -/******/ // The module cache -/******/ var installedModules = {}; - -/******/ // object to store loaded and loading chunks -/******/ // "0" means "already loaded" -/******/ // Array means "loading", array contains callbacks -/******/ var installedChunks = { -/******/ 3:0 -/******/ }; - -/******/ // The require function -/******/ function __webpack_require__(moduleId) { - -/******/ // Check if module is in cache -/******/ if(installedModules[moduleId]) -/******/ return installedModules[moduleId].exports; - -/******/ // Create a new module (and put it into the cache) -/******/ var module = installedModules[moduleId] = { -/******/ exports: {}, -/******/ id: moduleId, -/******/ loaded: false -/******/ }; - -/******/ // Execute the module function -/******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__); - -/******/ // Flag the module as loaded -/******/ module.loaded = true; - -/******/ // Return the exports of the module -/******/ return module.exports; -/******/ } - -/******/ // This file contains only the entry chunk. -/******/ // The chunk loading function for additional chunks -/******/ __webpack_require__.e = function requireEnsure(chunkId, callback) { -/******/ // "0" is the signal for "already loaded" -/******/ if(installedChunks[chunkId] === 0) -/******/ return callback.call(null, __webpack_require__); - -/******/ // an array means "currently loading". -/******/ if(installedChunks[chunkId] !== undefined) { -/******/ installedChunks[chunkId].push(callback); -/******/ } else { -/******/ // start chunk loading -/******/ installedChunks[chunkId] = [callback]; -/******/ var head = document.getElementsByTagName('head')[0]; -/******/ var script = document.createElement('script'); -/******/ script.type = 'text/javascript'; -/******/ script.charset = 'utf-8'; -/******/ script.async = true; - -/******/ script.src = __webpack_require__.p + "" + chunkId + "." + ({"0":"docs-cn","1":"docs-en","2":"omi"}[chunkId]||chunkId) + "." + {"0":"51cfc83d","1":"2c91bed5","2":"461a076c"}[chunkId] + ".js"; -/******/ head.appendChild(script); -/******/ } -/******/ }; - -/******/ // expose the modules object (__webpack_modules__) -/******/ __webpack_require__.m = modules; - -/******/ // expose the module cache -/******/ __webpack_require__.c = installedModules; - -/******/ // __webpack_public_path__ -/******/ __webpack_require__.p = ""; - -/******/ // Load entry module and return exports -/******/ return __webpack_require__(0); -/******/ }) -/************************************************************************/ -/******/ ({ - -/***/ 0: -/***/ function(module, exports, __webpack_require__) { - - module.exports = __webpack_require__(51); - - -/***/ }, - -/***/ 51: -/***/ function(module, exports) { - - "use strict"; - - /*! @source http://purl.eligrey.com/github/classList.js/blob/master/classList.js */ - "document" in self && ("classList" in document.createElement("_") && (!document.createElementNS || "classList" in document.createElementNS("http://www.w3.org/2000/svg", "g")) ? !function () { - "use strict"; - var t = document.createElement("_");if (t.classList.add("c1", "c2"), !t.classList.contains("c2")) { - var e = function e(t) { - var e = DOMTokenList.prototype[t];DOMTokenList.prototype[t] = function (t) { - var n, - i = arguments.length;for (n = 0; i > n; n++) { - t = arguments[n], e.call(this, t); - } - }; - };e("add"), e("remove"); - }if (t.classList.toggle("c3", !1), t.classList.contains("c3")) { - var n = DOMTokenList.prototype.toggle;DOMTokenList.prototype.toggle = function (t, e) { - return 1 in arguments && !this.contains(t) == !e ? e : n.call(this, t); - }; - }t = null; - }() : !function (t) { - "use strict"; - if ("Element" in t) { - var e = "classList", - n = "prototype", - i = t.Element[n], - s = Object, - r = String[n].trim || function () { - return this.replace(/^\s+|\s+$/g, ""); - }, - o = Array[n].indexOf || function (t) { - for (var e = 0, n = this.length; n > e; e++) { - if (e in this && this[e] === t) return e; - }return -1; - }, - c = function c(t, e) { - this.name = t, this.code = DOMException[t], this.message = e; - }, - a = function a(t, e) { - if ("" === e) throw new c("SYNTAX_ERR", "An invalid or illegal string was specified");if (/\s/.test(e)) throw new c("INVALID_CHARACTER_ERR", "String contains an invalid character");return o.call(t, e); - }, - l = function l(t) { - for (var e = r.call(t.getAttribute("class") || ""), n = e ? e.split(/\s+/) : [], i = 0, s = n.length; s > i; i++) { - this.push(n[i]); - }this._updateClassName = function () { - t.setAttribute("class", this.toString()); - }; - }, - u = l[n] = [], - h = function h() { - return new l(this); - };if (c[n] = Error[n], u.item = function (t) { - return this[t] || null; - }, u.contains = function (t) { - return t += "", -1 !== a(this, t); - }, u.add = function () { - var t, - e = arguments, - n = 0, - i = e.length, - s = !1;do { - t = e[n] + "", -1 === a(this, t) && (this.push(t), s = !0); - } while (++n < i);s && this._updateClassName(); - }, u.remove = function () { - var t, - e, - n = arguments, - i = 0, - s = n.length, - r = !1;do { - for (t = n[i] + "", e = a(this, t); -1 !== e;) { - this.splice(e, 1), r = !0, e = a(this, t); - } - } while (++i < s);r && this._updateClassName(); - }, u.toggle = function (t, e) { - t += "";var n = this.contains(t), - i = n ? e !== !0 && "remove" : e !== !1 && "add";return i && this[i](t), e === !0 || e === !1 ? e : !n; - }, u.toString = function () { - return this.join(" "); - }, s.defineProperty) { - var f = { get: h, enumerable: !0, configurable: !0 };try { - s.defineProperty(i, e, f); - } catch (d) { - void 0 !== d.number && -2146823252 !== d.number || (f.enumerable = !1, s.defineProperty(i, e, f)); - } - } else s[n].__defineGetter__ && i.__defineGetter__(e, h); - } - }(self)); - -/***/ } - -/******/ }); \ No newline at end of file