React学习一:文件组成,react.js编写TodoList功能

刚开始接触React,整理一下今天所看到的一部分内容。

react是一个JavaScript语言的工具库。需要安装node.js。react本身并不依赖于Node.js,但是我们开发中用到的诸多工具需要Node.js的支持。安装node.js的同时也就安装了npm,npm是node.js的安装包管理工具,在开发中会大量使用现有的安装包。

1. create-react-app工具

create-react-app是Facebook提供的一个快速开发react应用的工具,这个工具的目的是将开发人员从配置文件中解脱出来,无需过早关注这些技术栈细节。

npm install --global create-react-app   //安装结束之后,命令行就会有create-react-app这样一个可以执行的命令
create-react-app first_react_app    //这个命令是在当前目录下创建一个名为first_react_app的目录,在这个目录中会自动添加一个应用的框架
cd first_react_app    
npm start  //启动一个开发模式的服务器,浏览器自动打开一个网页指向本机地址http://localhost:3000/
2. 增加一个新的react组件
  1. React是基于组件开发的框架,组件就是网页上的一部分,能完成某个特定功能的独立的、可重用的代码。在react中,组件名称必须以大写字母开头。
  2. 在开发过程中,我们主要关注src目录中的内容,这个目录中是所有的源代码。
    React中的 src/index.js是入口文件 ,这个应用只是渲染一个名为App的组件,App组件在同目录下的App.js文件。
    页面上展示的内容App.js文件中的render函数return中的内容 所决定的,public下的index.html 是项目页面的HTML文件。
  3. 使用import导入组件,import是ES6语法中导入文件模块的方式,ES6语法的JavaScript代码会被webpack和babel转译成所有浏览器都支持的ES5语法,create-react-app已经替我们完成了这些工作。
    在index.js中引入react,目的是让浏览器能够理解下面的组件语法。
    在index.js中引入react-dom,目的是把一个组件挂载到页面的一个DOM节点上,它会把这个组件渲染到public的index.html的id=root的div标签里面去。
import ClickCounter from './ClickCounter';
ReactDOM.render(< TodoList  />, document.getElementById('root'));
//把TodoList组件渲染到html的id=root的标签上去。
  • 我们调用ReactDOM.render()函数,并传入TodoList组件作为参数,React调用TodoList组件,TodoList组件将内部的return内容作为返回值,React DOM 将DOM高效地更新。
  1. 在创建组件的第一行都会从react库中引入React和Component,Component是所有组件的基类,提供了很多组件共有的功能。
import React,{Component} from 'react';
class ClickCounter extends Component{   //使用ES6创建组件类
}

注意: 这里我们导入的Component在组件定义中使用了,但是React没有被使用,但是不能删除,如果删除会被报错——在使用JSX的范围内必须要有React。在使用JSX的代码文件中,即使代码中并没有直接使用React,也需要导入,因为JSX最终会被转译成依赖于React的表达式。

定义一个组件:让一个类继承react.Component,组件展示render返回的。

  import React,{Component} from 'react';
  class 类名 extends Component{
    render(){  负责这个组件要显示的内容
       return (   就是组件要显示的内容

       );
    }
  }
  或者
  import React from 'react';
  class 类名 extends React.Component{
    render(){  负责这个组件要显示的内容
       return (   就是组件要显示的内容

       );
    }
  }
  1. JSX :在JavaScript中可以编写像HTML一样的代码。让我们在react之中可以直接去使用这样标签形式的语法,可以在标签语法中通过花括号的形式写js表达式,但是不是js语句,不需要在js外面加引号,就需要引入react。
    JSX和HTML的区别:
    1) 在JSX中,不仅仅可以用HTML标签,还可以使用自己定义的标签。如果我们要使用自己创建的组件,直接通过标签形式来使用我们定义的组件名就可以,但是组件的名字开头必须以大写字母开头(react判断一个元素是HTML元素还是React组件的原则)。
    2) 在JSX中可以通过onClick这样的方式给一个元素添加一个事件处理函数。
    JSX的onClick事件处理函数和HTML中的onclick事件处理函数的不同:
    1) onclick添加的事件处理函数是在全局环境下执行的,会污染全局环境。onClick挂载的函数都可以控制在组件范围内,不会污染全局空间。
    2) 给很多DOM元素添加onclick事件,会影响网页的性能。在JSX中,使用了事件委托的方式处理点击事件,无论有多少个onClick出现,最后都只在DOM树上添加了一个事件处理函数。
    3) 对于使用onclick的DOM元素,如果动态地从DOM树中删除的话,需要把对于的时间处理函数注销,否则可能会内存泄漏。react控制了组件的生命周期,可以清除事件处理函数,不存在内存泄漏。
    在定义的组件中:
    1)可以直接返回视图标签不报错。
    2)外层必须要有一个根标签包裹着。
    3)根标签内部可以写 js 表达式,会自动编译,js 语句会报错。
    4)index.js 中 render 中引用组件时,组件名写在标签符号内。
    在JSX中写注释,只在开发上有意义,控制台不会展示出来。
{/*普通的js注释*/}
或者
 {
   //单行注释
 }
