React基础用法

React基础

脚手架安装

npm install create-react-app

安装完成以后,在控制台输入如下命令,验证是否安装成功

create-react-app --version

脚手架创建项目

create-react-app 项目名称

脚手架项目结果

image-20201023084047192
1.public是公开文件夹
2.src目录是开发目录

  • index.js是整个程序的启动目录,也是webpack的入口文件
  • index.css是程序程序的公共CSS文件,如果需要写公共CSS文件最好写在这里
  • App.js是根组件,在React里面,这就是一个根组件,React的组件是以JS文件的形式存在
  • App.css是App.js组件的样式,一般情况下,一个JS文件会对应一个CSS文件
  • serviceWorker.js是在开发React的时候启动的http服务器

分析React脚手架项目的启动

index.js文件

import React from 'react';					//导入React,一定要导,即使你没有用
import ReactDOM from 'react-dom';			//因为主要是操作DOM,所以这个是React操作DOM的
import './index.css';						//导入样式文件
import App from './App';					//导入App.js,它是一个组件
import * as serviceWorker from './serviceWorker';  //启用动开的时候后台服务,开启HMR热模块
//下面的代码就相当于 Vue当中的new Vue({})的代码。创建实例,接管区域,渲染组件
ReactDOM.render(
  <React.StrictMode>
    <App />
  </React.StrictMode>,
  document.getElementById('root')
);
// If you want your app to work offline and load faster, you can change
// unregister() to register() below. Note this comes with some pitfalls.
// Learn more about service workers: https://bit.ly/CRA-PWA
serviceWorker.unregister();		      //当程序退出的时候,退出后台

React当中的语法使用的是JSX的语法,它不是完全的JS语法

认识JSX语法

它是一种全新的语法,也是比较流行一种语法,它将JS语法与HTML语法来进行混合使用,就是说可以在写JS的时候去插入HTML代码

React的开发完全用ES6及JSX 的语法,JSX本质上面所做的事情还是MVVM 的,只是换了一种方式在操作,它里面也有条件渲染,列表渲染,属性渲染,事件处理,组件化等操作(这些操作都是Vue当中自带的,只是在React里面要自己手写)

创建组件

在React当中一切皆组件,所以我们可以把CSS与好,JS也好都看成是一个组件,在目前创建组件的时候有两种方式,也就是目前React开发的两种方式

  1. 基于class的开发
  2. 基于React Hooks Api的开发(这是目前新堆出来的一种开发方式)
import React from "react";      //导入React
class App extends React.Component{
    
    
  //在组件的内部,必须有一个方法render,这个方法负责在页面上面渲染数据
  render(){
    
    
    //render函数return的东西就是页面上面显示的东西
    //在return的后面只能有一个根标题,与vue当中的template一样,也只能也有一个根标签
    return (
      <div>
        <h1>这是一个1号标题</h1>
        <h1>这是一个2号标题</h1>
      </div>
    );
  }
}

export default App;

注意事项:组件的名称一定是大写开头的

扫描二维码关注公众号,回复: 12651569 查看本文章

普通数据渲染

React最主要的一点就是与Vue是一样的,都是数据驱动页面,关注数据的变化就可以了,所以在React当中,它的数据应该在哪里呢?怎么渲染呢?

在Vue当中,我们的数据来源于三个地方,第一个是data,第二个是computed,第三个来源于父级props

在React当中,它的数据主要来源于两个地方,第一个是自身的数据state,第二个是父级数据props

render(){
    
    
    //render函数return的东西就是页面上面显示的东西
    //在return的后面只能有一个根标题,与vue当中的template一样,也只能也有一个根标签
    return (
      <div>
        <h1>这是一个1号标题------  {
    
    this.state.userName}   </h1>
        <h1>这是一个2号标题</h1>
      </div>
    );
  }

在JSX语法里面,如果在HTML标签当中要嵌入JS代码 则使用{}包裹就可以了

条件渲染

