React学习总结

前言

前端可以做到读写数据、切换视图、用户交互,这意味着,网页其实是一个应用程序,而不是信息的纯展示。这种单张网页的应用程序称为 SPA(single-page-application)。
2010年后,前端工程师从开发页面(切模板),逐渐变成了开发“前端应用”(跑在浏览器里面的应用程序)。目前,最流行的前端框架 Vue、Angular、React 等等,都属于 SPA 开发框架。

react脚手架建立工程

1、安装

npm install create-react-app -g

2、创建

create-react-app react-demo  (react-demo项目名)

3、初始化

cd react-demo 
npm install  or cnpm install or yarn install

4、运行

yarn start

创建一个helloWorld Demo

引入模块

//第一步 导入react
import React,{Component} from 'react';
import '../assets/css/index.css'
import logo from '../assets/images/logo.svg';
import '../assets/css/App.css';
/**
 * 绑定原生属性注意:
 * class 要换成className
 * for 要换成htmlFor
 * style 要用{}包裹成对象 
 */

//第二步,编写组件类并继承React.Component
class Home extends Component{
    constructor(){
        super();
        //定义数据
        this.state={
            msg:'你好,世界!'

        }
    }
//第三步,重写render()方法,用于渲染页面
    render(){
        return (
            <div>
               <h1>{this.state.msg}</h1>
               <img src={logo} width='500px'></img>
            </div>
            

        );
    }
}

//第四步,导出该类
export default Home;

然后启动工程即可完成一个简单的demo

yarn start

在这里插入图片描述

react是面向组件的,通过JSX语法来操作虚拟dom节点,如果state的数据发生了变化则会触发对应的dom的刷新。JSX语法就是,可以在js文件中插入html片段,是React自创的一种语法。JSX语法会被Babel等转码工具进行转码,得到正常的js代码再执行。所有标签必须闭合

注意在本地引用img等资源时,需要通过{xx}对象形式引用。如果是网络图片,直接用url引用即可。

JSX语法就是,可以在js文件中插入html片段,是React自创的一种语法。JSX语法会被Babel等转码工具进行转码,得到正常的js代码再执行。所有标签必须闭合

react 通过state来定义和绑定数据,但这种绑定并不是MVVM那种双向数据绑定,在JSX中要使用时通过 this.state.xxx来使用

知识点:

1. 目录结构分析

在这里插入图片描述
用脚手架创建的工程的目录是有些不完整的,需要补全(为了方便归档)
component文件主要放组件,model放数据模型,App.js是默认的根组件,index.js是入口文件,相当于main,yarn.lock是项目生成的临时文件,package.json是依赖管理文件(类似maven的pom文件),nodel_modules是存放依赖包的文件夹

2. 创建组件

第一步 导入react
第二步,编写组件类并继承React.Component
第三步,重写render()方法,用于渲染页面
第四步,导出该类

3. JSX注意事项

如果要在模板中嵌套多个HTML标签,需要使用一个父元素对其进行包裹

            <div>
               <h1>{this.state.msg}</h1>
               <img src={logo} width='500px'></img>
            </div>

4.绑定数据或对象

js中定义对象用{},其实就是restful风格的东东。
类似于

{
	title:"xxx",
	content:"xxxx"
}

数据的定义用[ ],一对方括号即可。
在react中绑定对象只需要在state中定义即可

this.state={
            msg:'你好,世界!'
       }

事件及数据绑定Demo

import React from 'react'

class Demo1 extends React.Component{
    constructor(props){
        super(props);
        this.state={
            msg:"demo1组件",
            text:"",
            keydown:"",
        }
    }

    run=(e)=>{
        alert(e.target.getAttribute('id')) //获取当前执行事件的dom节点
        e.target.style.background='red';

    }

    inputChange=(e)=>{
        //获取表单的值
        //console.log(e.target.value);
        this.setState({
            text: e.target.value
        })
    }

    inputChange1=()=>{
        let value = this.refs.input.value;
        this.setState({
            text: value
        })
    }

    getInputValue=()=>{
        alert(this.state.text)
    }

    inputOnKeydown = (e)=>{
        console.log(e.keyCode);
        this.setState({
            keydown:e.keyCode
        })
    }

    inputChange2 = (e)=>{
        this.setState({
            text:e.target.value
        })
    }

    changeTextMode = (e)=>{
        this.setState({
            text:"改变后的model值,可以看到下面这个输入框的数据已经改变,而上面两个输入框未发生变化"
        })
    }

