资讯专栏INFORMATION COLUMN

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

sanyang / 2029人阅读

摘要:在装载组件之前调用会组件的构造函数。当实现子类的构造函数时,应该在任何其他语句之前调用设置初始状态绑定键盘回车事件,添加新任务修改状态值,每次修改以后,自动调用方法,再次渲染组件。可以通过直接安装到项目中,使用或进行引用。

首先我们看一下我们完成后的最终形态:TodoMvc:

学习必要条件:略懂node.js,略懂ES6,然后你的电脑必须安装有较新版本node,没有的同学赶紧安装。
好了,废话不多说,直接开始。

第一部分源码:todoMvc-1step

webpack的配置 1. 介绍:

Webpack 是当下最热门的前端资源模块化管理和打包工具。详细见官网

2. 安装:

</>复制代码

  1. $ npm install webpack -g

此时 Webpack 已经安装到了全局环境下,可以通过命令行 webpack -h 试试。但通常我们会将 Webpack 以及相关依赖以这种方式安装,如下:

</>复制代码

  1. # 进入项目目录
  2. # 确定已经有 package.json,没有就通过 npm init 创建
  3. # 安装 webpack 依赖
  4. $ npm install webpack --save-dev
  5. # 安装react.js依赖(i是install的简写,-S是--save的简写)
  6. $ npm i react react-dom -S

剩余的依赖组件参照我源码中的package.json的依赖添加就好。最终,我们得到的package.json应该如下图:确保红框中的内容一样即可。

3. 配置

现在我们已经安装好了依赖,下面我们需要先把项目的目录建好:

</>复制代码

  1. .
  2. ├── node_modules # npm install 安装的东西都跑着里面来了
  3. ├── src
  4. ├── components
  5. ├── app.js # react组件
  6. ├── styles
  7. ├── main.styl # stylus文件(类似于sass)
  8. ├── entry.js # 入口js文件
  9. ├── index.html # 入口页面
  10. ├── package.json # 项目描述文件(内有相关依赖)
  11. └── webpack.config.js # webpack配置文件

然后我们在webpack.config.js中添加配置:

</>复制代码

  1. module.exports = {
  2. entry: [
  3. "./src/entry.js"
  4. ],
  5. output: {
  6. path: "./out/",
  7. filename: "bundle.js"
  8. },
  9. module: {
  10. loaders: [
  11. { test: /.js[x]?$/, loader: "babel-loader?presets[]=es2015&presets[]=react", include: /src/},
  12. { test: /.css$/, loader: "style!css"},
  13. { test: /.styl$/, loader: "style-loader!css-loader!stylus-loader"},
  14. { test: /.(png|jpg)$/, loader: "url?limit=8192"}
  15. ]
  16. }
  17. }

配置文件将我们的入口文件entry.js打包输出到 ./out/bundle.js,我们直接在页面index.html中引入bundle.js就好了。

</>复制代码

不懂得话可以参考webpack的文档:webpack-usage 和 webpack-loader。关于/src目录下的文件内容可以直接到源码中查看。然后就可以小试牛刀啦,在终端中输入:

</>复制代码

  1. $ webpack

然后我们看到我们的目录下多了个./out/bundle.js文件,然后我们在浏览器打开目录下的index.html文件可以看到内容并alert("success")那么恭喜你,第一步圆满完成!

React如何双向绑定

todoMvc-2step源码
todoMvc-2step演示
上一章主要说了下react+webpack的环境搭建,这一章主要讲一下如何双向绑定。对vue和angular略有了解的都知道,这两个框架都是支持双向绑定的,而react是单向绑定的,知乎有一篇关于单向绑定和双向绑定可以拓展一下:单向数据绑定和双向数据绑定的优缺点,适合什么场景。下面分析如何具体实现:
进入我们的app.js文件,在之前我们搭建环境的时候已经安装了react相关的依赖以及babel编译工具,所以我们可以直接在这里使用ES6JSX语法。

1. 引入react核心内容

</>复制代码

  1. import React from "react"
  2. import ReactDOM from "react-dom"

其中,react.js 是 React 的核心库,react-dom.js 是提供与 DOM 相关的功能。

2. 生成组件

先介绍react三个比较重要的知识点:
1.ReactDOM.render()
ReactDOM.render 是 React 的最基本方法,用于将模板转为 HTML 语言,并插入指定的 DOM 节点。举个例子:

</>复制代码

  1. ReactDOM.render(
  2. Hello, world!

    ,
  3. document.getElementById("example")
  4. );

上面代码将一个 h1 标题,插入 example 节点。
2.JSX 语法
HTML 语言直接写在 JavaScript 语言之中,不加任何引号,这就是 JSX 的语法,它允许 HTML 与 JavaScript 的混写,上面的