分解react的应用

在package.json文件中可以看到安装的一些内容。start命令实际上是调用了react-scripts命令,

"scripts": {
    "start": "react-scripts start",  //启动
    "build": "react-scripts build",  //创建生产环境优化代码
    "test": "react-scripts test",    //单元测试
    "eject": "react-scripts eject"   //把隐藏在react-scripts中的一系列技术栈配置都弹射到应用的顶层。eject命令是不可逆的。
  },

在调用npm run eject命令时,在当前目录会添加两个目录——scripts和config,同时在package.json文件中eject这行命令消失。

react的工作方式:
  1. UI=render(data);——UI是用户看到的界面,是render函数的执行结果,只接受数据作为参数。这个函数是一个纯函数,输出完全依赖于输入的函数。想要更新用户界面,只需要更新data。react.js是一种新的编程思想,函数式、响应式编程。优势:开发者的效率大大提高,开发出来的代码可维护性和可读性也大大增强。

  2. 相比于vue.js灵活性更大一些,处理比较复杂的业务时,技术方案会有更多一点的选择,Vue提供了更丰富的API,实现功能会更简单,但是因为API多,所以它的灵活性会受到限制。
    react官网提供的react脚手架create-react-app,使用很简单,可定制性很强,调试代码也非常方便。

  3. react中的响应式设计思想和事件绑定:
    响应式设计思想:不直接操作DOM,操作数据,数据改变,react页面会响应数据的变化。
    在react中,使用state保存数据状态,当改变状态时,需要使用setState()方法。

   this.setState({
      inputValue:e.target.value
  });
  1. 编写todolist功能:
    第一步:把TodoList.js文件引入到index.js中并挂载。
import TodoList from './TodoList';
ReactDOM.render(<TodoList />, document.getElementById('root'));

第二步:在TodoList.js文件的return中开始写标签语言
注意: render函数return出去的内容只能是一个大的JSX,如果有多于1个的JSX区块会报错,需要把多个JSX区块包裹在一个大的JSX区块中。这样在查看的时候会多一个div标签,我们可以使用React.Fragment标签,这样查看源代码时就root下不会多一层标签,Fragment也是一个组件。