    render(){
        return (
             <div>   
                <hr></hr>
                <h2>事件对象演示</h2>       
                {this.state.msg}
                {/* 事件对象 */}
                <button id='buttonId' onClick={this.run}>事件对象</button>
                <hr></hr>
                <h2>表单事件演示</h2>       
                <p>{this.state.text}</p>
                <input type="text" onChange={this.inputChange}/>
                <button onClick={this.getInputValue}>获取表单值</button>
                <hr></hr>
                <h2>ref获取dom节点,获得表单值</h2>    
                <p>{this.state.text}</p>   
                <input ref='input' type="text" onChange={this.inputChange1}/>
                <button onClick={this.getInputValue}>获取表单值</button>
                <hr></hr>
                <h2>键盘事件</h2>    
                <p>{this.state.keydown}</p>
                <input type="text" onKeyDown={this.inputOnKeydown}/>
                <hr></hr>
                <h2>react实现双向数据绑定</h2>    
                <p>model改变影响view(通过value属性),view改变影响model</p>
                <p>model值:{this.state.text}</p> 
                <input type='text' value={this.state.text} onChange={this.inputChange2}></input>
                <button onClick={this.changeTextMode}>改变model的值</button>
            </div>
        )
    }

}

export default Demo1 ;

在这里插入图片描述

知识点:

事件绑定:

  1. 绑定事件需要在对应的事件响应中获得正确的this对象
    例如:为Button 绑定了一个事件
<button id='buttonId' onClick={this.run}>事件对象</button>

如果你用箭头函数写响应方法,则this指向的就是react的当前组件

    run=(e)=>{
        alert(e.target.getAttribute('id')) //获取当前执行事件的dom节点
        e.target.style.background='red';

    }

如果你用的是普通写法写的函数响应

    funtion run(e){
        alert(e.target.getAttribute('id')) //获取当前执行事件的dom节点
        e.target.style.background='red';
    }

需要使用下面这种写法传递对象指向

<button id='buttonId' onClick={this.run.bind(this)}>事件对象</button>

数据绑定(View->Model)

<p>{this.state.text}</p>
<input type="text" onChange={this.inputChange}/>
    inputChange=(e)=>{
        //获取表单的值,设置model的数据
        //console.log(e.target.value);
        this.setState({
            text: e.target.value
        })
    }

数据绑定(Model->View)

<button onClick={this.getInputValue}>获取表单值</button>
getInputValue=()=>{
        alert(this.state.text) //获取model中的数据
  }

双向数据绑定(M->V&V->M 俗称MVVM)

<h2>react实现双向数据绑定</h2>    
<p>model改变影响view(通过value属性),view改变影响model</p>
<p>model值:{this.state.text}</p> 
<input type='text' value={this.state.text} onChange={this.inputChange2}></input>
<button onClick={this.changeTextMode}>改变model的值</button>

value 通过属性绑定model 完成 m->v的绑定
通过监听onChange完成v->m的绑定 ,和上面那个View->Model的绑定是一样的。

TodoList小练习

该练习的旨在熟悉双向数据绑定和react的基础用法,另外扩展了localStorage缓冲处理方案,实现刷新不会丢失数据状态。
在这里插入图片描述

import React, {Component}from 'react';
import Storage from '../model/storage'

class Demo3 extends Component {
    constructor(props) {
        super(props);
        this.state = { 
            todo:'',
            todolist:[],
         };
    }

    //生命周期函数,页面加载触发
    componentDidMount=()=>{
        let list = Storage.get('todolist');
        if(list){
            console.log("get:"+list)
            this.setState({
                todolist:list
            })
        }
    }

    addTodoText=(e)=>{
        this.setState({
            todo: e.target.value
        })
        
    }
    onAddBtnClick=()=>{
        let todolist = this.state.todolist;
        
        todolist.push({
            todo:this.state.todo,
            checked:false
        })
        this.setState({
            todolist:todolist,
            todo:""
        })
        //缓存数据
        Storage.set("todolist",todolist);
    }

    onPressEnter=(e)=>{
        if(e.keyCode==13){
            this.onAddBtnClick();
        }

    }

    ondelBtnClick=(index)=>{
        let todolist = this.state.todolist;
        todolist.splice(index,1);
        this.setState({
            todolist:todolist
        })
        //缓存数据
        Storage.set("todolist",todolist);
    }

    checkChange = (index)=>{
        let todolist = this.state.todolist;
        todolist[index].checked=!todolist[index].checked;
        this.setState({
            todolist:todolist
        })
        //缓存数据
        Storage.set("todolist",todolist);
    }