Hello, world!

,就是使用了jsx语法。
3.组件
React 允许将代码封装成组件(component),然后像插入普通 HTML 标签一样,在网页中插入这个组件。React.createClass 方法就用于生成一个组件类。举个?:

</>复制代码

  1. //es5写法
  2. var HelloMessage = React.createClass({
  3. render: function() {
  4. return

    Hello React

    ;
  5. }
  6. });
  7. //es6写法
  8. Class HelloMessage extends React.Component {
  9. render() {
  10. return

    Hello, React;

  11. }
  12. }

当然,这里的HelloMessage我们也可以当做HTML标签用ReactDOM.render()渲染出来。

app.js:

</>复制代码

  1. class App extends React.Component { //定义组件,继承父类
  2. constructor() {//constructor 是和 class 一起用来创建和初始化对象的特殊方法。
  3. super()//在装载组件(mounting)之前调用会React组件的构造函数。当实现React.Component子类的构造函数时,应该在任何其他语句之前调用super(props)
  4. this.state = {//设置初始状态
  5. todos: []
  6. }
  7. }
  8. // 绑定键盘回车事件,添加新任务
  9. handlerKeyUp(e) {
  10. if(e.keyCode == 13) {
  11. let value = e.target.value;
  12. if(!value) return false;
  13. let newTodoItem = {
  14. text: value,
  15. isDone: false
  16. };
  17. e.target.value = "";
  18. this.state.todos.push(newTodoItem)
  19. this.setState({todos: this.state.todos}); //修改状态值,每次修改以后,自动调用 this.render 方法,再次渲染组件。
  20. }
  21. }
  22. render(){
  23. return (
    • {this.state.todos.map((todo,index) => {{
    • return (
    • {todo.text}
    • //Keys help React identify which items have changed, are added, or are removed. Keys should be given to the elements inside the array to give the elements a stable identity
    • )
    • }})}
  24. )
  25. }
  26. }
  27. ReactDOM.render(,document.getElementById("app"))
3. 测试

运行

</>复制代码

  1. $ webpack

然后打开index.html,如果可以在input输入,按下回车可以在下方生成list

那么恭喜你,双向绑定功能完成!

组件化

todoMvc-3step源码
todoMvc-3step演示
上一章主要介绍了下React如何进行双向绑定以及如何生成一个组件,我们第三步的目标就是需要把之前做的内容抽象出更细的组件,这样便于解耦,各个组件各司其职,互不干扰。
先看下抽象后src/components下的目录

先看下我们的app.js修改过后的内容:

</>复制代码

  1. import React from "react"
  2. import ReactDOM from "react-dom"
  3. import TodoHeader from "./TodoHeader" // 引入TodoHeader组件
  4. import TodoMain from "./TodoMain" // 引入TodoMain组件
  5. class App extends React.Component { // 定义组件,继承父类
  6. constructor() {
  7. super()
  8. this.state = {
  9. todos: []
  10. }
  11. }
  12. addTodo(item) { // 新增了添加todo事项的方法
  13. this.state.todos.push(item)
  14. this.setState({todos: this.state.todos}); //设置状态
  15. }
  16. render(){
  17. return (
  18. // 将原内容写在组件中并引入进行渲染
  19. // 把addTodo方法传递到TodoHeader组件中,bind(this)是为了把该React实例绑定到this
  20. // 把 state.todos 传入到TodoMain 中
  21. )
  22. }
  23. }
  24. ReactDOM.render(,document.getElementById("app"))

TodoHeader:

</>复制代码

  1. import React from "react"
  2. class TodoHeader extends React.Component {
  3. // 绑定键盘回车事件,添加新任务
  4. handlerKeyUp(e) {
  5. if(e.keyCode == 13) { // enter键的 keyCode 为13
  6. let value = e.target.value;
  7. if(!value) return false;
  8. let newTodoItem = {
  9. text: value,
  10. isDone: false
  11. };
  12. e.target.value = "";
  13. this.props.addTodo(newTodoItem) // 通过 this.props 来调用父组件传递过来的addTodo方法
  14. }
  15. }
  16. render(){
  17. return (
  18. )
  19. }
  20. }
  21. export default TodoHeader // 将TodoHeader导出,否则父组件无法导入

TodoMain修改后内容:

</>复制代码

  1. import React from "react"
  2. import TodoItem from "./TodoItem"
  3. class TodoMain extends React.Component {
  4. render(){
  5. if(this.props.todos.length == 0) {
  6. return (
  7. 恭喜您,目前没有待办任务
  8. )
  9. } else {
  10. return (
    • {
    • this.props.todos.map((todo,index) => {
    • //{...this.props} 用来传递TodoMain的todos属性和delete、change方法。
    • return
    • })
    • }
  11. )
  12. }
  13. }
  14. }
  15. export default TodoMain