import React,{Component,Fragment} from 'react';
class TodoList extends Component{
  render(){
        return(
         <Fragment>
            <div>
           <input value={this.state.inputValue} onChange={this.handleInputChange} />
            <button onClick={this.handleBtnClick}>add</button>
            </div>
            <ul>{this.getToDoItems()}</ul>
        </Fragment>
}

第三步:想要在点击add按钮时,给ul中添加内容,需要给button按钮绑定一个事件,react中事件绑定是C大写的onClick,js语法要放在{}花 括号中,this指的是这个组件。

//添加数据项:
constructor(props){  //当TodoList这个组件刚被创建时,constructor会被自动执行,
    super(props);   //super做一些初始化
    this.state={  //一创建组件时,我们在TodoList中就创建了state这个数据项,state里面可以存放很多的数据内容
        list:[
            "learn react",
            "learn english"
        ]
    };
};
// 怎样添加方法:新增的都是一样的,
handleBtnClick(){
  //this.state.list.push("x");这样是有错的,报错是找不到state,因为在下面button上的this是指的这个组件,但是handleBtnClick这个函数中的this指的是button按钮
    //解决方法是把下面button中的方法用bind函数指向组件的this,onClick={this.handleBtnClick.bind(this)}
    //但是虽然不报错了,列表中的内容并没有变化,解决方法是需要调用react中的方法,this.setState去改变state中的数据,改变的是list数据,
    this.setState({
        list:[...this.state.list,"hello,world"]   //使用的是ES6中的展开运算符,来表示list的形式,数据发生变化,页面就发生变化
    });
   // 还是会有一个警告,警告的意思是每个li标签上都应该有一个key值,如果不想要警告,可以在下面li中写一个key,map可以获取下标, 
   //         {this.state.list.map((item,index)=>{
    //                     return <li key={index+1}>{item}</li>
    //                 })}
};
render(){
    return(
    <div>
        <div>
       <input />
        <button onClick={this.handleBtnClick.bind(this)}>add</button>
        </div>
        <ul>
            {this.state.list.map((item,index)=>{
                return <li key={index+1}>{item}</li>
            })}
            /** map()是对数组做循环的函数 */
        </ul>
    </div>
    );
}

上面的内容是每次add后,都增加的一样的内容。

下面实现新增列表项时新增的内容不一样的。

input框只要有变化就会触发 onChange 事件,所以给input框绑定一个onChange事件,

handleInputChange(e){  //将input框的内容赋给inputValue数据项。
    this.setState({
        inputValue:e.target.value
    });
};
constructor(props){ 
    super(props);  
    this.state={  
        list:[],
        inputValue:''   //新增一个数据项,保存input框中的内容。
    };
};
handleBtnClick(){
    this.setState({
        list:[...this.state.list,this.state.inputValue]  //将inputValue的内容添加到list中
    });
 };
 <input onChange={this.handleInputChange.bind(this)} />

有一个问题: 每次点击add后,需要手动删除input框中的内容,希望每次点击add后,input框可以清空。
解决方法:

handleBtnClick(){
     this.setState({
        list:[...this.state.list,this.state.inputValue], 
        inputValue:""
    });
 };
   <input value={this.state.inputValue} onChange={this.handleInputChange.bind(this)} />

原因:在这里是input框发生变化,会触发onChange事件,然后inputValue会变成value的值,然后value又绑定了inputValue的值,所以这时候value的值是inputValue的值,然后点击add按钮之后,inputValue变成空,相对value的值也会变为空。

删除操作:

每次删除某一行时,需要知道这一行的id(id可以唯一的标识一行),点击事件是onClick。

handleItemClick(index){   //用来删除的,index可以用来获取删除的id
    const list = [...this.state.list]; //获取一个副本
    list.splice(index,1);  //删除id=index的一个
    this.setState({   
        list:list   //如果键值是一样的,可以省略, ==this.setState({list})
    });
    //可以直接操作state中的list,但是那样性能和可调式会变差,所以推荐使用副本的写法。
};
{this.state.list.map((item,index)=>{
    return <li key={index} onClick={this.handleItemClick.bind(this,index)}>{item}</li>
})}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
好的,下面是一个使用React和TypeScript完成的TodoList示例: 首先,创建一个React组件:TodoList.tsx ```tsx import React, { useState } from "react"; interface TodoItem { id: number; content: string; completed: boolean; } const TodoList = () => { const [todos, setTodos] = useState<TodoItem[]>([]); const [inputValue, setInputValue] = useState(""); const handleAddTodo = () => { if (inputValue.trim() === "") return; const newTodo: TodoItem = { id: todos.length, content: inputValue, completed: false }; setTodos([...todos, newTodo]); setInputValue(""); }; const handleToggleTodo = (id: number) => { const updatedTodos = todos.map(todo => todo.id === id ? { ...todo, completed: !todo.completed } : todo ); setTodos(updatedTodos); }; const handleDeleteTodo = (id: number) => { const updatedTodos = todos.filter(todo => todo.id !== id); setTodos(updatedTodos); }; return ( <div> <h1>Todo List</h1> <div> <input type="text" value={inputValue} onChange={e => setInputValue(e.target.value)} /> <button onClick={handleAddTodo}>Add</button> </div> <ul> {todos.map(todo => ( <li key={todo.id} style={{ textDecoration: todo.completed ? "line-through" : "none" }} > {todo.content} <button onClick={() => handleToggleTodo(todo.id)}> {todo.completed ? "Uncomplete" : "Complete"} </button> <button onClick={() => handleDeleteTodo(todo.id)}>Delete</button> </li> ))} </ul> </div> ); }; export default TodoList; ``` 在这个组件中,我们定义了一个状态todos来存储所有的待办事项,以及一个状态inputValue来存储用户输入的新待办事项的内容。我们通过useState Hook来定义这些状态。 我们还定义了三个处理函数handleAddTodo、handleToggleTodo和handleDeleteTodo来添加、切换完成状态和删除待办事项。我们通过map函数来遍历todos数组,以便将每个待办事项渲染为一个li元素。 最后,我们导出TodoList组件。 接下来,在App.tsx中使用TodoList组件: ```tsx import React from "react"; import TodoList from "./TodoList"; const App = () => { return ( <div> <TodoList /> </div> ); }; export default App; ``` 现在,我们就可以在浏览器中查看TodoList应用程序了。 注:在使用前需要先安装React和TypeScript的依赖。在终端中执行以下命令: ```sh npm install react react-dom npm install --save-dev typescript @types/react @types/react-dom ```

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值