脚本宝典收集整理的这篇文章主要介绍了

React+webpack+Antd从0到1开发一个todoMvc

脚本宝典小编觉得挺不错的,现在分享给大家,也给大家做个参考,希望能帮助你少写一行代码,多一份安全和惬意。
<p><code></p> <p>首先我们看一下我们完成后的最终形态:<a href="https://zegendary.github.io/react-demo/todoMvc/todoMvc-5step/" rel="nofollow noreferrer" target="_blank">TodoMvc</a>:</p> <p><span class="img-wrap"><img data-src="/img/remote/1460000008575278" src="/img/remote/1460000008575278" alt="TodoMVc" title="TodoMVc" style="cursor: pointer; display: inline;"></span></p> <p>学习必要条件:略懂<code><a href="http://www.js-code.com/tag/node" title="node" target="_blank">node</a>.js</code>,略懂<code>ES6</code>,然后你的电脑<strong>必须</strong>安装有较新版本<a href="https://nodejs.org/en/download/" rel="nofollow noreferrer" target="_blank">node</a>,没有的同学赶紧安装。<br />好了,废话不多说,直接开始。</p> <p>第一部分源码:<a href="https://github.com/Zegendary/react-demo/tree/master/todoMvc/todoMvc-1step" rel="nofollow noreferrer" target="_blank">todoMvc-1step</a></p> <h1 id="articleHeader0"> <a href="https://webpack.github.io/docs/what-is-webpack.html" rel="nofollow noreferrer" target="_blank">webpack</a>的配置</h1> <h4>1. 介绍:</h4> <p><a href="https://github.com/webpack/webpack" rel="nofollow noreferrer" target="_blank">Webpack</a>&nbsp;是当下最热门的前端资源模块化管理和打包工具。详细见官网</p> <h4>2. 安装:</h4> <div class="widget-codetool" style="display:none;"> <div class="widget-codetool--inner"> <span class="selectCode code-tool" data-toggle="tooltip" data-placement="top" title="" data-original-title="全选"></span><br /> <span type="button" class="copyCode code-tool" data-toggle="tooltip" data-placement="top" data-clipboard-text="$ npm install webpack -g" title="" data-original-title="复制"></span> </div> </p></div> <pre class="hljs sql"><code style="word-break: break-word; white-space: initial;">$ npm <span class="hljs-keyword"><a href="http://www.js-code.com/tag/in" title="浏览关于“in”的文章" target="_blank" class="tag_link">in</a>st<a href="http://www.js-code.com/tag/all" title="浏览关于“all”的文章" target="_blank" class="tag_link">all</a></span> webpack -g</code></pre> <p>此时 Webpack 已经安装到了全局环境下,可以通过命令行 webpack -h 试试。但通常我们会将 Webpack 以及相关依赖以这种方式安装,如下:</p> <div class="widget-codetool" style="display:none;"> <div class="widget-codetool--inner"> <span class="selectCode code-tool" data-toggle="tooltip" data-placement="top" title="" data-original-title="全选"></span><br /> <span type="button" class="copyCode code-tool" data-toggle="tooltip" data-placement="top" data-clipboard-text="# 进入项目目录 # 确定已经有 package.json,没有就通过 npm init 创建 # 安装 webpack 依赖 $ npm install webpack --save-dev # 安装react.js依赖(i是install的简写,-S是--save的简写) $ npm i react react-dom -S" title="" data-original-title="复制"></span> </div> </p></div> <pre class="hljs sql"><code><span class="hljs-comment"># 进入项目目录</span> <span class="hljs-comment"># 确定已经有 <a href="http://www.js-code.com/tag/package" title="浏览关于“package”的文章" target="_blank" class="tag_link">package</a>.json,没有就通过 npm init 创建</span> <span class="hljs-comment"># 安装 webpack 依赖</span> $ npm <span class="hljs-keyword">install</span> webpack <span class="hljs-comment">--save-dev</span> <span class="hljs-comment"># 安装react.js依赖(i是install的简写,-S是--save的简写)</span> $ npm i react react-<a href="http://www.js-code.com/tag/do" title="浏览关于“do”的文章" target="_blank" class="tag_link">do</a>m -S</code></pre> <p>剩余的依赖组件参照我源码中的<a href="http://www.js-code.com/tag/package" title="package" target="_blank">package</a>.json的依赖添加就好。最终,我们得到的<a href="http://www.js-code.com/tag/package" title="package" target="_blank">package</a>.json应该如下图:<span class="img-wrap"><img data-src="/img/remote/1460000008452599" src="https://static.segmentfault.com/v-5cc2cd8e/global/img/squares.svg" alt="package.json" title="package.json" style="cursor: pointer;"></span>确保红框中的内容一样即可。</p> <h4>3. 配置</h4> <p>现在我们已经安装好了依赖,下面我们需要先把项目的目录建好:</p> <div class="widget-codetool" style="display:none;"> <div class="widget-codetool--inner"> <span class="selectCode code-tool" data-toggle="tooltip" data-placement="top" title="" data-original-title="全选"></span><br /> <span type="button" class="copyCode code-tool" data-toggle="tooltip" data-placement="top" data-clipboard-text=". ├── node_modules # npm install 安装的东西都跑着里面来了 ├── src ├── components ├── app.js # react组件 ├── styles ├── main.styl # stylus文件(类似于sass) ├── entry.js # 入口js文件 ├── index.html # 入口页面 ├── package.json # 项目描述文件(内有相关依赖) └── webpack.config.js # webpack配置文件" title="" data-original-title="复制"></span> </div> </p></div> <pre class="hljs objectivec"><code>. ├── <a href="http://www.js-code.com/tag/node" title="浏览关于“node”的文章" target="_blank" class="tag_link">node</a>_modules <span class="hljs-meta"># npm install 安装的东西都跑着里面来了</span> ├── src ├── components ├── app.js <span class="hljs-meta"># react组件</span> ├── styles ├── main.styl <span class="hljs-meta"># stylus文件(类似于sass)</span> ├── en<a href="http://www.js-code.com/tag/try" title="浏览关于“try”的文章" target="_blank" class="tag_link">try</a>.js <span class="hljs-meta"># 入口js文件</span> ├── index.html <span class="hljs-meta"># 入口页面</span> ├── package.json <span class="hljs-meta"># 项目描述文件(内有相关依赖)</span> └── webpack.config.js <span class="hljs-meta"># webpack配置文件</span></code></pre> <p>然后我们在webpack.config.js中添加配置:</p> <div class="widget-codetool" style="display:none;"> <div class="widget-codetool--inner"> <span class="selectCode code-tool" data-toggle="tooltip" data-placement="top" title="" data-original-title="全选"></span><br /> <span type="button" class="copyCode code-tool" data-toggle="tooltip" data-placement="top" data-clipboard-text="module.exports = { entry: [ &quot;./src/entry.js&quot; ], output: { path: './out/', filename: &quot;bundle.js&quot; }, module: { loaders: [ { test: /.js[x]?$/, loader: &quot;babel-loader?presets[]=es2015&amp;presets[]=react&quot;, include: /src/}, { test: /.css$/, loader: &quot;style!css&quot;}, { test: /.styl$/, loader: &quot;style-loader!css-loader!stylus-loader&quot;}, { test: /.(png|jpg)$/, loader: 'url?limit=8192'} ] } }" title="" data-original-title="复制"></span> </div> </p></div> <pre class="hljs groovy"><code>module.<a href="http://www.js-code.com/tag/export" title="浏览关于“export”的文章" target="_blank" class="tag_link">export</a>s = { <span class="hljs-symbol"> entry:</span> [ <span class="hljs-string">"./src/entry.js"</span> ], <span class="hljs-symbol"> output:</span> { <span class="hljs-symbol"> path:</span> <span class="hljs-string">'./out/'</span>, <span class="hljs-symbol"> file<a href="http://www.js-code.com/tag/name" title="浏览关于“name”的文章" target="_blank" class="tag_link">name</a>:</span> <span class="hljs-string">"bundle.js"</span> }, <span class="hljs-symbol"> module:</span> { <span class="hljs-symbol"> loaders:</span> [ { <span class="hljs-string">test:</span> <span class="hljs-regexp">/.js[x]?$/</span>, <span class="hljs-string">loader:</span> <span class="hljs-string">"<a href="http://www.js-code.com/tag/babel" title="浏览关于“babel”的文章" target="_blank" class="tag_link">babel</a>-loader?p<a href="http://www.js-code.com/tag/reset" title="浏览关于“reset”的文章" target="_blank" class="tag_link">reset</a>s[]=es2015&amp;presets[]=react"</span>, <span class="hljs-string">include:</span> <span class="hljs-regexp">/src/</span>}, { <span class="hljs-string">test:</span> <span class="hljs-regexp">/.css$/</span>, <span class="hljs-string">loader:</span> <span class="hljs-string">"style!css"</span>}, { <span class="hljs-string">test:</span> <span class="hljs-regexp">/.styl$/</span>, <span class="hljs-string">loader:</span> <span class="hljs-string">"style-loader!css-loader!stylus-loader"</span>}, { <span class="hljs-string">test:</span> <span class="hljs-regexp">/.(png|jpg)$/</span>, <span class="hljs-string">loader:</span> <span class="hljs-string">'url?limit=8192'</span>} ] } }</code></pre> <p>配置文件将我们的入口文件<code>en<a href="http://www.js-code.com/tag/try" title="try" target="_blank">try</a>.js</code>打包输出到 <code>./out/bundle.js</code>,我们直接在页面<code><a href="http://www.js-code.com/tag/in" title="in" target="_blank">in</a>dex.html</code>中引入<code>bundle.js</code>就好了。</p> <div class="widget-codetool" style="display:none;"> <div class="widget-codetool--inner"> <span class="selectCode code-tool" data-toggle="tooltip" data-placement="top" title="" data-original-title="全选"></span><br /> <span type="<a href="http://www.js-code.com/tag/button" title="button" target="_blank">button</a>" <a href="http://www.js-code.com/tag/class" title="class" target="_blank">class</a>="copyCode code-tool" data-toggle="tooltip" data-placement="<a href="http://www.js-code.com/tag/top" title="top" target="_blank">top</a>" data-clipboard-<a href="http://www.js-code.com/tag/text" title="text" target="_blank">text</a>=" <script src=&quot;./out/bundle.js&quot;></script>" title="" data-original-title="复制"></span> </div> </p></div> <pre class="hljs xml"><code style="word-break: break-word; white-space: initial;"> <span class="hljs-tag">&lt;<span class="hljs-name">script</span> <span class="hljs-attr">src</span>=<span class="hljs-string">"./out/bundle.js"</span>&gt;</span><span class="undefined"></span><span class="hljs-tag">&lt;/<span class="hljs-name">script</span>&gt;</span></code></pre> <p>不懂得话可以参考webpack的文档:<a href="https://webpack.github.io/docs/usage.html" rel="nofollow noreferrer" target="_blank">webpack-usage</a> 和 <a href="https://webpack.github.io/docs/using-loaders.html" rel="nofollow noreferrer" target="_blank">webpack-loader</a>。关于<code>/src</code>目录下的文件内容可以直接到源码中查看。然后就可以小试牛刀啦,在终端中输入:</p> <div class="widget-codetool" style="display:none;"> <div class="widget-codetool--inner"> <span class="selectCode code-tool" data-toggle="tooltip" data-placement="top" title="" data-original-title="全选"></span><br /> <span type="button" class="copyCode code-tool" data-toggle="tooltip" data-placement="top" data-clipboard-text=" $ webpack" title="" data-original-title="复制"></span> </div> </p></div> <pre class="hljs ruby"><code style="word-break: break-word; white-space: initial;"> $ webpack</code></pre> <p>然后我们看到我们的目录下多了个<code>./out/bundle.js</code>文件,然后我们在浏览器打开目录下的<a href="http://www.js-code.com/tag/in" title="in" target="_blank">in</a>dex.html文件可以看到内容并<code><a href="http://www.js-code.com/tag/alert" title="alert" target="_blank">alert</a>('success')</code><span class="img-wrap"><img data-src="/img/remote/1460000008452600" src="https://static.segmentfault.com/v-5cc2cd8e/global/img/squares.svg" alt="todoMvc-step1" title="todoMvc-step1" style="cursor: pointer;"></span>那么恭喜你,第一步圆满完成!</p> <h1 id="articleHeader1"><a href="http://www.js-code.com/tag/react" title="React" target="_blank">React</a>如何<a href="http://www.js-code.com/tag/%e5%8f%8c%e5%90%91%e7%bb%91%e5%ae%9a" title="双向绑定" target="_blank">双向绑定</a></h1> <p><a href="https://github.com/Zegendary/react-demo/tree/master/todoMvc/todoMvc-2step" rel="nofollow noreferrer" target="_blank">todoMvc-2step源码</a> <br /><a href="https://zegendary.github.io/react-demo/todoMvc/todoMvc-2step/" rel="nofollow noreferrer" target="_blank">todoMvc-2step演示</a><br />上一章主要说了下react+webpack的环境搭建,这一章主要讲一下如何<a href="http://www.js-code.com/tag/%e5%8f%8c%e5%90%91%e7%bb%91%e5%ae%9a" title="双向绑定" target="_blank">双向绑定</a>。对vue和angular略有了解的都知道,这两个框架都是支持<a href="http://www.js-code.com/tag/%e5%8f%8c%e5%90%91%e7%bb%91%e5%ae%9a" title="浏览关于“双向绑定”的文章" target="_blank" class="tag_link">双向绑定</a>的,而react是单向绑定的,知乎有一篇关于单向绑定和双向绑定可以拓展一下:<a href="https://www.zhihu.com/question/49964363" rel="nofollow noreferrer" target="_blank">单向数据绑定和双向数据绑定的优缺点,适合什么场景</a>。下面分析如何具体实现:<br />进入我们的<code>app.js</code>文件,在之前我们搭建环境的时候已经安装了react相关的依赖以及<a href="http://www.js-code.com/tag/babel" title="babel" target="_blank">babel</a>编译工具,所以我们可以直接在这里使用<code>ES6</code>、<code><a href="http://www.js-code.com/tag/jsx" title="JSX" target="_blank">JSX</a></code>语法。</p> <h4>1. 引入react核心内容</h4> <div class="widget-codetool" style="display:none;"> <div class="widget-codetool--inner"> <span class="selectCode code-tool" data-toggle="tooltip" data-placement="top" title="" data-original-title="全选"></span><br /> <span type="button" class="copyCode code-tool" data-toggle="tooltip" data-placement="top" data-clipboard-text="import React from 'react' import ReactDOM from 'react-dom'" title="" data-original-title="复制"></span> </div> </p></div> <pre class="hljs typescript"><code><span class="hljs-keyword">import</span> <a href="http://www.js-code.com/tag/react" title="浏览关于“React”的文章" target="_blank" class="tag_link">React</a> <span class="hljs-keyword">from</span> <span class="hljs-string">'react'</span> <span class="hljs-keyword">import</span> React<a href="http://www.js-code.com/tag/dom" title="浏览关于“DOM”的文章" target="_blank" class="tag_link">DOM</a> <span class="hljs-keyword">from</span> <span class="hljs-string">'react-dom'</span></code></pre> <p>其中,react.js 是 <a href="http://www.js-code.com/tag/react" title="React" target="_blank">React</a> 的核心库,react-<a href="http://www.js-code.com/tag/do" title="do" target="_blank">do</a>m.js 是提供与 <a href="http://www.js-code.com/tag/dom" title="DOM" target="_blank">DOM</a> 相关的功能。</p> <h4>2. 生成组件</h4> <p>先介绍react三个比较重要的知识点:<br />1.React<a href="http://www.js-code.com/tag/dom" title="DOM" target="_blank">DOM</a>.render()<br /> ReactDOM.render 是 React 的最基本方法,用于将模板转为 <a href="http://www.js-code.com/tag/html" title="HTML" target="_blank">HTML</a> 语言,并插入指定的 DOM 节点。举个例子:</p> <div class="widget-codetool" style="display:none;"> <div class="widget-codetool--inner"> <span class="selectCode code-tool" data-toggle="tooltip" data-placement="top" title="" data-original-title="全选"></span><br /> <span type="<a href="http://www.js-code.com/tag/button" title="button" target="_blank">button</a>" <a href="http://www.js-code.com/tag/class" title="class" target="_blank">class</a>="copyCode code-tool" data-toggle="tooltip" data-placement="<a href="http://www.js-code.com/tag/top" title="top" target="_blank">top</a>" data-clipboard-<a href="http://www.js-code.com/tag/text" title="text" target="_blank">text</a>="ReactDOM.render(</p> <h1>Hello, world!</h1> <p>,<br /> document.getElementById('example')<br /> );" title="" data-original-title="复制"></span> </div> </p></div> <pre class="hljs javascript"><code>ReactDOM.render( <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">h1</span>&gt;</span>Hello, world!<span class="hljs-tag">&lt;/<span class="hljs-name">h1</span>&gt;</span></span>, <span class="hljs-built_in"><a href="http://www.js-code.com/tag/document" title="浏览关于“document”的文章" target="_blank" class="tag_link">document</a></span>.getElementById(<span class="hljs-string">'example'</span>) );</code></pre> <p>上面代码将一个 h1 标题,插入 example 节点。<br />2.<a href="http://www.js-code.com/tag/jsx" title="JSX" target="_blank">JSX</a> 语法<br /> <a href="http://www.js-code.com/tag/html" title="HTML" target="_blank">HTML</a> 语言直接写在 JavaScript 语言之中,不加任何引号,这就是&nbsp;<a href="http://facebook.github.io/react/docs/displaying-data.html#jsx-syntax" rel="nofollow noreferrer" target="_blank">JSX 的语法</a>,它允许 <a href="http://www.js-code.com/tag/html" title="浏览关于“HTML”的文章" target="_blank" class="tag_link">HTML</a> 与 JavaScript 的混写,上面的<code>&lt;h1&gt;Hello, world!&lt;/h1&gt;</code>,就是使用了jsx语法。<br />3.组件<br /> React 允许将代码封装成组件(component),然后像插入普通 HTML 标签一样,在网页中插入这个组件。React.create<a href="http://www.js-code.com/tag/class" title="Class" target="_blank">Class</a> 方法就用于生成一个组件类。举个?:</p> <div class="widget-codetool" style="display:none;"> <div class="widget-codetool--inner"> <span class="selectCode code-tool" data-toggle="tooltip" data-placement="top" title="" data-original-title="全选"></span><br /> <span type="<a href="http://www.js-code.com/tag/button" title="浏览关于“button”的文章" target="_blank" class="tag_link">button</a>" class="copyCode code-tool" data-toggle="tooltip" data-placement="<a href="http://www.js-code.com/tag/top" title="浏览关于“top”的文章" target="_blank" class="tag_link">top</a>" data-clipboard-<a href="http://www.js-code.com/tag/text" title="浏览关于“text”的文章" target="_blank" class="tag_link">text</a>="//<a href="http://www.js-code.com/tag/es5" title="es5" target="_blank">es5</a>写法<br /> <a href="http://www.js-code.com/tag/var" title="var" target="_blank">var</a> HelloMessage = React.create<a href="http://www.js-code.com/tag/class" title="Class" target="_blank">Class</a>({<br /> render: <a href="http://www.js-code.com/tag/function" title="function" target="_blank">function</a>() {<br /> <a href="http://www.js-code.com/tag/return" title="return" target="_blank">return</a> </p> <h1>Hello React</h1> <p>;<br /> }<br /> });<br /> //<a href="http://www.js-code.com/tag/es6" title="es6" target="_blank">es6</a>写法<br /> <a href="http://www.js-code.com/tag/class" title="浏览关于“Class”的文章" target="_blank" class="tag_link">Class</a> HelloMessage <a href="http://www.js-code.com/tag/extends" title="extends" target="_blank">extends</a> React.Component {<br /> render() {<br /> <a href="http://www.js-code.com/tag/return" title="return" target="_blank">return</a> </p> <h1>Hello, React</hr> <p>;<br /> }<br /> }" title="" data-original-title="复制"></span> </div> </p></div> <pre class="hljs javascript"><code><span class="hljs-comment">//<a href="http://www.js-code.com/tag/es5" title="浏览关于“es5”的文章" target="_blank" class="tag_link">es5</a>写法</span> <span class="hljs-keyword"><a href="http://www.js-code.com/tag/var" title="浏览关于“var”的文章" target="_blank" class="tag_link">var</a></span> HelloMessage = React.createClass({ <span class="hljs-attr">render</span>: <span class="hljs-function"><span class="hljs-keyword"><a href="http://www.js-code.com/tag/function" title="浏览关于“function”的文章" target="_blank" class="tag_link">function</a></span>(<span class="hljs-params"></span>) </span>{ <span class="hljs-keyword"><a href="http://www.js-code.com/tag/return" title="浏览关于“return”的文章" target="_blank" class="tag_link">return</a></span> <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">h1</span>&gt;</span>Hello React<span class="hljs-tag">&lt;/<span class="hljs-name">h1</span>&gt;</span></span>; } }); <span class="hljs-comment">//<a href="http://www.js-code.com/tag/es6" title="浏览关于“es6”的文章" target="_blank" class="tag_link">es6</a>写法</span> Class HelloMessage <a href="http://www.js-code.com/tag/extends" title="浏览关于“extends”的文章" target="_blank" class="tag_link">extends</a> React.Component { render() { <span class="hljs-keyword">return</span> <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">h1</span>&gt;</span>Hello, React<span class="hljs-tag">&lt;/<span class="hljs-name">hr</span>&gt;</span></span>; } }</code></pre> <p>当然,这里的<code>HelloMessage</code>我们也可以当做HTML标签用<code>ReactDOM.render()</code>渲染出来。</p> <p><code>app.js</code>:</p> <div class="widget-codetool" style="display:none;"> <div class="widget-codetool--inner"> <span class="selectCode code-tool" data-toggle="tooltip" data-placement="top" title="" data-original-title="全选"></span><br /> <span type="button" class="copyCode code-tool" data-toggle="tooltip" data-placement="top" data-clipboard-text="class App <a href="http://www.js-code.com/tag/extends" title="extends" target="_blank">extends</a> React.Component { //定义组件,继承父类<br /> <a href="http://www.js-code.com/tag/const" title="const" target="_blank">const</a>ructor() {//<a href="http://www.js-code.com/tag/const" title="const" target="_blank">const</a>ructor 是和 class 一起用来创建和初始化对象的特殊方法。<br /> <a href="http://www.js-code.com/tag/super" title="super" target="_blank">super</a>()//在装载组件(mounting)之前调用会<a href="http://www.js-code.com/tag/react%e7%bb%84%e4%bb%b6" title="React组件" target="_blank">React组件</a>的构造函数。当实现React.Component子类的构造函数时,应该在任何其他语句之前调用<a href="http://www.js-code.com/tag/super" title="super" target="_blank">super</a>(props)<br /> <a href="http://www.js-code.com/tag/this" title="this" target="_blank">this</a>.state = {//设置初始状态<br /> to<a href="http://www.js-code.com/tag/do" title="do" target="_blank">do</a>s: []<br /> }<br /> }<br /> // 绑定键盘回车事件,添加新任务<br /> handlerKeyUp(e) {<br /> <a href="http://www.js-code.com/tag/if" title="if" target="_blank">if</a>(e.keyCode == 13) {<br /> <a href="http://www.js-code.com/tag/let" title="let" target="_blank">let</a> value = e.target.value;<br /> <a href="http://www.js-code.com/tag/if" title="if" target="_blank">if</a>(!value) <a href="http://www.js-code.com/tag/return" title="return" target="_blank">return</a> <a href="http://www.js-code.com/tag/false" title="false" target="_blank">false</a>;<br /> <a href="http://www.js-code.com/tag/let" title="let" target="_blank">let</a> <a href="http://www.js-code.com/tag/new" title="new" target="_blank">new</a>TodoItem = {<br /> text: value,<br /> isDone: <a href="http://www.js-code.com/tag/false" title="false" target="_blank">false</a><br /> };<br /> e.target.value = '';<br /> <a href="http://www.js-code.com/tag/this" title="this" target="_blank">this</a>.state.todos.push(<a href="http://www.js-code.com/tag/new" title="new" target="_blank">new</a>TodoItem)<br /> <a href="http://www.js-code.com/tag/this" title="this" target="_blank">this</a>.set<a href="http://www.js-code.com/tag/state" title="State" target="_blank">State</a>({todos: <a href="http://www.js-code.com/tag/this" title="this" target="_blank">this</a>.state.todos}); //修改状态值,每次修改以后,自动调用 <a href="http://www.js-code.com/tag/this" title="this" target="_blank">this</a>.render 方法,再次渲染组件。<br /> }<br /> }<br /> render(){<br /> <a href="http://www.js-code.com/tag/return" title="return" target="_blank">return</a> (</p> <div className=&quot;todo-input&quot;> <input type=&quot;text&quot; placeholder=&quot;请输入待办事项&quot; onKeyUp={this.handlerKeyUp.bind(this)}/></p> <ul> {this.state.todos.map((todo,index) => {{<br /> return (</p> <li key={index}>{todo.text}</li> <p>//Keys help React ident<a href="http://www.js-code.com/tag/if" title="浏览关于“if”的文章" target="_blank" class="tag_link">if</a>y which items have changed, are added, or are removed. Keys should be given to the <a href="http://www.js-code.com/tag/element" title="element" target="_blank">element</a>s inside the array to give the <a href="http://www.js-code.com/tag/elements" title="elements" target="_blank">elements</a> a stable identity<br /> )<br /> }})} </ul> </p></div> <p> )<br /> }<br /> }<br /> ReactDOM.render(<App></App>,document.getElementById('app'))<br /> " title="" data-original-title="复制"></span> </div> </p></div> <pre class="hljs scala"><code><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">App</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">React</span>.<span class="hljs-title">Component</span> </span>{ <span class="hljs-comment">//定义组件,继承父类</span> <a href="http://www.js-code.com/tag/constructor" title="浏览关于“constructor”的文章" target="_blank" class="tag_link">constructor</a>() {<span class="hljs-comment">//<a href="http://www.js-code.com/tag/const" title="浏览关于“const”的文章" target="_blank" class="tag_link">const</a>ructor 是和 class 一起用来创建和初始化对象的特殊方法。</span> <span class="hljs-keyword"><a href="http://www.js-code.com/tag/super" title="浏览关于“super”的文章" target="_blank" class="tag_link">super</a></span>()<span class="hljs-comment">//在装载组件(mounting)之前调用会<a href="http://www.js-code.com/tag/react%e7%bb%84%e4%bb%b6" title="浏览关于“React组件”的文章" target="_blank" class="tag_link">React组件</a>的构造函数。当实现React.Component子类的构造函数时,应该在任何其他语句之前调用super(props)</span> <span class="hljs-keyword"><a href="http://www.js-code.com/tag/this" title="浏览关于“this”的文章" target="_blank" class="tag_link">this</a></span>.state = {<span class="hljs-comment">//设置初始状态</span> todos: [] } } <span class="hljs-comment">// 绑定键盘回车事件,添加新任务</span> handlerKeyUp(e) { <span class="hljs-keyword">if</span>(e.keyCode == <span class="hljs-number">13</span>) { <a href="http://www.js-code.com/tag/let" title="浏览关于“let”的文章" target="_blank" class="tag_link">let</a> value = e.target.value; <span class="hljs-keyword">if</span>(!value) <span class="hljs-keyword">return</span> <span class="hljs-literal"><a href="http://www.js-code.com/tag/false" title="浏览关于“false”的文章" target="_blank" class="tag_link">false</a></span>; let <a href="http://www.js-code.com/tag/new" title="浏览关于“new”的文章" target="_blank" class="tag_link">new</a>TodoItem = { text: value, isDone: <span class="hljs-literal">false</span> }; e.target.value = ''; <span class="hljs-keyword">this</span>.state.todos.push(newTodoItem) <span class="hljs-keyword">this</span>.<a href="http://www.js-code.com/tag/setstate" title="浏览关于“setState”的文章" target="_blank" class="tag_link">setState</a>({todos: <span class="hljs-keyword">this</span>.state.todos}); <span class="hljs-comment">//修改状态值,每次修改以后,自动调用 this.render 方法,再次渲染组件。</span> } } render(){ <span class="hljs-keyword">return</span> ( &lt;<a href="http://www.js-code.com/tag/div" title="浏览关于“div”的文章" target="_blank" class="tag_link">div</a> className=<span class="hljs-string">"todo-input"</span>&gt; &lt;input <span class="hljs-class"><span class="hljs-keyword">type</span></span>=<span class="hljs-string">"text"</span> placeholder=<span class="hljs-string">"请输入待办事项"</span> onKeyUp={<span class="hljs-keyword">this</span>.handlerKeyUp.bind(<span class="hljs-keyword">this</span>)}/&gt; &lt;ul&gt; {<span class="hljs-keyword">this</span>.state.todos.map((todo,index) =&gt; {{ <span class="hljs-keyword">return</span> ( &lt;li key={index}&gt;{todo.text}&lt;/li&gt;<span class="hljs-comment">//Keys help React identify which items have changed, are added, or are removed. Keys should be given to the <a href="http://www.js-code.com/tag/elements" title="浏览关于“elements”的文章" target="_blank" class="tag_link">elements</a> inside the array to give the <a href="http://www.js-code.com/tag/element" title="浏览关于“element”的文章" target="_blank" class="tag_link">element</a>s a stable identity</span> ) }})} &lt;/ul&gt; &lt;/div&gt; ) } } <span class="hljs-type">ReactDOM</span>.render(&lt;<span class="hljs-type">App</span>/&gt;,document.getElementById(<span class="hljs-symbol">'ap</span>p')) </code></pre> <h4>3. 测试</h4> <p>运行</p> <div class="widget-codetool" style="display:none;"> <div class="widget-codetool--inner"> <span class="selectCode code-tool" data-toggle="tooltip" data-placement="top" title="" data-original-title="全选"></span><br /> <span type="button" class="copyCode code-tool" data-toggle="tooltip" data-placement="top" data-clipboard-text="$ webpack" title="" data-original-title="复制"></span> </div> </p></div> <pre class="hljs shell"><code style="word-break: break-word; white-space: initial;"><span class="hljs-meta">$</span><span class="bash"> webpack</span></code></pre> <p>然后打开<code>index.html</code>,如果可以在input输入,按下回车可以在下方生成list<span class="img-wrap"><img data-src="/img/remote/1460000008486187" src="https://static.segmentfault.com/v-5cc2cd8e/global/img/squares.svg" alt="成功画面" title="成功画面" style="cursor: pointer;"></span></p> <p>那么恭喜你,双向绑定功能完成!</p> <h1 id="articleHeader2">组件化</h1> <p><a href="https://github.com/Zegendary/react-demo/tree/master/todoMvc/todoMvc-3step" rel="nofollow noreferrer" target="_blank">todoMvc-3step源码</a><br /><a href="https://zegendary.github.io/react-demo/todoMvc/todoMvc-3step/" rel="nofollow noreferrer" target="_blank">todoMvc-3step演示</a><br />上一章主要介绍了下React如何进行双向绑定以及如何生成一个组件,我们第三步的目标就是需要把之前做的内容抽象出更细的组件,这样便于解耦,各个组件各司其职,互不干扰。<br />先看下抽象后<code>src/components</code>下的目录</p> <p><span class="img-wrap"><img data-src="/img/remote/1460000008575279" src="https://static.segmentfault.com/v-5cc2cd8e/global/img/squares.svg" alt="组件目录" title="组件目录" style="cursor: pointer;"></span></p> <p>先看下我们的<code>app.js</code>修改过后的内容:</p> <div class="widget-codetool" style="display:none;"> <div class="widget-codetool--inner"> <span class="selectCode code-tool" data-toggle="tooltip" data-placement="top" title="" data-original-title="全选"></span><br /> <span type="button" class="copyCode code-tool" data-toggle="tooltip" data-placement="top" data-clipboard-text="<a href="http://www.js-code.com/tag/import" title="import" target="_blank">import</a> React from 'react'<br /> <a href="http://www.js-code.com/tag/import" title="import" target="_blank">import</a> ReactDOM from 'react-dom'<br /> import TodoHeader from './TodoHeader' // 引入TodoHeader组件<br /> import TodoMain from './TodoMain' // 引入TodoMain组件</p> <p>class App extends React.Component { // 定义组件,继承父类<br /> <a href="http://www.js-code.com/tag/constructor" title="constructor" target="_blank">constructor</a>() {<br /> <a href="http://www.js-code.com/tag/super" title="super" target="_blank">super</a>()<br /> <a href="http://www.js-code.com/tag/this" title="this" target="_blank">this</a>.state = {<br /> todos: []<br /> }<br /> }<br /> addTodo(item) { // 新增了添加todo事项的方法<br /> this.state.todos.push(item)<br /> this.<a href="http://www.js-code.com/tag/setstate" title="setState" target="_blank">setState</a>({todos: this.state.todos}); //设置状态<br /> }<br /> render(){<br /> return (</p> <div className=&quot;todo-wrapper&quot;> // 将原内容写在组件中并引入进行渲染<br /> // 把addTodo方法传递到TodoHeader组件中,bind(this)是为了把该React实例绑定到this上<br /> <TodoHeader addTodo={this.addTodo.bind(this)}></TodoHeader><br /> // 把 state.todos 传入到TodoMain 中<br /> <TodoMain todos={this.state.todos}></TodoMain> </div> <p> )<br /> }<br /> }</p> <p>ReactDOM.render(<App></App>,document.getElementById('app'))" title="" data-original-title="复制"></span> </div> </p></div> <pre class="hljs scala"><code><span class="hljs-keyword">import</span> <span class="hljs-type">React</span> from <span class="hljs-symbol">'reac</span>t' <span class="hljs-keyword">import</span> <span class="hljs-type">ReactDOM</span> from <span class="hljs-symbol">'react</span>-dom' <span class="hljs-keyword">import</span> <span class="hljs-type">TodoHeader</span> from './<span class="hljs-type">TodoHeader</span>' <span class="hljs-comment">// 引入TodoHeader组件</span> <span class="hljs-keyword">import</span> <span class="hljs-type">TodoMain</span> from './<span class="hljs-type">TodoMain</span>' <span class="hljs-comment">// 引入TodoMain组件</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">App</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">React</span>.<span class="hljs-title">Component</span> </span>{ <span class="hljs-comment">// 定义组件,继承父类</span> constructor() { <span class="hljs-keyword">super</span>() <span class="hljs-keyword">this</span>.state = { todos: [] } } addTodo(item) { <span class="hljs-comment">// 新增了添加todo事项的方法</span> <span class="hljs-keyword">this</span>.state.todos.push(item) <span class="hljs-keyword">this</span>.set<a href="http://www.js-code.com/tag/state" title="浏览关于“State”的文章" target="_blank" class="tag_link">State</a>({todos: <span class="hljs-keyword">this</span>.state.todos}); <span class="hljs-comment">//设置状态</span> } render(){ <span class="hljs-keyword">return</span> ( &lt;div className=<span class="hljs-string">"todo-wrapper"</span>&gt; <span class="hljs-comment">// 将原内容写在组件中并引入进行渲染</span> <span class="hljs-comment">// 把addTodo方法传递到TodoHeader组件中,bind(this)是为了把该React实例绑定到this上</span> &lt;<span class="hljs-type">TodoHeader</span> addTodo={<span class="hljs-keyword">this</span>.addTodo.bind(<span class="hljs-keyword">this</span>)}/&gt; <span class="hljs-comment">// 把 state.todos 传入到TodoMain 中</span> &lt;<span class="hljs-type">TodoMain</span> todos={<span class="hljs-keyword">this</span>.state.todos}/&gt; &lt;/div&gt; ) } } <span class="hljs-type">ReactDOM</span>.render(&lt;<span class="hljs-type">App</span>/&gt;,document.getElementById(<span class="hljs-symbol">'ap</span>p'))</code></pre> <p><code>TodoHeader</code>:</p> <div class="widget-codetool" style="display:none;"> <div class="widget-codetool--inner"> <span class="selectCode code-tool" data-toggle="tooltip" data-placement="top" title="" data-original-title="全选"></span><br /> <span type="button" class="copyCode code-tool" data-toggle="tooltip" data-placement="top" data-clipboard-text="import React from 'react' class TodoHeader extends React.Component { // 绑定键盘回车事件,添加新任务 handlerKeyUp(e) { if(e.keyCode == 13) { // enter键的 keyCode 为13 <a href="http://www.js-code.com/tag/let" title="let" target="_blank">let</a> value = e.target.value;<br /> if(!value) return false;<br /> <a href="http://www.js-code.com/tag/let" title="let" target="_blank">let</a> newTodoItem = {<br /> text: value,<br /> isDone: false<br /> };<br /> e.target.value = '';<br /> this.props.addTodo(newTodoItem) // 通过 this.props 来调用父组件传递过来的addTodo方法<br /> }<br /> }<br /> render(){<br /> return (</p> <div className=&quot;todo-header&quot;> <input onKeyUp={this.handlerKeyUp.bind(this)} type=&quot;text&quot; placeholder=&quot;请输入你的任务名称,按回车键确认&quot;/> </div> <p> )<br /> }<br /> }<br /> export default TodoHeader // 将TodoHeader导出,否则父组件无法导入" title="" data-original-title="复制"></span> </div> </p></div> <pre class="hljs scala"><code><span class="hljs-keyword">import</span> <span class="hljs-type">React</span> from <span class="hljs-symbol">'reac</span>t' <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">TodoHeader</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">React</span>.<span class="hljs-title">Component</span> </span>{ <span class="hljs-comment">// 绑定键盘回车事件,添加新任务</span> handlerKeyUp(e) { <span class="hljs-keyword">if</span>(e.keyCode == <span class="hljs-number">13</span>) { <span class="hljs-comment">// enter键的 keyCode 为13</span> let value = e.target.value; <span class="hljs-keyword">if</span>(!value) <span class="hljs-keyword">return</span> <span class="hljs-literal">false</span>; let newTodoItem = { text: value, isDone: <span class="hljs-literal">false</span> }; e.target.value = ''; <span class="hljs-keyword">this</span>.props.addTodo(newTodoItem) <span class="hljs-comment">// 通过 this.props 来调用父组件传递过来的addTodo方法</span> } } render(){ <span class="hljs-keyword">return</span> ( &lt;div className=<span class="hljs-string">"todo-header"</span>&gt; &lt;input onKeyUp={<span class="hljs-keyword">this</span>.handlerKeyUp.bind(<span class="hljs-keyword">this</span>)} <span class="hljs-class"><span class="hljs-keyword">type</span></span>=<span class="hljs-string">"text"</span> placeholder=<span class="hljs-string">"请输入你的任务名称,按回车键确认"</span>/&gt; &lt;/div&gt; ) } } export <span class="hljs-keyword"><a href="http://www.js-code.com/tag/default" title="浏览关于“default”的文章" target="_blank" class="tag_link">default</a></span> <span class="hljs-type">TodoHeader</span> <span class="hljs-comment">// 将TodoHeader导出,否则父组件无法导入</span></code></pre> <p><code>TodoMain</code>修改后内容:</p> <div class="widget-codetool" style="display:none;"> <div class="widget-codetool--inner"> <span class="selectCode code-tool" data-toggle="tooltip" data-placement="top" title="" data-original-title="全选"></span><br /> <span type="button" class="copyCode code-tool" data-toggle="tooltip" data-placement="top" data-clipboard-text="import React from 'react' import TodoItem from './TodoItem' class TodoMain extends React.Component { render(){ if(this.props.todos.<a href="http://www.js-code.com/tag/length" title="length" target="_blank">length</a> == 0) {<br /> return (</p> <div className=&quot;todo-empty&quot;>恭喜您,目前没有待办任务</div> <p> )<br /> } <a href="http://www.js-code.com/tag/else" title="else" target="_blank">else</a> {<br /> return (</p> <ul className=&quot;todo-main&quot;> {<br /> this.props.todos.map((todo,index) => {<br /> //{...this.props} 用来传递TodoMain的todos属性和<a href="http://www.js-code.com/tag/delete" title="delete" target="_blank">delete</a>、change方法。<br /> return <TodoItem text={todo.text} isDone={todo.isDone} index={index} {...this.props} key={index}></TodoItem><br /> })<br /> } </ul> <p> )<br /> }<br /> }<br /> }<br /> export default TodoMain" title="" data-original-title="复制"></span> </div> </p></div> <pre class="hljs scala"><code><span class="hljs-keyword">import</span> <span class="hljs-type">React</span> from <span class="hljs-symbol">'reac</span>t' <span class="hljs-keyword">import</span> <span class="hljs-type">TodoItem</span> from './<span class="hljs-type">TodoItem</span>' <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">TodoMain</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">React</span>.<span class="hljs-title">Component</span> </span>{ render(){ <span class="hljs-keyword">if</span>(<span class="hljs-keyword">this</span>.props.todos.<a href="http://www.js-code.com/tag/length" title="浏览关于“length”的文章" target="_blank" class="tag_link">length</a> == <span class="hljs-number">0</span>) { <span class="hljs-keyword">return</span> ( &lt;div className=<span class="hljs-string">"todo-empty"</span>&gt;恭喜您,目前没有待办任务&lt;/div&gt; ) } <span class="hljs-keyword"><a href="http://www.js-code.com/tag/else" title="浏览关于“else”的文章" target="_blank" class="tag_link">else</a></span> { <span class="hljs-keyword">return</span> ( &lt;ul className=<span class="hljs-string">"todo-main"</span>&gt; { <span class="hljs-keyword">this</span>.props.todos.map((todo,index) =&gt; { <span class="hljs-comment">//{...this.props} 用来传递TodoMain的todos属性和<a href="http://www.js-code.com/tag/delete" title="浏览关于“delete”的文章" target="_blank" class="tag_link">delete</a>、change方法。</span> <span class="hljs-keyword">return</span> &lt;<span class="hljs-type">TodoItem</span> text={todo.text} isDone={todo.isDone} index={index} {...<span class="hljs-keyword">this</span>.props} key={index}/&gt; }) } &lt;/ul&gt; ) } } } export <span class="hljs-keyword">default</span> <span class="hljs-type">TodoMain</span></code></pre> <p><code>TodoItem</code>:</p> <div class="widget-codetool" style="display:none;"> <div class="widget-codetool--inner"> <span class="selectCode code-tool" data-toggle="tooltip" data-placement="top" title="" data-original-title="全选"></span><br /> <span type="button" class="copyCode code-tool" data-toggle="tooltip" data-placement="top" data-clipboard-text="import React from 'react' class TodoItem extends React.Component { render() { let className = this.props.isDone?'task-done':'' return ( <li> <label><br /> <input type=&quot;checkbox&quot;/><br /> <span className={className}>{this.props.text}</span><br /> </label> </li> <p> )<br /> }<br /> }</p> <p>export default TodoItem<br /> " title="" data-original-title="复制"></span> </div> </p></div> <pre class="hljs scala"><code><span class="hljs-keyword">import</span> <span class="hljs-type">React</span> from <span class="hljs-symbol">'reac</span>t' <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">TodoItem</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">React</span>.<span class="hljs-title">Component</span> </span>{ render() { let className = <span class="hljs-keyword">this</span>.props.isDone?<span class="hljs-symbol">'task</span>-done':'' <span class="hljs-keyword">return</span> ( &lt;li&gt; &lt;label&gt; &lt;input <span class="hljs-class"><span class="hljs-keyword">type</span></span>=<span class="hljs-string">"<a href="http://www.js-code.com/tag/checkbox" title="浏览关于“checkbox”的文章" target="_blank" class="tag_link">checkbox</a>"</span>/&gt; &lt;span className={className}&gt;{<span class="hljs-keyword">this</span>.props.text}&lt;/span&gt; &lt;/label&gt; &lt;/li&gt; ) } } export <span class="hljs-keyword">default</span> <span class="hljs-type">TodoItem</span> </code></pre> <p>这一步时<code>webpack</code>先编译,然后打开index.html,如果页面像下图这样的<a href="https://zegendary.github.io/react-demo/todoMvc/todoMvc-3step/" rel="nofollow noreferrer" target="_blank">odoMvc-3step演示</a>,那就说明成功了。<br /><span class="img-wrap"><img data-src="/img/remote/1460000008575280" src="https://static.segmentfault.com/v-5cc2cd8e/global/img/squares.svg" alt="第三部截图" title="第三部截图" style="cursor: pointer;"></span></p> <p>做到这里应该对react组件组件化的有个大概的了解了。新手们基本可以对着源码按照这种思路继续做下去。以完善【删除】、【清除已完成】、【未完成数量】等功能了,由于代码类似,故不做赘述了,不太清楚的地方可以参考源码。</p> <h1 id="articleHeader3">Antd</h1> <p><a href="https://github.com/Zegendary/react-demo/tree/master/todoMvc/todoMvc-4step" rel="nofollow noreferrer" target="_blank">todoMvc-4step源码</a><br /><a href="https://zegendary.github.io/react-demo/todoMvc/todoMvc-4step/" rel="nofollow noreferrer" target="_blank">todoMvc-4step演示</a></p> <p>这一章主要以【删除】键为例讲一下如何使用以&nbsp;<a href="http://facebook.github.io/react/" rel="nofollow noreferrer" target="_blank">React</a>&nbsp;封装了一套 <a href="https://ant.design/index-cn" rel="nofollow noreferrer" target="_blank">Ant Design</a> 的组件库:</p> <p><span class="img-wrap"><img data-src="/img/remote/1460000008575281" src="https://static.segmentfault.com/v-5cc2cd8e/global/img/squares.svg" alt="Ant Design" title="Ant Design" style="cursor: pointer;"></span></p> <h4>1. 安装</h4> <p>推荐使用 npm 的方式进行开发,不仅可在开发环境轻松调试,也可放心地在生产环境打包部署使用,享受整个生态圈和工具链带来的诸多好处。<br />可以通过 npm 直接安装到项目中,使用 <code>import</code> 或 <code>require</code> 进行引用。</p> <div class="widget-codetool" style="display:none;"> <div class="widget-codetool--inner"> <span class="selectCode code-tool" data-toggle="tooltip" data-placement="top" title="" data-original-title="全选"></span><br /> <span type="button" class="copyCode code-tool" data-toggle="tooltip" data-placement="top" data-clipboard-text=" $ npm install antd --save " title="" data-original-title="复制"></span> </div> </p></div> <pre class="hljs sql"><code> $ npm <span class="hljs-keyword">install</span> antd <span class="hljs-comment">--save</span> </code></pre> <h4>2. 加载</h4> <p>可以通过以下的写法来按需加载组件。</p> <div class="widget-codetool" style="display:none;"> <div class="widget-codetool--inner"> <span class="selectCode code-tool" data-toggle="tooltip" data-placement="top" title="" data-original-title="全选"></span><br /> <span type="button" class="copyCode code-tool" data-toggle="tooltip" data-placement="top" data-clipboard-text="import Button from 'antd/lib/button'; import 'antd/lib/button/style'; // 或者 antd/lib/button/style/css 加载 css 文件 " title="" data-original-title="复制"></span> </div> </p></div> <pre class="hljs typescript"><code><span class="hljs-keyword">import</span> Button <span class="hljs-keyword">from</span> <span class="hljs-string">'antd/lib/button'</span>; <span class="hljs-keyword">import</span> <span class="hljs-string">'antd/lib/button/style'</span>; <span class="hljs-comment">// 或者 antd/lib/button/style/css 加载 css 文件</span> </code></pre> <p>但我推荐使用更简便的写法:<br />首先需要安装<a href="https://github.com/ant-design/babel-plugin-import" rel="nofollow noreferrer" target="_blank">babel-plugin-import</a>&nbsp;依赖</p> <div class="widget-codetool" style="display:none;"> <div class="widget-codetool--inner"> <span class="selectCode code-tool" data-toggle="tooltip" data-placement="top" title="" data-original-title="全选"></span><br /> <span type="button" class="copyCode code-tool" data-toggle="tooltip" data-placement="top" data-clipboard-text="$ npm install babel-plugin-import --save-dev" title="" data-original-title="复制"></span> </div> </p></div> <pre class="hljs sql"><code style="word-break: break-word; white-space: initial;">$ npm <span class="hljs-keyword">install</span> babel-<span class="hljs-keyword"><a href="http://www.js-code.com/tag/plugin" title="浏览关于“plugin”的文章" target="_blank" class="tag_link">plugin</a></span>-<span class="hljs-keyword">import</span> <span class="hljs-comment">--save-dev</span></code></pre> <p>然后在我们的根目录下新建<code>.<a href="http://www.js-code.com/tag/babel" title="babel" target="_blank">babel</a>rc</code>:</p> <div class="widget-codetool" style="display:none;"> <div class="widget-codetool--inner"> <span class="selectCode code-tool" data-toggle="tooltip" data-placement="top" title="" data-original-title="全选"></span><br /> <span type="button" class="copyCode code-tool" data-toggle="tooltip" data-placement="top" data-clipboard-text="{ &quot;plugins&quot;: [[&quot;import&quot;, {&quot;libraryName&quot;: &quot;antd&quot;, &quot;style&quot;: &quot;css&quot;}]] //import js and css modularly }" title="" data-original-title="复制"></span> </div> </p></div> <pre class="hljs json"><code>{ <span class="hljs-attr">"plugins"</span>: [[<span class="hljs-string">"import"</span>, {<span class="hljs-attr">"libraryName"</span>: <span class="hljs-string">"antd"</span>, <span class="hljs-attr">"style"</span>: <span class="hljs-string">"css"</span>}]] //import js and css modularly }</code></pre> <p>这时我们需要什么UI组件,即可如下这么写以达到按需加载<code>js</code>和<code>css</code>:</p> <div class="widget-codetool" style="display:none;"> <div class="widget-codetool--inner"> <span class="selectCode code-tool" data-toggle="tooltip" data-placement="top" title="" data-original-title="全选"></span><br /> <span type="button" class="copyCode code-tool" data-toggle="tooltip" data-placement="top" data-clipboard-text="import { Button } from 'antd'; " title="" data-original-title="复制"></span> </div> </p></div> <pre class="hljs typescript"><code><span class="hljs-keyword">import</span> { Button } <span class="hljs-keyword">from</span> <span class="hljs-string">'antd'</span>; </code></pre> <h4>3. 使用</h4> <p>由于<code>Antd</code>组件已经油<code>React</code>封装好了,用法和原生html标签没差:</p> <div class="widget-codetool" style="display:none;"> <div class="widget-codetool--inner"> <span class="selectCode code-tool" data-toggle="tooltip" data-placement="top" title="" data-original-title="全选"></span><br /> <span type="button" class="copyCode code-tool" data-toggle="tooltip" data-placement="top" data-clipboard-text="<Button type=&quot;danger&quot; size=&quot;small&quot; onClick={this.handlerDelete.bind(this)}>删除</Button><br /> " title="" data-original-title="复制"></span> </div> </p></div> <pre class="hljs scala"><code>&lt;<span class="hljs-type">Button</span> <span class="hljs-class"><span class="hljs-keyword">type</span></span>=<span class="hljs-string">"danger"</span> size=<span class="hljs-string">"small"</span> onClick={<span class="hljs-keyword">this</span>.handlerDelete.bind(<span class="hljs-keyword">this</span>)}&gt;删除&lt;/<span class="hljs-type">Button</span>&gt; </code></pre> <p>剩余的样式我们就可以对着<a href="https://ant.design/components/button-cn/" rel="nofollow noreferrer" target="_blank">antd components</a>的demo来开发。</p> <h1 id="articleHeader4">使用<a href="https://leancloud.cn/" rel="nofollow noreferrer" target="_blank">leancloud</a>登录注册</h1> <p><a href="https://github.com/Zegendary/react-demo/tree/master/todoMvc/todoMvc-5step" rel="nofollow noreferrer" target="_blank">todoMvc-5step源码</a> <br /><a href="https://zegendary.github.io/react-demo/todoMvc/todoMvc-5step/" rel="nofollow noreferrer" target="_blank">todoMvc-5step演示</a></p> <p>这一章主要将上一章已经成型的TodoMvc增加【注册】、【登陆】、【数据储存】的功能,这里我们把数据保存到<a href="https://leancloud.cn/" rel="nofollow noreferrer" target="_blank">leancloud</a>。</p> <h4>1. 创建 LeanCloud 账户</h4> <p>你需要去&nbsp;<a href="https://leancloud.cn/" rel="nofollow noreferrer" target="_blank">https://leancloud.cn</a>&nbsp;创建一个账户。<br />创建成功后,你需要验证你的邮箱,否则无法创建应用。</p> <h4>2. 创建TodoMVC应用</h4> <p>如下图操作:<br /><span class="img-wrap"><img data-src="/img/remote/1460000008575282" src="https://static.segmentfault.com/v-5cc2cd8e/global/img/squares.svg" alt="创建应用" title="创建应用" style="cursor: pointer;"></span><br />创建成功后就放在那里,因为接下来我们要按照 LeanCloud 的「<a href="https://leancloud.cn/docs/sdk_setup-js.html" rel="nofollow noreferrer" target="_blank">JavaScript SDK 文档</a>」来开发登录、注册功能。</p> <h4>3. 准备HTML页面</h4> <p>登陆和注册的页面同样也以组件的形式单独抽离出来,样式如图:</p> <p><span class="img-wrap"><img data-src="/img/remote/1460000008575283" src="https://static.segmentfault.com/v-5cc2cd8e/global/img/squares.svg" alt="登录注册" title="登录注册" style="cursor: pointer;"></span></p> <p>组件<code>Login.js</code>代码如下:</p> <div class="widget-codetool" style="display:none;"> <div class="widget-codetool--inner"> <span class="selectCode code-tool" data-toggle="tooltip" data-placement="top" title="" data-original-title="全选"></span><br /> <span type="button" class="copyCode code-tool" data-toggle="tooltip" data-placement="top" data-clipboard-text="import React from 'react' import { Form, Icon, Input, Button } from 'antd'; const FormItem = Form.Item; const Login = Form.create()(React.createClass({ handleSubmit(e) { // 提交操作 e.preventDefault(); this.props.form.validateFields((err, values) => {<br /> if (!err) {<br /> this.props.loginOrSignUp(values)<br /> }<br /> });<br /> },<br /> render() {<br /> <a href="http://www.js-code.com/tag/const" title="const" target="_blank">const</a> { getFieldDecorator } = this.props.<a href="http://www.js-code.com/tag/for" title="for" target="_blank">for</a>m;<br /> let text = this.props.value == 1 ?'注册':'登陆' // 判断“登陆”或者注册功能<br /> return (<br /> <Form onSubmit={this.handleSubmit} className=&quot;login-form&quot;> // antdUI的表单<br /> <FormItem><br /> {getFieldDecorator('userName', {<br /> rules: [{ required: <a href="http://www.js-code.com/tag/true" title="true" target="_blank">true</a>, message: 'Please input your user<a href="http://www.js-code.com/tag/name" title="name" target="_blank">name</a>!' }],<br /> })(<br /> <Input addonBe<a href="http://www.js-code.com/tag/for" title="for" target="_blank">for</a>e={<Icon type=&quot;user&quot; ></Icon>} placeholder=&quot;Username&quot; /><br /> )}<br /> </FormItem><br /> <FormItem><br /> {getFieldDecorator('<a href="http://www.js-code.com/tag/password" title="password" target="_blank">password</a>', {<br /> rules: [{ required: <a href="http://www.js-code.com/tag/true" title="true" target="_blank">true</a>, message: 'Please input your Password!' }], // 必须填写项<br /> })(<br /> <Input addonBe<a href="http://www.js-code.com/tag/for" title="浏览关于“for”的文章" target="_blank" class="tag_link">for</a>e={<Icon type=&quot;lock&quot; ></Icon>} type=&quot;password&quot; placeholder=&quot;Password&quot; /><br /> )}<br /> </FormItem><br /> <FormItem><br /> <Button type=&quot;primary&quot; htmlType=&quot;submit&quot; className=&quot;login-form-button&quot;><br /> {text}<br /> </Button><br /> </FormItem><br /> </Form><br /> );<br /> },<br /> }));<br /> export default Login" title="" data-original-title="复制"></span> </div> </p></div> <pre class="hljs kotlin"><code><span class="hljs-keyword">import</span> React from <span class="hljs-string">'react'</span> <span class="hljs-keyword">import</span> { Form, Icon, Input, Button } from <span class="hljs-string">'antd'</span>; <span class="hljs-keyword">const</span> FormItem = Form.Item; <span class="hljs-keyword">const</span> Login = Form.create()(React.createClass({ handleSubmit(e) { <span class="hljs-comment">// 提交操作</span> e.pr<a href="http://www.js-code.com/tag/event" title="浏览关于“event”的文章" target="_blank" class="tag_link">event</a>Default(); <span class="hljs-keyword">this</span>.props.<a href="http://www.js-code.com/tag/form" title="浏览关于“form”的文章" target="_blank" class="tag_link">form</a>.validateFields((err, values) =&gt; { <span class="hljs-keyword">if</span> (!err) { <span class="hljs-keyword">this</span>.props.loginOrSignUp(values) } }); }, render() { <span class="hljs-keyword">const</span> { getFieldDecorator } = <span class="hljs-keyword">this</span>.props.form; let text = <span class="hljs-keyword">this</span>.props.value == <span class="hljs-number">1</span> ?<span class="hljs-string">'注册'</span>:<span class="hljs-string">'登陆'</span> <span class="hljs-comment">// 判断“登陆”或者注册功能</span> <span class="hljs-keyword">return</span> ( &lt;Form onSubmit={<span class="hljs-keyword">this</span>.handleSubmit} className=<span class="hljs-string">"login-form"</span>&gt; <span class="hljs-comment">// antdUI的表单</span> &lt;FormItem&gt; {getFieldDecorator(<span class="hljs-string">'userName'</span>, { rules: [{ required: <span class="hljs-literal"><a href="http://www.js-code.com/tag/true" title="浏览关于“true”的文章" target="_blank" class="tag_link">true</a></span>, message: <span class="hljs-string">'Please input your username!'</span> }], })( &lt;Input addonBefore={&lt;Icon type=<span class="hljs-string">"user"</span> /&gt;} placeholder=<span class="hljs-string">"Username"</span> /&gt; )} &lt;/FormItem&gt; &lt;FormItem&gt; {getFieldDecorator(<span class="hljs-string">'<a href="http://www.js-code.com/tag/password" title="浏览关于“password”的文章" target="_blank" class="tag_link">password</a>'</span>, { rules: [{ required: <span class="hljs-literal">true</span>, message: <span class="hljs-string">'Please input your Password!'</span> }], <span class="hljs-comment">// 必须填写项</span> })( &lt;Input addonBefore={&lt;Icon type=<span class="hljs-string">"lock"</span> /&gt;} type=<span class="hljs-string">"password"</span> placeholder=<span class="hljs-string">"Password"</span> /&gt; )} &lt;/FormItem&gt; &lt;FormItem&gt; &lt;Button type=<span class="hljs-string">"primary"</span> htmlType=<span class="hljs-string">"<a href="http://www.js-code.com/tag/submit" title="浏览关于“submit”的文章" target="_blank" class="tag_link">submit</a>"</span> className=<span class="hljs-string">"login-form-button"</span>&gt; {text} &lt;/Button&gt; &lt;/FormItem&gt; &lt;/Form&gt; ); }, })); export <span class="hljs-keyword">default</span> Login</code></pre> <p>在<code>app.js</code>中做判断,如果<strong>已登录</strong>,则显示ToDo应用界面,否则显示登陆界面:</p> <div class="widget-codetool" style="display:none;"> <div class="widget-codetool--inner"> <span class="selectCode code-tool" data-toggle="tooltip" data-placement="top" title="" data-original-title="全选"></span><br /> <span type="button" class="copyCode code-tool" data-toggle="tooltip" data-placement="top" data-clipboard-text="render(){ if (!this.state.currentUser){ // 判断是否已经登录 <a href="http://www.js-code.com/tag/const" title="const" target="_blank">const</a> RadioGroup = Radio.Group;<br /> return (</p> <div className=&quot;form-wrapper&quot;> <h1 className=&quot;todo-title&quot;>React-Todos</h1> <p> <RadioGroup className=&quot;radio-wrapper&quot; onChange={this.onChange.bind(this)} value={this.state.value}><br /> <Radio value={1}>注册</Radio><br /> <Radio value={2}>登入</Radio><br /> </RadioGroup><br /> <Login loginOrSignUp={this.loginOrSignUp.bind(this)} value={this.state.value}></Login> </div> <p> )<br /> } else {<br /> let info = {<br /> isAllChecked: this.state.isAllChecked,<br /> todoCount: this.state.todos.length || 0,<br /> todoDoneCount: (this.state.todos &amp;&amp; this.state.todos.filter((todo) => todo.isDone)).<a href="http://www.js-code.com/tag/length" title="length" target="_blank">length</a> || 0<br /> }<br /> return (</p> <div className=&quot;todo-wrapper&quot;> <TodoHeader addTodo={this.addTodo.bind(this)} currentUser={this.state.currentUser} logout={this.logout.bind(this)}></TodoHeader><br /> <TodoMain todos={this.state.todos} changeTodoState={this.changeTodoState.bind(this)} deleteTodo={this.deleteTodo.bind(this)} saveOrUpdateTodos={this.saveOrUpdateTodos.bind(this)}></TodoMain><br /> <TodoFooter {...info} clearDone={this.clearDone.bind(this)} changeTodoState={this.changeTodoState.bind(this)}></TodoFooter> </div> <p> )<br /> }<br /> }<br /> " title="" data-original-title="复制"></span> </div> </p></div> <pre class="hljs kotlin"><code>render(){ <span class="hljs-keyword">if</span> (!<span class="hljs-keyword">this</span>.state.currentUser){ <span class="hljs-comment">// 判断是否已经登录</span> <span class="hljs-keyword">const</span> RadioGroup = Radio.Group; <span class="hljs-keyword">return</span> ( &lt;div className=<span class="hljs-string">"form-wrapper"</span>&gt; &lt;h1 className=<span class="hljs-string">"todo-title"</span>&gt;React-Todos&lt;/h1&gt; &lt;RadioGroup className=<span class="hljs-string">"<a href="http://www.js-code.com/tag/radio" title="浏览关于“radio”的文章" target="_blank" class="tag_link">radio</a>-wrapper"</span> onChange={<span class="hljs-keyword">this</span>.onChange.bind(<span class="hljs-keyword">this</span>)} value={<span class="hljs-keyword">this</span>.state.value}&gt; &lt;Radio value={<span class="hljs-number">1</span>}&gt;注册&lt;/Radio&gt; &lt;Radio value={<span class="hljs-number">2</span>}&gt;登入&lt;/Radio&gt; &lt;/RadioGroup&gt; &lt;Login loginOrSignUp={<span class="hljs-keyword">this</span>.loginOrSignUp.bind(<span class="hljs-keyword">this</span>)} value={<span class="hljs-keyword">this</span>.state.value}/&gt; &lt;/div&gt; ) } <span class="hljs-keyword">else</span> { let info = { isAllChecked: <span class="hljs-keyword">this</span>.state.isAllChecked, todoCount: <span class="hljs-keyword">this</span>.state.todos.length || <span class="hljs-number">0</span>, todoDoneCount: (<span class="hljs-keyword">this</span>.state.todos &amp;&amp; <span class="hljs-keyword">this</span>.state.todos.filter((todo) =&gt; todo.isDone)).length || <span class="hljs-number">0</span> } <span class="hljs-keyword">return</span> ( &lt;div className=<span class="hljs-string">"todo-wrapper"</span>&gt; &lt;TodoHeader addTodo={<span class="hljs-keyword">this</span>.addTodo.bind(<span class="hljs-keyword">this</span>)} currentUser={<span class="hljs-keyword">this</span>.state.currentUser} logout={<span class="hljs-keyword">this</span>.logout.bind(<span class="hljs-keyword">this</span>)}/&gt; &lt;TodoMain todos={<span class="hljs-keyword">this</span>.state.todos} changeTodoState={<span class="hljs-keyword">this</span>.changeTodoState.bind(<span class="hljs-keyword">this</span>)} deleteTodo={<span class="hljs-keyword">this</span>.deleteTodo.bind(<span class="hljs-keyword">this</span>)} saveOrUpdateTodos={<span class="hljs-keyword">this</span>.saveOrUpdateTodos.bind(<span class="hljs-keyword">this</span>)}/&gt; &lt;TodoFooter {...info} clearDone={<span class="hljs-keyword">this</span>.clearDone.bind(<span class="hljs-keyword">this</span>)} changeTodoState={<span class="hljs-keyword">this</span>.changeTodoState.bind(<span class="hljs-keyword">this</span>)}/&gt; &lt;/div&gt; ) } } </code></pre> <h4>4. 注册&amp;登陆</h4> <p>1.安装 LeanCloud SDK<br /><a href="https://leancloud.cn/docs/sdk_setup-js.html" rel="nofollow noreferrer" target="_blank">https://leancloud.cn/docs/sdk_setup-js.html</a></p> <div class="widget-codetool" style="display:none;"> <div class="widget-codetool--inner"> <span class="selectCode code-tool" data-toggle="tooltip" data-placement="top" title="" data-original-title="全选"></span><br /> <span type="button" class="copyCode code-tool" data-toggle="tooltip" data-placement="top" data-clipboard-text="$ npm install leancloud-storage --save" title="" data-original-title="复制"></span> </div> </p></div> <pre class="hljs sql"><code style="word-break: break-word; white-space: initial;">$ npm <span class="hljs-keyword">install</span> leancloud-<span class="hljs-keyword">storage</span> <span class="hljs-comment">--save</span></code></pre> <p>2.初始化<br /><a href="https://leancloud.cn/docs/sdk_setup-js.html#%E5%88%9D%E5%A7%8B%E5%8C%96" rel="nofollow noreferrer" target="_blank">https://leancloud.cn/docs/sdk_setup-js.html#初始化</a><br /><code>app.js</code>:</p> <div class="widget-codetool" style="display:none;"> <div class="widget-codetool--inner"> <span class="selectCode code-tool" data-toggle="tooltip" data-placement="top" title="" data-original-title="全选"></span><br /> <span type="button" class="copyCode code-tool" data-toggle="tooltip" data-placement="top" data-clipboard-text="import AV from 'leancloud-storage' const appId = 'XXXXXXXXXXXXXXXXXXXXXX' //这里的appId就是刚才我们创建的应用的Id,每个人都不一样 const appKey = 'XXXXXXXXXXXXXXXXXXX'; AV.init({ appId, appKey });" title="" data-original-title="复制"></span> </div> </p></div> <pre class="hljs typescript"><code><span class="hljs-keyword">import</span> AV <span class="hljs-keyword">from</span> <span class="hljs-string">'leancloud-storage'</span> <span class="hljs-keyword">const</span> appId = <span class="hljs-string">'XXXXXXXXXXXXXXXXXXXXXX'</span> <span class="hljs-comment">//这里的appId就是刚才我们创建的应用的Id,每个人都不一样</span> <span class="hljs-keyword">const</span> appKey = <span class="hljs-string">'XXXXXXXXXXXXXXXXXXX'</span>; AV.init({ appId, appKey });</code></pre> <p>3.写入注册登陆的方法<br />我们先要通读一下 LeanCloud&nbsp;<a href="https://leancloud.cn/docs/leanstorage_guide-js.html#%E7%94%A8%E6%88%B7%E5%90%8D%E5%92%8C%E5%AF%86%E7%A0%81%E6%B3%A8%E5%86%8C" rel="nofollow noreferrer" target="_blank">关于注册的文档</a>,然后按照里面的demo去做修改。<br /><code>app.js</code>:</p> <div class="widget-codetool" style="display:none;"> <div class="widget-codetool--inner"> <span class="selectCode code-tool" data-toggle="tooltip" data-placement="top" title="" data-original-title="全选"></span><br /> <span type="button" class="copyCode code-tool" data-toggle="tooltip" data-placement="top" data-clipboard-text="//登陆或者注册 loginOrSignUp(values){ //判断是登陆还是注册 if (this.state.value === 1){ let user = new AV.User(); user.setUsername(values.userName); user.setPassword(values.password); user.signUp().then((loginedUser) => {<br /> this.state.currentUser = this.getCurrentUser()<br /> this.setState({currentUser: this.state.currentUser})<br /> }, function (error) {<br /> alert(&quot;注册失败&quot;)<br /> })<br /> } else if (this.state.value === 2){<br /> console.log(&quot;执行登陆&quot;)<br /> AV.User.logIn(values.userName, values.password).then((loginedUser) => {<br /> this.state.currentUser = this.getCurrentUser()<br /> this.setState({currentUser: this.state.currentUser})<br /> this.fetchTodos()<br /> }, function (error) {<br /> alert(&quot;登陆失败&quot;)<br /> });<br /> }<br /> }" title="" data-original-title="复制"></span> </div> </p></div> <pre class="hljs javascript"><code><span class="hljs-comment">//登陆或者注册</span> loginOrSignUp(values){ <span class="hljs-comment">//判断是登陆还是注册</span> <span class="hljs-keyword">if</span> (<span class="hljs-keyword">this</span>.state.value === <span class="hljs-number">1</span>){ <span class="hljs-keyword">let</span> user = <span class="hljs-keyword">new</span> AV.User(); user.setUsername(values.userName); user.setPassword(values.password); user.signUp().then(<span class="hljs-function">(<span class="hljs-params">loginedUser</span>) =&gt;</span> { <span class="hljs-keyword">this</span>.state.currentUser = <span class="hljs-keyword">this</span>.getCurrentUser() <span class="hljs-keyword">this</span>.setState({<span class="hljs-attr">currentUser</span>: <span class="hljs-keyword">this</span>.state.currentUser}) }, <span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params">error</span>) </span>{ <a href="http://www.js-code.com/tag/alert" title="浏览关于“alert”的文章" target="_blank" class="tag_link">alert</a>(<span class="hljs-string">"注册失败"</span>) }) } <span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> (<span class="hljs-keyword">this</span>.state.value === <span class="hljs-number">2</span>){ <span class="hljs-built_in">console</span>.log(<span class="hljs-string">"执行登陆"</span>) AV.User.logIn(values.userName, values.password).then(<span class="hljs-function">(<span class="hljs-params">loginedUser</span>) =&gt;</span> { <span class="hljs-keyword">this</span>.state.currentUser = <span class="hljs-keyword">this</span>.getCurrentUser() <span class="hljs-keyword">this</span>.setState({<span class="hljs-attr">currentUser</span>: <span class="hljs-keyword">this</span>.state.currentUser}) <span class="hljs-keyword">this</span>.fetchTodos() }, <span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params">error</span>) </span>{ alert(<span class="hljs-string">"登陆失败"</span>) }); } }</code></pre> <p>下面还需要去做【登出】、【保存Todo】等功能。这里我就不贴出来代码了,可以直接去github上面去看我的<a href="https://github.com/Zegendary/react-demo/blob/master/todoMvc/todoMvc-5step/src/components/app.js" rel="nofollow noreferrer" target="_blank">app.js源码</a>。<br />至此,我们React+Webpack+Antd 的一个TodoMVC的思路就讲解完毕了。希望能帮助小伙伴。</p> <p></code></p>

总结

以上是脚本宝典为你收集整理的

React+webpack+Antd从0到1开发一个todoMvc

全部内容,希望文章能够帮你解决

React+webpack+Antd从0到1开发一个todoMvc

所遇到的程序开发问题,欢迎加入QQ群277859234一起讨论学习。如果觉得脚本宝典网站内容还不错,欢迎将脚本宝典网站推荐给程序员好友。 本图文内容来源于网友网络收集整理提供,作为学习参考使用,版权属于原作者。如您有任何意见或建议可联系处理。小编QQ:384754419,请注明来意。

80%的人都看过