diff --git a/test/js/component.js b/test/js/component.js index f8d667139..6021b85a9 100644 --- a/test/js/component.js +++ b/test/js/component.js @@ -1,68 +1,58 @@ -import Omi from '../../src/index.js'; +import Omi from '../../src/index.js' class Hello extends Omi.Component { constructor(data, renderTo) { - super(data, renderTo); - + super(data, renderTo) } - style () { - return ` - h1{ - color:red; - } - `; + style() { + return ` + h1 { + color: red; + } + ` } - onClick(){ - alert(1); + onClick() { + alert(1) } render() { - return `

Omi by {{name}}

`; - + return `

Omi by {{name}}

` } } -var hello = Omi.render(new Hello({ name:'dntzhang'}),'body'); - -describe("A suite is just a function", function() { - +var hello = Omi.render(new Hello({ name: 'dntzhang'}), 'body') +describe('A suite is just a function', function() { var result = hello.node.outerHTML - it("hello omi", function() { - expect(result).toBe('

Omi by dntzhang

'); - }); -}); + it('hello omi', function() { + expect(result).toBe('

Omi by dntzhang

') + }) +}) -describe("Omi.mixIndex ", function() { +describe('Omi.mixIndex ', function() { + var items = [1, 2] + Omi.mixIndex(items) + it('Omi.mixIndex', function() { + expect(JSON.stringify(items)).toBe('[{"value":1,"index":0},{"value":2,"index":1}]') + }) - var items = [1,2] - Omi.mixIndex(items); - it("Omi.mixIndex", function() { - expect(JSON.stringify(items)).toBe('[{"value":1,"index":0},{"value":2,"index":1}]'); - }); + var items2 = [{a: 1}, {b: 2}] + Omi.mixIndex(items2) + it('Omi.mixIndex', function() { + expect(JSON.stringify(items2)).toBe('[{"a":1,"index":0},{"b":2,"index":1}]') + }) - var items2 = [{a:1},{b:2}]; - Omi.mixIndex(items2); - it("Omi.mixIndex", function() { - expect(JSON.stringify(items2)).toBe('[{"a":1,"index":0},{"b":2,"index":1}]'); - }); + var items3 = [{a: 1}, {b: 2}] + Omi.mixIndex(items3, 'myIndex') + it('Omi.mixIndex', function() { + expect(JSON.stringify(items3)).toBe('[{"a":1,"myIndex":0},{"b":2,"myIndex":1}]') + }) +}) - var items3 = [{a:1},{b:2}]; - Omi.mixIndex(items3,"myIndex"); - it("Omi.mixIndex", function() { - expect(JSON.stringify(items3)).toBe('[{"a":1,"myIndex":0},{"b":2,"myIndex":1}]'); - }); -}); +describe('_getDataset ', function() { + hello._dataset = {} + hello._getDataset('
') - - - - - -describe("_getDataset ", function() { - hello._dataset = {}; - hello._getDataset('
'); - - it("_getDataset", function() { - expect(hello._dataset.a).toBe('a'); - }); -}); \ No newline at end of file + it('_getDataset', function() { + expect(hello._dataset.a).toBe('a') + }) +}) diff --git a/test/js/event.js b/test/js/event.js index 531007ce6..16b97e01d 100644 --- a/test/js/event.js +++ b/test/js/event.js @@ -1,55 +1,49 @@ -import scopedEvent from '../../src/event.js'; +import scopedEvent from '../../src/event.js' -describe("scopedEvent", function() { - var result2 = scopedEvent("
sfsdf
",1); - var result3 = scopedEvent("
sfsdf
",1); - var result = scopedEvent("
sfsdf
",1); - it("and so is a spec", function() { - expect(result).toBe("
sfsdf
"); - expect( scopedEvent(result)).toBe("
sfsdf
"); - expect(result2).toBe("
sfsdf
"); - expect(result3).toBe("
sfsdf
"); - }); -}); +describe('scopedEvent', function() { + var result2 = scopedEvent("
sfsdf
", 1) + var result3 = scopedEvent("
sfsdf
", 1) + var result = scopedEvent("
sfsdf
", 1) + it('and so is a spec', function() { + expect(result).toBe("
sfsdf
") + expect(scopedEvent(result)).toBe("
sfsdf
") + expect(result2).toBe("
sfsdf
") + expect(result3).toBe("
sfsdf
") + }) +}) -describe("scopedEvent2", function() { +describe('scopedEvent2', function() { + var result = scopedEvent("
sfsdf
", 1) + it('and so is a spec', function() { + expect(result).toBe("
sfsdf
") + }) +}) - var result = scopedEvent("
sfsdf
",1); - it("and so is a spec", function() { - expect(result).toBe("
sfsdf
"); +describe('scopedEvent3', function() { + var result = scopedEvent("
sfsdf
", 1) + it('and so is a spec', function() { + expect(result).toBe("
sfsdf
") + }) +}) - }); -}); - -describe("scopedEvent3", function() { - - var result = scopedEvent("
sfsdf
",1); - it("and so is a spec", function() { - expect(result).toBe("
sfsdf
"); - - }); -}); - -describe("scopedEvent4", function() { - - var result = scopedEvent("
sfsdf
",1); - it("and so is a spec", function() { - expect(result).toBe("
sfsdf
"); - - }); -}); -//describe("jsx-like event binding", function() { +describe('scopedEvent4', function() { + var result = scopedEvent("
sfsdf
", 1) + it('and so is a spec', function() { + expect(result).toBe("
sfsdf
") + }) +}) +// describe("jsx-like event binding", function() { // // var result = scopedEvent("
sfsdf
",1); // it("and so is a spec", function() { // expect(result).toBe(`
sfsdf
`); // }); -//}); +// }); // -//describe("jsx-like event binding with quote", function() { +// describe("jsx-like event binding with quote", function() { // // var result = scopedEvent('
sfsdf
',1); // it("and so is a spec", function() { // expect(result).toBe(`
sfsdf
`); // }); -//}); +// }); diff --git a/test/js/hello.js b/test/js/hello.js index 0f43d91b5..f187d2c42 100644 --- a/test/js/hello.js +++ b/test/js/hello.js @@ -1,12 +1,10 @@ +describe('A suite is just a function', function() { + var a -describe("A suite is just a function", function() { - var a; + it('and so is a spec', function() { + a = true - it("and so is a spec", function() { - a = true; - - expect(a).toBe(true); - }); -}); - \ No newline at end of file + expect(a).toBe(true) + }) +}) diff --git a/test/js/slot.js b/test/js/slot.js index 09ab544c1..7bd577de0 100644 --- a/test/js/slot.js +++ b/test/js/slot.js @@ -1,77 +1,59 @@ -import Omi from '../../src/index.js'; +import Omi from '../../src/index.js' class Hello extends Omi.Component { - render() { - return `
abc
`; - + return `
abc
` } } - class Test extends Omi.Component { - render() { - return `
efg
`; - + return `
efg
` } } -Omi.tag('Test',Test) -var hello = Omi.render(new Hello(),'body'); - -describe("slot1", function() { - +Omi.tag('Test', Test) +var hello = Omi.render(new Hello(), 'body') +describe('slot1', function() { var result = hello.node.outerHTML - it("hello omi", function() { - expect(result).toBe(`
abc
efg
`); - }); -}); - + it('hello omi', function() { + expect(result).toBe(`
abc
efg
`) + }) +}) class Hello2 extends Omi.Component { - render() { - return `
+ return `
abc
efg
-
`; - +
` } } - class Test2 extends Omi.Component { - render() { - return `
+ return `
-
`; - +
` } } -Omi.tag('Test2',Test2) +Omi.tag('Test2', Test2) - - - -describe("slot2", function() { - - - var hello2 = Omi.render(new Hello2(),'body'); +describe('slot2', function() { + var hello2 = Omi.render(new Hello2(), 'body') var result2 = hello2.node.outerHTML - it("hello omi", function() { + it('hello omi', function() { expect(result2).toBe(`
efg
abc
-
`); - }); -}); + `) + }) +}) diff --git a/test/js/style.js b/test/js/style.js index 15d1459b5..1b4667a08 100644 --- a/test/js/style.js +++ b/test/js/style.js @@ -1,97 +1,97 @@ -import assert from 'assert'; -import style from '../../src/style.js'; +import assert from 'assert' +import style from '../../src/style.js' -describe("scoper", function() { - describe("Attribute selector as prefix", function() { - var result = style.scoper(".active{ color:red};","[attribute]"); - it("expect attribute selector prefix works well", function() { - expect(result).toBe(".active[attribute],[attribute] .active{ color:red};"); - }); - }); +describe('scoper', function() { + describe('Attribute selector as prefix', function() { + var result = style.scoper('.active{ color:red};', '[attribute]') + it('expect attribute selector prefix works well', function() { + expect(result).toBe('.active[attribute],[attribute] .active{ color:red};') + }) + }) - describe("Id selector as prefix", function() { - var result = style.scoper(".active{ color:red};","#id"); - it("expect id selector prefix works well", function() { - expect(result).toBe(".active#id,#id .active{ color:red};"); - }); - }); + describe('Id selector as prefix', function() { + var result = style.scoper('.active{ color:red};', '#id') + it('expect id selector prefix works well', function() { + expect(result).toBe('.active#id,#id .active{ color:red};') + }) + }) - describe("Two classes", function() { - var result = style.scoper(".active,.xx{ color:red};","#id"); - it("expect id selector prefix works well with two class selector", function() { - expect(result).toBe(".active#id,#id .active,.xx#id,#id .xx{ color:red};"); - }); - }); + describe('Two classes', function() { + var result = style.scoper('.active,.xx{ color:red};', '#id') + it('expect id selector prefix works well with two class selector', function() { + expect(result).toBe('.active#id,#id .active,.xx#id,#id .xx{ color:red};') + }) + }) - describe("Pseudo class", function() { - var result = style.scoper(".active:hover{ color:red};","[attribute]"); - it("expect pseudo class works well", function() { - expect(result).toBe(".active[attribute]:hover,[attribute] .active:hover{ color:red};"); - }); - }); + describe('Pseudo class', function() { + var result = style.scoper('.active:hover{ color:red};', '[attribute]') + it('expect pseudo class works well', function() { + expect(result).toBe('.active[attribute]:hover,[attribute] .active:hover{ color:red};') + }) + }) - describe("Pseudo element", function() { - var result = style.scoper(".active::after{ color:red};","[attribute]"); - it("expect pseudo element works well", function() { - expect(result).toBe(".active[attribute]::after,[attribute] .active::after{ color:red};"); - }); - }); + describe('Pseudo element', function() { + var result = style.scoper('.active::after{ color:red};', '[attribute]') + it('expect pseudo element works well', function() { + expect(result).toBe('.active[attribute]::after,[attribute] .active::after{ color:red};') + }) + }) - describe("Quoted values", function() { - var result = style.scoper(".active { font-family: \"Helvetica Neue\"};","[attribute]"); - it("expect quoted values works well", function() { - expect(result).toBe(".active[attribute],[attribute] .active{ font-family: \"Helvetica Neue\"};"); - }); - }); + describe('Quoted values', function() { + var result = style.scoper('.active { font-family: "Helvetica Neue"};', '[attribute]') + it('expect quoted values works well', function() { + expect(result).toBe('.active[attribute],[attribute] .active{ font-family: "Helvetica Neue"};') + }) + }) - describe("Base64 values", function() { - var result = style.scoper(".watch i, .watchaa ,p:lang(it){background-image: url(data:image/png;base64,iVBORw0C);}.watch i, .watchaa ,p:lang(it){background-image: url(data:image/png;base64,iVBORw0C);}",'#xx'); - it("expect quoted values works well", function() { - expect(result).toBe(".watch i#xx,#xx .watch i, .watchaa#xx,#xx .watchaa,p#xx:lang(it),#xx p:lang(it){background-image: url(data:image/png;base64,iVBORw0C);}.watch i#xx,#xx .watch i, .watchaa#xx,#xx .watchaa,p#xx:lang(it),#xx p:lang(it){background-image: url(data:image/png;base64,iVBORw0C);}"); - }); - }); + describe('Base64 values', function() { + var result = style.scoper('.watch i, .watchaa ,p:lang(it){background-image: url(data:image/png;base64,iVBORw0C);}.watch i, .watchaa ,p:lang(it){background-image: url(data:image/png;base64,iVBORw0C);}', '#xx') + it('expect quoted values works well', function() { + expect(result).toBe('.watch i#xx,#xx .watch i, .watchaa#xx,#xx .watchaa,p#xx:lang(it),#xx p:lang(it){background-image: url(data:image/png;base64,iVBORw0C);}.watch i#xx,#xx .watch i, .watchaa#xx,#xx .watchaa,p#xx:lang(it),#xx p:lang(it){background-image: url(data:image/png;base64,iVBORw0C);}') + }) + }) - describe("Media queries", function() { - var rule = "@media (max-width: 600px) {\n" + - " h1 {\n" + - " font-family: \"Helvetica Neue\", Helvetica, Arial, sans-serif;\n" + - " }" + - "}"; - var expected = "@media (max-width: 600px) {\n" + - " h1#scoper-1,#scoper-1 h1{\n" + - " font-family: \"Helvetica Neue\", Helvetica, Arial, sans-serif;\n" + - " }" + - "}"; - var actual = style.scoper(rule, "#scoper-1"); - it("expect media queries works well", function() { - expect(actual).toBe(expected); - }); - }); + describe('Media queries', function() { + var rule = '@media (max-width: 600px) {\n' + + ' h1 {\n' + + ' font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;\n' + + ' }' + + '}' + var expected = '@media (max-width: 600px) {\n' + + ' h1#scoper-1,#scoper-1 h1{\n' + + ' font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;\n' + + ' }' + + '}' + var actual = style.scoper(rule, '#scoper-1') + it('expect media queries works well', function() { + expect(actual).toBe(expected) + }) + }) - describe("Font faces", function() { - var rule = "@font-face {\n" + + describe('Font faces', function() { + var rule = '@font-face {\n' + " font-family: 'MyWebFont';\n" + " src: url('myfont.woff2') format('woff2');\n" + " url('myfont.woff') format('woff');\n" + - "}"; - var expected = rule; - var actual = style.scoper(rule, "#scoper-1"); - it("expect font faces works well", function() { - expect(actual).toBe(expected); - }); - }); + '}' + var expected = rule + var actual = style.scoper(rule, '#scoper-1') + it('expect font faces works well', function() { + expect(actual).toBe(expected) + }) + }) - describe("Comment", function() { - var rule = "/* .item:nth-child(odd) {float: left;}*/"; - var expected = ''; - var actual = style.scoper(rule, "#scoper-1"); - it("expect comment works well", function() { - expect(actual).toBe(expected); - }); - }); + describe('Comment', function() { + var rule = '/* .item:nth-child(odd) {float: left;}*/' + var expected = '' + var actual = style.scoper(rule, '#scoper-1') + it('expect comment works well', function() { + expect(actual).toBe(expected) + }) + }) - describe("complex test", function() { - var rule= `.clearfix{*zoom:1;}.clearfix:before,.clearfix:after{display:table;content:"";line-height:0;} + describe('complex test', function() { + var rule = `.clearfix{*zoom:1;}.clearfix:before,.clearfix:after{display:table;content:"";line-height:0;} .clearfix:after{clear:both;} .nick { @@ -140,11 +140,10 @@ font-family:proxima-nova,"Helvetica Neue",Helvetica,Roboto,PT Sans,DejaVu Sans,A vertical-align: top; -webkit-transform: scale(.5, .5); transform: scale(.5, .5); -}`; - var actual = style.scoper(rule, "#cc"); - it("expect complex test works well", function() { - expect(actual).toBe(expected); - }); - }); - -}); +}` + var actual = style.scoper(rule, '#cc') + it('expect complex test works well', function() { + expect(actual).toBe(expected) + }) + }) +}) diff --git a/test/karma.conf.js b/test/karma.conf.js index aea21a6c1..dc8dc2bfa 100644 --- a/test/karma.conf.js +++ b/test/karma.conf.js @@ -1,82 +1,70 @@ // Karma configuration // Generated on Tue Jan 03 2017 10:33:15 GMT+0800 (中国标准时间) -var webpackConfig = require('./webpack.test.config'); +var webpackConfig = require('./webpack.test.config') module.exports = function(config) { - config.set({ + config.set({ + // base path that will be used to resolve all patterns (eg. files, exclude) + basePath: '', - // base path that will be used to resolve all patterns (eg. files, exclude) - basePath: '', + // frameworks to use + // available frameworks: https://npmjs.org/browse/keyword/karma-adapter + frameworks: ['jasmine'], + // list of files / patterns to load in the browser + files: [ + 'js/*.js' + ], - // frameworks to use - // available frameworks: https://npmjs.org/browse/keyword/karma-adapter - frameworks: ['jasmine'], + // list of files to exclude + exclude: [ + ], + // preprocess matching files before serving them to the browser + // available preprocessors: https://npmjs.org/browse/keyword/karma-preprocessor + preprocessors: { + 'js/*.js': ['webpack'] + }, - // list of files / patterns to load in the browser - files: [ - 'js/*.js' - ], + // test results reporter to use + // possible values: 'dots', 'progress' + // available reporters: https://npmjs.org/browse/keyword/karma-reporter + reporters: ['progress'], + // web server port + port: 9876, - // list of files to exclude - exclude: [ - ], + // enable / disable colors in the output (reporters and logs) + colors: true, + // level of logging + // possible values: config.LOG_DISABLE || config.LOG_ERROR || config.LOG_WARN || config.LOG_INFO || config.LOG_DEBUG + logLevel: config.LOG_INFO, - // preprocess matching files before serving them to the browser - // available preprocessors: https://npmjs.org/browse/keyword/karma-preprocessor - preprocessors: { - 'js/*.js':['webpack'] - }, + // enable / disable watching file and executing tests whenever any file changes + autoWatch: true, + // start these browsers + // available browser launchers: https://npmjs.org/browse/keyword/karma-launcher + browsers: ['Chrome'], - // test results reporter to use - // possible values: 'dots', 'progress' - // available reporters: https://npmjs.org/browse/keyword/karma-reporter - reporters: ['progress'], + // Continuous Integration mode + // if true, Karma captures browsers, runs the tests and exits + singleRun: true, + // Concurrency level + // how many browser should be started simultaneous + concurrency: Infinity, - // web server port - port: 9876, - - - // enable / disable colors in the output (reporters and logs) - colors: true, - - - // level of logging - // possible values: config.LOG_DISABLE || config.LOG_ERROR || config.LOG_WARN || config.LOG_INFO || config.LOG_DEBUG - logLevel: config.LOG_INFO, - - - // enable / disable watching file and executing tests whenever any file changes - autoWatch: true, - - - // start these browsers - // available browser launchers: https://npmjs.org/browse/keyword/karma-launcher - browsers: ['Chrome'], - - - // Continuous Integration mode - // if true, Karma captures browsers, runs the tests and exits - singleRun: true, - - // Concurrency level - // how many browser should be started simultaneous - concurrency: Infinity, - - webpack: webpackConfig, - webpackMiddleware:{ - noInfo:false - }, - plugins: [ - 'karma-webpack', - 'karma-jasmine', - 'karma-chrome-launcher' - ] - }) + webpack: webpackConfig, + webpackMiddleware: { + noInfo: false + }, + plugins: [ + 'karma-webpack', + 'karma-jasmine', + 'karma-chrome-launcher' + ] + }) } diff --git a/test/webpack.test.config.js b/test/webpack.test.config.js index 8969e1a26..07bc8982f 100644 --- a/test/webpack.test.config.js +++ b/test/webpack.test.config.js @@ -1,13 +1,11 @@ -var path = require('path'); -var webpack = require('webpack'); -module.exports={ - module:{ - loaders:[{ - test:/\.js$/, - loader:'babel', - query:{ - presets:['es2015'] +module.exports = { + module: { + loaders: [{ + test: /\.js$/, + loader: 'babel', + query: { + presets: ['es2015'] } }] } -}; \ No newline at end of file +} diff --git a/tutorial/js-expression.md b/tutorial/js-expression.md index 740145b2b..1bf072064 100644 --- a/tutorial/js-expression.md +++ b/tutorial/js-expression.md @@ -1,10 +1,10 @@ ## 写在前面 -[Omi框架](https://github.com/AlloyTeam/omi)可以通过在组件上声明 data-* 把属性传递给子节点。 +[Omi框架](https://github.com/AlloyTeam/omi)可以通过在组件上声明`data-*`把属性传递给子节点。 Omi从设计之初,就是往标准的DOM标签的标准传递方式靠齐。比如: -* 下划线自动转驼峰, data-page-index传到子组件就变成this.data.pageIndex -* data-xx 传递到子节点全都变成字符串,如data-page-index="1"到子节点中this.data.pageIndex就是字符串"1" +* 下划线自动转驼峰,`data-page-index`传到子组件就变成 `this.data.pageIndex` +* `data-xx` 传递到子节点全都变成字符串,如`data-page-index="1"`到子节点中`this.data.pageIndex`就是字符串"1" 这样会有什么局限性和问题?如: @@ -14,7 +14,7 @@ Omi从设计之初,就是往标准的DOM标签的标准传递方式靠齐。 那么支持传递javascript表达式就能解决这些痛点。 -废话不多说,来看神器的冒号。 +废话不多说,来看神奇的冒号。 ## 冒号标记 @@ -23,73 +23,71 @@ Omi从设计之初,就是往标准的DOM标签的标准传递方式靠齐。 ```js import Hello from 'hello.js' -Omi.tag('hello', Hello); +Omi.tag('hello', Hello) class App extends Omi.Component { - render() { - return ` -
- -
+ return ` +
+ +
` - } } Omi.render(new App(),"#container") ``` -在data-user前面加上冒号即:data-user,就代表传递的是js 表达式,够方便吧。 +在`data-user`前面加上冒号即`:data-user`,就代表传递的是js表达式,够方便吧。 然后在Hello组件内就可以直接使用。 ```js class Hello extends Omi.Component { - render() { - return ` -
-

{{user.name}} love {{user.favorite}}.

-
- ` + return ` +
+

{{user.name}} love {{user.favorite}}.

+
+ ` } } ``` -你也可以在hello组件内打印出 this.data.user 试试。 +你也可以在hello组件内打印出`this.data.user`试试。 ## 传递其他类型 上面的例子展示了传递JSON,其他类型也支持。比如: -```js - +```html + ``` -```js - +```html + ``` -```js - +```html + ``` -```js - +```html + ``` 当然也支持传递多个值: -```js - +```html + ``` 当然你也可以使用:data合并到一起: -```js - ``` @@ -99,56 +97,51 @@ class Hello extends Omi.Component { ```js class Hello extends Omi.Component { - - handleClick(evt){ - alert( this.data.arrayTest[0].name) + handleClick(evt) { + alert(this.data.arrayTest[0].name) } - - render() { - return ` - - `; - } -} - -Omi.tag('hello', Hello); - -class App extends Omi.Component { - render() { return ` -
- -
- `; - + + ` } } -Omi.render(new App(),"#container"); +Omi.tag('hello', Hello) + +class App extends Omi.Component { + render() { + return ` +
+ +
+ ` + } +} + +Omi.render(new App(), "#container") ``` -当然,在子组件中,你也可以不使用 [mustache.js](https://github.com/janl/mustache.js)模板引擎的语法去遍历,使用ES6+的姿势去遍历。 + +当然,在子组件中,你也可以不使用[mustache.js](https://github.com/janl/mustache.js)模板引擎的语法去遍历,使用ES6+的姿势去遍历。 ```js class Hello extends Omi.Component { - render() { - return ` - - `; + return ` + + ` } } ``` + 这也是为什么omi提供了两个版本,omi.js和omi.lite.js的原因。omi.lite.js不包含 [mustache.js](https://github.com/janl/mustache.js)模板引擎。 ## 在线演示 diff --git a/tutorial/store.md b/tutorial/store.md index ada21b494..2c9a74af6 100644 --- a/tutorial/store.md +++ b/tutorial/store.md @@ -4,56 +4,57 @@ 当我们组件之间,拥有共享的数据的时候,经常需要进行组件通讯。在Omi框架里,父组件传递数据给子组件非常方便: -* 通过在组件上声明 data-* 或者 :data-* 传递给子节点 -* 通过在组件上声明 data 或者 :data 传递给子节点 (支持复杂数据类型的映射) -* 声明 group-data 把数组里的data传给一堆组件传递(支持复杂数据类型的映射) +* 通过在组件上声明 `data-*` 或者 `:data-*` 传递给子节点 +* 通过在组件上声明 `data` 或者 `:data` 传递给子节点(支持复杂数据类型的映射) +* 声明 `group-data` 把数组里的data传给一堆组件传递(支持复杂数据类型的映射) -注:上面带有冒号的是[传递javascript表达式](https://github.com/AlloyTeam/omi/blob/master/tutorial/js-expression.md) +注:上面带有冒号的是[传递javascript表达式](js-expression.md) -通过声明onXxx="xxxx"可以让子组件内执行父组件的方法。具体的如下图所示: +通过声明 `onXxx="xxxx"` 可以让子组件内执行父组件的方法。具体的如下图所示: ![](http://images2015.cnblogs.com/blog/105416/201705/105416-20170509130200394-716974903.jpg) - 如果还不明白的话,那... 我就直接上代码了: ```js class Main extends Omi.Component { - - handlePageChange(index){ - this.content.goto(index+1) + handlePageChange(index) { + this.content.goto(index + 1) this.update() } render () { - return `
-

Pagination Example

- - -
`; + return ` +
+

Pagination Example

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

TODO

- - -
- - -
- -
`; + render() { + return ` +
+

TODO

+ + +
+ + +
+
+ ` } } export default Todo; ``` -为什么要去写beforeRender方法?因为render只会使用this.data去渲染页面而不会去使用this.$store.data,所以需要把数据转移到组件的this.data下。这样组件既能使用自身的data,也能使用全局放this.$store.data了,不会耦合在一起。 +为什么要去写`beforeRender`方法?因为render只会使用`this.data`去渲染页面而不会去使用`this.$store.data`,所以需要把数据转移到组件的`this.data`下。这样组件既能使用自身的data,也能使用全局放`this.$store.data`了,不会耦合在一起。 注意看上面的: ```js - install(){ + install() { this.$store.addView(this) } ``` -通过 addView 可以让 store 和 view(也就是组件的实例) 关联起来,以后store执行update方法的时候,关联的view都会自动更新! +通过 `addView` 可以让 store 和 view(也就是组件的实例)关联起来,以后store执行update方法的时候,关联的view都会自动更新! 再看上面的子组件声明: @@ -225,12 +227,12 @@ export default Todo; ``` -这样相当于把this.$store.data传递给了List组件。所以在List内部,就不再需要写beforeRender方法转换了。 +这样相当于把`this.$store.data`传递给了List组件。所以在List内部,就不再需要写`beforeRender`方法转换了。 ```js class List extends Omi.Component { - render () { - return ` ` + render() { + return `` } } ``` @@ -244,10 +246,10 @@ class List extends Omi.Component { ```js let todoStore = new TodoStore() -setTimeout(()=>{ - todoStore.data.items = ["omi","store"]; - todoStore.beReady(); -},2000) +setTimeout(() => { + todoStore.data.items = ["omi", "store"] + todoStore.beReady() +}, 2000) ``` 上面的beReady就是代码已经准备就绪,在组件内部可以监听ready方法: @@ -258,28 +260,26 @@ class Todo extends Omi.Component { super(data) } - install(){ + install() { this.$store.addView(this) } - installed(){ - this.$store.ready(()=>this.$store.update()) + installed() { + this.$store.ready(() => this.$store.update()) } - add (evt) { + add(evt) { evt.preventDefault() - if(!this.$store.isReady){ - return - } + if (!this.$store.isReady) return let value = this.data.text this.data.text = '' this.$store.add(value) } ``` -可以看到上面的add方法可以通过this.$store.isReady获取组件store是否准备就绪。 +可以看到上面的add方法可以通过`this.$store.isReady`获取组件store是否准备就绪。 -你可以通过Omi.createStore快捷创建store。如: +你可以通过`Omi.createStore`快捷创建store。如: ```js export default Omi.createStore({ @@ -287,12 +287,12 @@ export default Omi.createStore({ items: ["omi", "store"] }, methods: { - add: function (value) { + add: function(value) { this.data.items.push(value) this.update() }, - clear: function () { + clear: function() { this.data.items.length = 0 this.update() } @@ -300,7 +300,7 @@ export default Omi.createStore({ }) ``` -也支持省略Omi.createStore的形式创建store。如: +也支持省略`Omi.createStore`的形式创建store。如: ```js export default { @@ -308,14 +308,14 @@ export default { items: ["omi", "store"] }, methods: { - install:function(){ }, + install: function() {}, - add: function (value) { + add: function(value) { this.data.items.push(value) this.update() }, - clear: function () { + clear: function() { this.data.items.length = 0 this.update() }