//在组件的内部,必须有一个方法render,这个方法负责在页面上面渲染数据
  render(){
    
    
    //render函数return的东西就是页面上面显示的东西
    //在return的后面只能有一个根标题,与vue当中的template一样,也只能也有一个根标签
    return (
      <div>
        <h1>这是一个1号标题------  {
    
    this.state.userName}   </h1>
        <h1>这是一个2号标题</h1>
        <hr />
        <p>{
    
    this.state.age>=18?'成年':'未成年'}</p>
        <hr />
        {
    
    this.state.age>=18&&<h2>这是一个非常好看的标签,age大于等于18就显示,否则就隐藏,怎么办?</h2>}
      </div>
    );
  }

React当中的条件渲染使用的是之前ES基础里面的逻辑操作符的特性短路原则来实行的

列表渲染

React当中的列表渲染借助于是数组语法,在数组语法当中,我们有一个map方法

<ul>
    {
    
    this.state.stus.map((item,index)=>{
    
    
        return <li key={
    
    index}>{
    
    item}</li>
    })}
</ul>

在做列表渲染的时候,与Vue一样,在每个渲染的元素上面要添加一个特殊的属性key,保证它的唯一性

**注意事项:**在React当中会大量使用箭头函数,箭头函数后面是否跟花括号是完不一样的

上面的代码如果不跟花括号,可以写成如下。因为不跟花括号{}则代表后面的东西是返回值

<ul>
    {
    
    this.state.stus.map((item,index)=>
        <li key={
    
    index}>{
    
    item}</li>
    )}
</ul>

**扩展:**如果我们现在需要在页面上面渲染10个button应该怎么办呢?

renderButton(){
    
    
    let arr = [];
    for(var i=0;i<10;i++){
    
    
      arr.push(<button type="button">按钮{
    
    i}</button>)
    }
    return arr;
  }
render(){
    
    
    return (
      <div> 
        {
    
    this.renderButton()}
        </div>
    );
}

在JSX代码当中可以直接把一部分代码重新封装成方法再进行。同时我们得出一些,列表渲染是需要得到一个数组再渲染

属性渲染

在Vue当中Vue如果要渲染属性需要使用v-bind:属性名来进行绑定,但是在React当中完全没有必要,还是直接使用JSX语法就行了

<button type="button" abc={
    
    userName}>   按钮 </button><a href={
    
    this.state.url1}>百度一下,你就知道</a>

始终记得一点,{}里面的就是JS代码就可以了

样式设置

在React的JSX语法当中,有一点与众不同就是样式的设置,因为在JSX的内部class是一个关键字,所以在设置元素的样式的时候,已经不能使用class来设置,要转而使用另一个关键字className

App.css文件