TodoItem

</>复制代码

  1. import React from "react"
  2. class TodoItem extends React.Component {
  3. render() {
  4. let className = this.props.isDone?"task-done":""
  5. return (
  6. {this.props.text}
  7. )
  8. }
  9. }
  10. export default TodoItem

这一步时webpack先编译,然后打开index.html,如果页面像下图这样的odoMvc-3step演示,那就说明成功了。

做到这里应该对react组件组件化的有个大概的了解了。新手们基本可以对着源码按照这种思路继续做下去。以完善【删除】、【清除已完成】、【未完成数量】等功能了,由于代码类似,故不做赘述了,不太清楚的地方可以参考源码。

Antd

todoMvc-4step源码
todoMvc-4step演示

这一章主要以【删除】键为例讲一下如何使用以 React 封装了一套 Ant Design 的组件库:

1. 安装

推荐使用 npm 的方式进行开发,不仅可在开发环境轻松调试,也可放心地在生产环境打包部署使用,享受整个生态圈和工具链带来的诸多好处。
可以通过 npm 直接安装到项目中,使用 importrequire 进行引用。

</>复制代码

  1. $ npm install antd --save
2. 加载

可以通过以下的写法来按需加载组件。

</>复制代码

  1. import Button from "antd/lib/button";
  2. import "antd/lib/button/style"; // 或者 antd/lib/button/style/css 加载 css 文件

但我推荐使用更简便的写法:
首先需要安装babel-plugin-import 依赖

</>复制代码

  1. $ npm install babel-plugin-import --save-dev

然后在我们的根目录下新建.babelrc

</>复制代码

  1. {
  2. "plugins": [["import", {"libraryName": "antd", "style": "css"}]] //import js and css modularly
  3. }

这时我们需要什么UI组件,即可如下这么写以达到按需加载jscss

</>复制代码

  1. import { Button } from "antd";
3. 使用

由于Antd组件已经油React封装好了,用法和原生html标签没差:

</>复制代码

剩余的样式我们就可以对着antd components的demo来开发。

使用leancloud登录注册

todoMvc-5step源码
todoMvc-5step演示

这一章主要将上一章已经成型的TodoMvc增加【注册】、【登陆】、【数据储存】的功能,这里我们把数据保存到leancloud。

1. 创建 LeanCloud 账户

你需要去 https://leancloud.cn 创建一个账户。
创建成功后,你需要验证你的邮箱,否则无法创建应用。

2. 创建TodoMVC应用

如下图操作:

创建成功后就放在那里,因为接下来我们要按照 LeanCloud 的「JavaScript SDK 文档」来开发登录、注册功能。

3. 准备HTML页面

登陆和注册的页面同样也以组件的形式多带带抽离出来,样式如图:

组件Login.js代码如下:

</>复制代码

  1. import React from "react"
  2. import { Form, Icon, Input, Button } from "antd";
  3. const FormItem = Form.Item;
  4. const Login = Form.create()(React.createClass({
  5. handleSubmit(e) { // 提交操作
  6. e.preventDefault();
  7. this.props.form.validateFields((err, values) => {
  8. if (!err) {
  9. this.props.loginOrSignUp(values)
  10. }
  11. });
  12. },
  13. render() {
  14. const { getFieldDecorator } = this.props.form;
  15. let text = this.props.value == 1 ?"注册":"登陆" // 判断“登陆”或者注册功能
  16. return (
  17. // antdUI的表单
  18. {getFieldDecorator("userName", {
  19. rules: [{ required: true, message: "Please input your username!" }],
  20. })(
  21. } placeholder="Username" />
  22. )}
  23. {getFieldDecorator("password", {
  24. rules: [{ required: true, message: "Please input your Password!" }], // 必须填写项
  25. })(
  26. } type="password" placeholder="Password" />
  27. )}
  28. {text}
  29. );
  30. },
  31. }));
  32. export default Login

app.js中做判断,如果已登录,则显示ToDo应用界面,否则显示登陆界面:

</>复制代码

  1. render(){
  2. if (!this.state.currentUser){ // 判断是否已经登录
  3. const RadioGroup = Radio.Group;
  4. return (
  5. React-Todos

  6. 注册
  7. 登入
  8. )
  9. } else {
  10. let info = {
  11. isAllChecked: this.state.isAllChecked,
  12. todoCount: this.state.todos.length || 0,
  13. todoDoneCount: (this.state.todos && this.state.todos.filter((todo) => todo.isDone)).length || 0
  14. }
  15. return (
  16. )
  17. }
  18. }
4. 注册&登陆

