美文网首页
react组件化(一)

react组件化(一)

作者: 单只蝴蝶_569d | 来源:发表于2020-02-18 21:43 被阅读0次

    目前主流的框架有react/angular/vue。与angular不同,react是专注于用户界面构建,也就是mvvm中的view层,数据层(Model)和控制层(ViewModel)则是由社区提供的库进行构建。在写react的时候,记住一点:react就是js。

    react脚手架

    npm install -g create-react-app --安装脚手架
    create-react-app my-app --使用脚手架创建react项目
    cd my-app --进入指定项目
    npm start --启动项目

    react基础知识

    jsx简介

    const element = <h1>Hello, world!</h1>;
    如上变量,被成为JSX语言,是javascript的语法扩展,Babel会把JSX转译成React.createElement函数调用。以下2种方式等价

    const element = (
      <h1 className="greeting">
        Hello, world!
      </h1>
    );
    
    const element=React.createElement(
    'h1',
    {className:'greeting'},
    ''Hello World!
    )
    
    • jsx使用
      声明一个变量name,在JSX中使用,写在大括号中。在 JSX 语法中,你可以在大括号内放置任何有效的 JavaScript 表达式。例如,2 + 2user.firstNameformatName(user) 都是有效的 JavaScript 表达式。
    const element=<p onClick={this.changeName} className='zhangsan' style={{coloe:red}}>{name}</p>
    

    在下面的示例中,我们将调用 JavaScript 函数 formatName(user) 的结果,并将结果嵌入到 <h1> 元素中。

    function formatName(user) {
      return user.firstName + ' ' + user.lastName;
    }
    
    const user = {
      firstName: 'Harper',
      lastName: 'Perez'
    };
    
    const element = (
      <h1>
        Hello, {formatName(user)}!
      </h1>
    );
    

    组件

    react的核心就是组件,react组件分为函数类型组件和基于类的组件2种类型
    函数类型的组件就是使用function创建的组件,基于类的组件是使用class关键词创建的组件,组件的本质也是函数。在react中组件名称以大写字母开头。

    • 函数式组件写法
     function Welcome1(props) {
      return <div>Welcome1, {props.name}</div>;
    }
    
    • 基于类的组件写法
    class Welcome2 extends React.Component {
      render() {
        return <div>Welcome2, {this.props.name}</div>;
      }
    }
    
    • 组件的调用
      class Welcome2 extends React.Component {
      render() {
        return <Welcome1 name='张三'></Welcome1>;
      }
    }
    

    state和props

    在react中是单向数据流,顶级组件就有状态state,通过props向下级组件进行传递。下级组件为无状态组件,只能使用props,不能够修改状态。在组件中,不能直接修改state,只能通过setState进行修改组件状态。组件状态的修改是异步的,多次调用会合并成一次进行组件状态的修改。因此如果需要连续多次的修改状态可以使用以下写法

    this.setState(()=>{
        date:new Date()
    })
    
    import React, { Component } from "react";
    
    export default class StateTest extends Component {
      state = {
        counter: 1
      };
    
      componentDidMount() {
        //   请不要直接修改状态值
        //   this.state.counter += 1;
    
        // 2.批量执行
        // this.setState(obj, cb)
        // this.setState(fn, cb)
        this.setState(prevState => ({
          counter: prevState.counter + 1
        }));
    
        this.setState(prevState => ({
          counter: prevState.counter + 1
        }));
    
        this.setState(prevState => ({
          counter: prevState.counter + 1
        }));
      }
    
      render() {
        return <div>{this.state.counter}</div>;
      }
    }
    
    

    组件的嵌套

    组件的嵌套以购物车的实例来进行说明。直接上代码。

    • 将函数和组件状态以props的形式传入下级组件。下级组件均为无状态组件,只负责渲染,逻辑均在顶层组件
    • 函数的绑定与DOM不同的点在于,在DOM中绑定函数名小写,在react中是驼峰命名法。在DOM中函数传入字符串,在react中传入函数体。
    • 在react的使用中,由于this指向问题,在定义函数时,尽量使用箭头函数的方式进行定义
      reduceShopBook=()=>{}
      这样this的指向f方为react实例。
      或者在初始化组件时,使用以下方式来改变this指向
      this.reduceShopBook=this.reduceShopBook.bind(this)
    • 在jsx中可以map来循环数组
    • 在react中可以使用条件判断和三元表达式来确定渲染的元素和组件。
    // 三元表达式
    const isLoggedIn = this.state.isLoggedIn;
     return (
       <div>
         The user is <b>{isLoggedIn ? 'currently' : 'not'}</b> logged in.
       </div>
     );
    
    
     // 使用If条件判断
        const isLoggedIn = this.state.isLoggedIn;
        let button;
    
        if (isLoggedIn) {
          button = <LogoutButton onClick={this.handleLogoutClick} />;
        } else {
          button = <LoginButton onClick={this.handleLoginClick} />;
        }
    
        return (
          <div>
            <Greeting isLoggedIn={isLoggedIn} />
            {button}
          </div>
        );
    
    
    import React from 'react';
    import logo from './logo.svg';
    import './App.css';
    class App extends React.Component{
       constructor(){
         super();
         this.reduceShopBook=this.reduceShopBook.bind(this)
         
       }
      
       state={
        books:[{
          name:'javascrip语言精粹',
          id:'1'
        },{
          name:'javascript高级程序设计',
          id:'2'
        }],
        shopBooks:[
          {
           name:'javascrip语言精粹',
           id:'1',
           count:1
          }
        ]
      }
    
       // 减少数目
       reduceShopBook(bookItem){
         const shopBooks=[...this.state.shopBooks];
         const bookIndex=shopBooks.findIndex((book)=>bookItem.id===book.id)
         if(shopBooks[bookIndex].count===1){ //去掉选项
             shopBooks.splice(bookIndex,1)
         }else{
           const newBook=Object.assign(shopBooks[bookIndex],{count:shopBooks[bookIndex].count-1})
            shopBooks.splice(bookIndex,1,newBook)
         }
         this.setState({shopBooks:shopBooks})
       }
       
       // 增加购物车中数目
       addShopBook=(bookItem)=>{
         let shopBooks=[...this.state.shopBooks];
         const bookIndex=shopBooks.findIndex((book)=>bookItem.id===book.id)
         if(bookIndex===-1){
           bookItem.count=1
           shopBooks=[...shopBooks,bookItem]
         }else{
           const book=Object.assign(shopBooks[bookIndex],{count:shopBooks[bookIndex].count+1})
         }
         this.setState({shopBooks:shopBooks})
       }
    
      // 渲染,调用下级组件。 将函数和组件状态以props的形式传入下级组件。修改组
       render(){
         const bookItems=<BookList books={this.state.books} addShopCart={this.addShopBook}></BookList>
         const shopcart=<Shopcart shopBooks={this.state.shopBooks} addShopBook={this.addShopBook} reduceShopBook={this.reduceShopBook}></Shopcart>
         const footer=<input type='button' value='确定' />
         return <div>
                 {bookItems}
                 {shopcart}
                 </div>
       }
    }
    export default App;
    
    /**
     * 书本列表 组件使用函数式组件,在下级组件中使用函数式组件,写法较为简单。
     * @param {*} props 
     */
    function BookList(props){
      const listItems= props.books.map((bookItem)=>{
        return <li key={bookItem.id}>{bookItem.name} <input type='button' value='加入购物车' onClick={e=>props.addShopCart(bookItem)} /></li>
      })
      return <ul>{listItems}  </ul>
    }
    
    /**
     * 购物车列表 
     * @param {} props 
     */
    function Shopcart(props){
       const shopItems=props.shopBooks.map((bookItem)=>{
         return <tr>
                    <td>{bookItem.name}</td>
                    <td>{bookItem.count}</td>
                    <td><input type="button" value="+" onClick={e=>props.addShopBook(bookItem)}  /><input type='button' value='-' onClick={e=>props.reduceShopBook(bookItem)}/></td>
                  </tr>
       })
    
       return <table>
             <thead><th>名称</th><th>数目</th><th>操作</th></thead>       
             {shopItems}
            </table>
    }
       
    }
    
    

    React中children的使用

    有人说,咦,类似于vue中slot,在react中怎么没有?不急,使用react中使用children属性可实现哦。

    • React中的Children不一定是组件,它们可以使任何东西。从本质上来讲, props.children 可以使任何的类型,比如数组、函数、对象等等。
    • React提供了一系列的函数助手来使得操作children更加方便。
      两个最显眼的函数助手就是 React.Children.map 以及 React.Children.forEach 。它们在对应数组的情况下能起作用,除此之外,当函数、对象或者任何东西作为children传递时,它们也会起作用。
    • 直接来个例子,封装一个弹出框,外层样式统一定义,内容和样式可定义。封装一个过滤器
    // 容器类组件 不需要知道状态
    // 作为容器 不需要关心状态和逻辑
    function Dialog(props){
      return <div style={{border:`1px solid ${props.color||'blue'}`}}>
                 {props.children}
                 {props.footer}
            </div>
    }
    
    // 使用封装好的弹出框
    function WelcomeDialog(props){
       return <Dialog {...props}>
              <p>hello world</p>
             </Dialog>
       
    }
    // 过滤器
    function Filter(props){
      return<div>
       { 
        React.Children.map(props.children,(element)=>{
          if(element.type===props.type){
             return element
          }
       })
      }
    
      </div>
       
    }
    class  App extends React.Component{
     render(){
        const footer=<input type='button' value='确定' />
         return <div>
                        <WelcomeDialog color="green" footer={footer}></WelcomeDialog>
                      <Filter type='p'>
                          <p>1、p标签的使用</p>
                         <span>2、span标签</span>
                     </Filter>
                </div>
       }
    }
    }
    

    相关文章

      网友评论

          本文标题:react组件化(一)

          本文链接:https://www.haomeiwen.com/subject/kkenfhtx.html