.box1{
    
    
  width: 100px;
  height: 100px;
  border: 2px solid red;

App.js文件

import "./App.css";             //导入CSS文件  
<div className="box1">这是一个盒子</div>

重点:在之前的Vue里面,我们的<style scoped></style> 会有一个scoped的属性,这个属性主要用于设置当前Vue文件内部的样式只作用于当前的<template>,那么在React当中应该怎么实现这个功能呢?
上面的我们直接使用<div className="box1">这是一个盒子</div>这是一个最普通的方式,它没有实现CSS的模块化

  1. 先将CSS文件名添加一个.module,如原来的App.css就会变成App.module.css文件

  2. 在App.js当中去导入的时候变成如下代码

import AppStyle from “./App.module.css”;

  1. 在使用的样式的时候应该如下使用
这是另一个盒子

动态样式绑定

constructor(){
    
    
    super(...arguments);
    this.state={
    
    
        navType:1
    }
}
 render(){
    
    
     return (
         <div>
             <ul className="navType">
                 <li className={
    
    this.state.navType==0?'selected':null}>正在热映</li>
                 <li className={
    
    this.state.navType==1?'selected':null}>即将上映</li>
             </ul>
         </div>
     );
 }

如果class的样式需要叠加的时候,在React当中会比较麻烦,但仍然有两种写法

1.借用ES6当中的模板字符串去完在

<ul className="navType">
    <li className={
    
    `abc ${
      
      this.state.navType===0?'selected':null}`}>正在热映</li>
    <li className={
    
    `abc ${
      
      this.state.navType===1?'selected':null}`}>即将上映</li>
</ul>

2.借用数组去完成

<ul className="navType">
    <li className={
    
    ["abc",this.state.navType===0?'selected':null].join(' ')}>
        正在热映
    </li>
    <li className={
    
    ["abc",this.state.navType===1?'selected':null].join(' ')}>
        即将上映
    </li>
</ul>

在React当中,React不建议我们去使用style去设置属性,但是并不是不能,如果要用可以按下面的方式来使用

this.state={
    
    
    styleObj:{
    
    
        width:"100px",
        height:"100px",
        border:"1px solid black"
    }
}
<div style={
    
    this.state.styleObj}>
    这是一个盒子
</div>

上面就是设置style的过程,我们看起来操作很麻烦,需要先定义一个对象,然后style再去引用这个对象,但是我们平常在开发的时候,可能就直接写成下面的样式了

<div style={
    
    {
    
    width:"100px",height:"100px",border:"1px solid red"}}>
    这又是一个盒子
</div>

组件化

之前已经学过了组件的创建,在本个环节,我们主要两个点

  1. 父级组件如何向子级组件传值
  2. 之前在vue当中的<slot>在React是如何实现的

父级组件向子级组件传值
App.js文件

<Home abc={
    
    this.state.userName} userAge={
    
    this.state.userAge}>
</Home>

Home.js文件

<h2>{
    
    this.props.abc}--------{
    
    this.props.userAge}</h2>

React当中的自定义属性是支持驼峰命名的

Vue中Slot的实现方式
在以前的时候Vue可以通过Slot来向子组件的某个地方去插入数据,在React当中也有类似的实现的方式

App.js文件中,我们在<Home>组下面插入了一个东西

<Home abc={
    
    this.state.userName} userAge={
    
    this.state.userAge}>
    <button type="button">这是通过Slot进来的</button>
</Home>

Home.js的文件中,怎么接收插入的内容呢

<div>
    {
    
    this.props.children}   
</div>

this.props.children就是插槽的数据

事件及事件处理

在React的JSX的语法当中,它的事件也是支持的,但是它的事件与做了相应的转换过程,如下所在

  1. onclick转变成了onClick
  2. onchange转变成了onChange

以前的事件名是全小写,现在on后面根的事件类型名变成了大写

 test(){
    
    
     console.log(this);
     alert("你好啊");
 }
<button type="button" onClick={
    
    this.test.bind(this)}>按钮2</button>

所以在上面的的样式绑定里面,我们可以通过事件去改变navType以实现样式的改变

changeNavType(type){
    
    
    console.log(type);
    // 如果要改变state 的状态,要调用setState的方法
    this.setState({
    
    
        navType:type
    });
}

<ul className="navType">
    <li onClick={
    
    this.changeNavType.bind(this,0)} 
        className={
    
    ["abc",this.state.navType===0?'selected':null].join(' ')}>
        正在热映
    </li>
    <li onClick={
    
    this.changeNavType.bind(this,1)} 
        className={
    
    ["abc",this.state.navType===1?'selected':null].join(' ')}>
        即将上映
    </li>
</ul>

React当中的单页面开发

在Vue当中Vue为了实现单页面开发使用的是vue-router来跳转页面,而在React里面,它也有路由,它使用的是下面两个包

  1. react-router
  2. react-router-dom

这两个包的配置与vue-router截然不同

安装路由的包

yarn add react-router react-router-dom --dev

配置路由

路由的配置方式有两种,第一种使用嵌套的方式在组件内部写,如下

App.js文件

import React from 'react';
import './App.css';
import {
    
     HashRouter, Route, Switch } from "react-router-dom";
import Home from "./views/Home/Home";
import Detail from "./views/Detail/Detail";

class App extends React.Component {
    
    
  //当一个路由嵌套另一个路由的时候,一定不能添加exact
  render() {
    
    
    return (
      <HashRouter>
        <Switch>
          <Route path="/Home" component={
    
    Home}></Route>
          <Route path="/Detail" component={
    
    Detail} exact></Route>
        </Switch>
      </HashRouter>
    );
  }
}
export default App;

Home.js文件

import React from "react";
import HomeStyle from "./Home.module.scss";
import ChooseFood from "../ChooseFood/ChooseFood";
import Order from "../Order/Order";
import {
    
     Route } from "react-router-dom";

class Home extends React.Component{
    
    
    render(){
    
    
        return(
            <div className={
    
    HomeStyle.homePage}>
                <div className={
    
    HomeStyle.routerBox}>
                    <Route path="/Home/ChooseFood" component={
    
    ChooseFood} exact></Route>
                    <Route path="/Home/Order" component={
    
    Order} exact></Route>
                </div>
                <ul className={
    
    HomeStyle.tabBar}>
                    
                </ul>
            </div>
        );
    }
}
export default Home;

路由在渲染组件的时候,可以使用两种方式

<HashRouter>
    <Switch>
        <Route path="/Home" component={
    
    Home}></Route>
        <Route path="/Detail" exact render={
    
    props => {
    
    
                return <Detail></Detail>
            }}></Route>
    </Switch>
</HashRouter>

第一种是直接使用component属性来渲染,第二种则是手动的调用render函数,然后返回一个组件

我们的路由的第二种配置就是使用第二种render函数来的

App.js的配置方法

import React from 'react';
import './App.css';
import {
    
     HashRouter, Route, Switch,Redirect } from "react-router-dom";
import Home from "./views/Home/Home";
import ChooseFood from "./views/ChooseFood/ChooseFood";
import Category from "./views/Category/Category";
import Order from "./views/Order/Order";
import MySelf from "./views/MySelf/MySelf";
import Detail from "./views/Detail/Detail";

class App extends React.Component {
    
    
  //当一个路由嵌套另一个路由的时候,一定不能添加exact
  render() {
    
    
    return (
      <HashRouter>
        <Switch>
          <Redirect path="/" to="/Home/ChooseFood" exact></Redirect>
          <Route path="/Home" render={
    
    props => {
    
    
            return <Home {
    
    ...props}>
              <Route path="/Home/ChooseFood" component={
    
    ChooseFood} exact></Route>
              <Route path="/Home/Order" component={
    
    Order} exact></Route>
              <Route path="/Home/Category" component={
    
    Category} exact></Route>
              <Route path="/Home/MySelf" component={
    
    MySelf} exact></Route>
            </Home>
          }}></Route>
          <Route path="/Detail" component={
    
    Detail} exact ></Route>
        </Switch>
      </HashRouter>
    );
  }
}

export default App;

Home.js页面

<div className={
    
    HomeStyle.homePage}>
    <div className={
    
    HomeStyle.routerBox}>
        {
    
    this.props.children}
    </div>
    <div className={
    
    HomeStyle.tabBar}>
        <NavLink to="/Home/ChooseFood" activeClassName={
    
    HomeStyle.active}>
            <span className="iconfont iconcanju" style={
    
    {
    
    fontSize:"22px"}}></span>
            点餐
        </NavLink>
        <NavLink to="/Home/Order" activeClassName={
    
    HomeStyle.active}>
            <span className="iconfont icondingdan" style={
    
    {
    
    fontSize:"22px"}}></span>
            订单
        </NavLink>
        <NavLink to="/Home/Category" activeClassName={
    
    HomeStyle.active}>
            <span className="iconfont iconfenlei" style={
    
    {
    
    fontSize:"22px"}}></span>
            分类
        </NavLink>
        <NavLink to="/Home/MySelf" activeClassName={
    
    HomeStyle.active}>
            <span className="iconfont iconyonghuming" style={
    
    {
    
    fontSize:"22px"}}></span>
            我的
        </NavLink>
    </div>
</div>

如果需要通过JS的方法去跳转面页面,则可以找this.props.history这个对象,它相当于Vue里面的this.$router

猜你喜欢

转载自blog.csdn.net/weixin_48255917/article/details/109244000