1.安装 LeanCloud SDK
https://leancloud.cn/docs/sdk_setup-js.html

</>复制代码

  1. $ npm install leancloud-storage --save

2.初始化
https://leancloud.cn/docs/sdk_setup-js.html#初始化
app.js:

</>复制代码

  1. import AV from "leancloud-storage"
  2. const appId = "XXXXXXXXXXXXXXXXXXXXXX" //这里的appId就是刚才我们创建的应用的Id,每个人都不一样
  3. const appKey = "XXXXXXXXXXXXXXXXXXX";
  4. AV.init({ appId, appKey });

3.写入注册登陆的方法
我们先要通读一下 LeanCloud 关于注册的文档,然后按照里面的demo去做修改。
app.js:

</>复制代码

  1. //登陆或者注册
  2. loginOrSignUp(values){
  3. //判断是登陆还是注册
  4. if (this.state.value === 1){
  5. let user = new AV.User();
  6. user.setUsername(values.userName);
  7. user.setPassword(values.password);
  8. user.signUp().then((loginedUser) => {
  9. this.state.currentUser = this.getCurrentUser()
  10. this.setState({currentUser: this.state.currentUser})
  11. }, function (error) {
  12. alert("注册失败")
  13. })
  14. } else if (this.state.value === 2){
  15. console.log("执行登陆")
  16. AV.User.logIn(values.userName, values.password).then((loginedUser) => {
  17. this.state.currentUser = this.getCurrentUser()
  18. this.setState({currentUser: this.state.currentUser})
  19. this.fetchTodos()
  20. }, function (error) {
  21. alert("登陆失败")
  22. });
  23. }
  24. }

下面还需要去做【登出】、【保存Todo】等功能。这里我就不贴出来代码了,可以直接去github上面去看我的app.js源码。
至此,我们React+Webpack+Antd 的一个TodoMVC的思路就讲解完毕了。希望能帮助小伙伴。

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/81915.html

相关文章

  • webpack工程化集成React技术栈(一)

    项目开始前,我们先聊一聊关于项目的一些说明。该项目起始于2017年初,当时公司主要技术栈为gulp+angular,鉴于react的火热的生态,在公司决定研发bss管理系统时选用react开发,目的也是为react native打下基础,以解决后期公司大前端技术栈的逐步成熟。(当时没有选择vue开发的主要原因是weex生态还不够特别成熟),既然决定换新,项目的构建也跟着一起换,从gulp转向火热的...

    tianhang 评论0 收藏0
  • 利用Dawn工程化工具实践MobX数据流管理方案

    摘要:新的项目目录设计如下放置静态文件业务组件入口文件数据模型定义数据定义工具函数其中数据流实践的核心概念就是数据模型和数据储存。最后再吃我一发安利是阿里云业务运营事业部前端团队开源的前端构建和工程化工具。 本文首发于阿里云前端dawn团队专栏。 项目在最初应用 MobX 时,对较为复杂的多人协作项目的数据流管理方案没有一个优雅的解决方案,通过对MobX官方文档中针对大型可维护项目最佳实践的...

    0x584a 评论0 收藏0
  • 学习零开始搭建React脚手架

    摘要:写在前面准备学习一下和相关的东西,官方的脚手架看起来太繁琐,所以打算自己来搭建一个,参考了这个文档从零搭建全家桶框架教程步骤上都差不多第一步,依赖总览完成到我现在半成品的过程中,目前完成开发模式的相关操作,添加了按需加载的地步。 写在前面 准备学习一下react和webpack相关的东西,官方的脚手架看起来太繁琐,所以打算自己来搭建一个,参考了这个文档从零搭建React全家桶框架教程;...

    cod7ce 评论0 收藏0
  • 采用React+Ant Design组件化开发前端界面(一)

    摘要:基础知识使用脚手架创建项目并启动安装脚手架使用脚手架创建项目为项目名。否则可能导致项目发布上线后,报错无法执行。安装测试使用注意默认情况下安装的需要引入才会生效样式,但很多时候,我们只是使用了部分组件,引入整个样式文件,有些得不偿失。 showImg(http://upload-images.jianshu.io/upload_images/2774022-8d65190f1b972c...

    cppprimer 评论0 收藏0
  • 用Browserify构建antd-mobile应用

    摘要:但在中,这一问题该如何解决呢使用遇到的问题如何自定义模块文件后缀名的优先级和一样,也提供了一个叫的配置选项,用于设定模块文件的后缀名及其优先级。 antd-mobile是蚂蚁金服出的移动端设计指南和前端框架,它提供了一套基于React的移动端组件库,可以很方便地用来开发体验良好的移动应用。 使用antd-mobile遇到的问题:react-native模块找不到 在阅读了antd-mo...

    tain335 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<