    render() {
        return (
            <div>
                <h2>todoList 演示</h2>
                
                <header><input type="text" value={this.state.todo} onChange={this.addTodoText} onKeyDown={this.onPressEnter}/> <button onClick={this.onAddBtnClick}>增加</button></header>
                <hr></hr>
                <h4>未完成事项</h4>
                <ul>
                    {
                        this.state.todolist.map((value,index)=>{
                            if(!value.checked){
                                return (
                                    <div key={index}>
                                        <input type='checkbox' checked={value.checked} onChange={this.checkChange.bind(this,index) }/>-----{value.todo} <button onClick={this.ondelBtnClick.bind(this,index)}>删除</button>
                                    </div>
                                )
                            }
                            
                        })
                    }
                </ul>
                <hr></hr>
                <h4>已完成事项</h4>
                <ul>
                {
                        this.state.todolist.map((value,index)=>{
                            if(value.checked){
                                return (
                                    <div key={index} className='complete'>
                                        <input type='checkbox' checked={value.checked} onChange={this.checkChange.bind(this,index) }/>-----{value.todo} <button onClick={this.ondelBtnClick.bind(this,index)}>删除</button>
                                    </div>
                                )
                            }
                            
                        })
                    }
                </ul>
            </div>
        );
    }
}

export default Demo3;



远程请求数据Demo

通过axios向服务端请求数据,我这里没有通过配置代理解决跨域问题,而是在后端配置了取消CROS请求来解决跨域问题

import React from 'react'
import axios from 'axios'
import request from '../model/server'
import jsonp from 'fetch-jsonp'

class Demo4 extends React.Component {
    constructor(props) {
        super(props);
        this.state = { 
            list:[],
         };
    }
     getData = ()=>{
         let api = 'http://localhost:18080/house/resources/findAll'
        axios.get(api)
        .then((response)=>{
            console.log(response)      
            this.setState({
                list:response.data
            })
        })
        .catch((error)=>{
            console.log(error)
        })
        // let data =await request.get(api)
        // console.log(data)
    }

    render() {
        return (
           <div>
               <h2>axios获取服务器数据,未处理跨域,取消cros</h2>
                <button onClick={this.getData}>获取服务器数据</button>
                <p>url:<a href='http://localhost:18080/house/resources/findAll'>http://localhost:18080/house/resources/findAll</a></p>
                <ul>
                    {
                        this.state.list.map((value,index)=>{
                            return (
                                <li key={index}>{value.created}</li>
                            )
                        })
                    }
                </ul>
                <h2>jsonp获取服务器数据,跨域请求</h2>
                <p>怎么看,看你的地址加入callback=xxx之后是否能访问就知道是否支持jsonp了</p>


           </div> 
        );
    }
}

export default Demo4;

在这里插入图片描述

知识点:

1. 跨域问题

所谓跨域问题就是 协议,域名,端口三者有其一不一致则出现跨域,一般情况下跨域是不被浏览器支持的。

2. axios

Axios 是一个基于 promise 的 HTTP 库,可以用在浏览器和 node.js 中。
使用

npm install --save axios

React-router 4.x基本配置及动态路由使用

安装

cnpm install react-router-dom --save

引入

import {BrowserRouter as Router,Route,Link} from 'react-router-dom'

基本使用:

<Router>
         <div>
                  <header className='header'>
                          <Link to="/">首页</Link><br/>
                          <Link to="/news">新闻</Link>
                  </header>
         </div>
               <hr/>
          <div>
                <Route exact path="/" component={Home} />
                <Route path='/news' component={News}/>
                <Route path='/content/:aid' component={Content}/>
          </div>
</Router>

router


在这里插入图片描述

动态路由的使用

定义路由
 <Route path='/content/:aid' component={Content}/>
使用路由
{
       this.state.list1.map((value,key)=>{
              return (
              //ES6模板字符串写法
              <Link to={`/content/${value.aid}?content=${value.content}`} key={key}>
              <li>{value.title}</li>
              </Link>
                        )
         })
}
在子组件中获得动态路由的传参
aid:this.props.match.params.aid,

在prps.match.params中获取传参即可

利用get实现动态路由

无需定义路由格式,直接使用,在路由后面像get方法一样传参
类似"?name=zhong"这种

使用路由
 <Link to={`/content/${value.aid}?content=${value.content}`} key={key}><li>{value.title}</li></Link>

其中
?content=${value.content} 就是使用了get传参

在子组件中获得动态路由的传参
    componentDidMount(){
        //通过npm带的url模块解析get参数 cnpm install url --save 安装即可
        console.log(url.parse(this.props.location.search,true))
        let news = {
            aid:this.props.match.params.aid, //通过动态路由传值
            content:url.parse(this.props.location.search,true).query.content, //通过get传值
        }
        this.setState({
            news:news
        })
    }

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值