react 和 vue 的比较

比较 vue

react   (npx create-react-app my-app)

点击事件和类的命名
<div @click="toclick"  class='btn'></div>
<div className="img-wrap"  onClick={() => this.toMv(item.id)}>
或者<div className="img-wrap"  onClick={this.click}>       click=()=>{this.toMv(item.id)}
动态添加类名
:class={aaa:this.aa  === 2}
动态添加单类名:  <div className={index===1?'active':null}>  </div>
已经有类名,在动态添加类名:  <div className={ `box${classA}${index===1?‘active’:null }` } ></div>
         或者:<div className={ [ classA,'box',index===1? ‘active’:null ].join(' ') } ></div>    join() 方法用于把数组中的所有元素放入一个字符串。
更改数据 this.data = '123' 或者 数组 $set 
this.setState({ liked: true })  每次在组件中调用 setState 时,React 都会自动更新其子组件。
条件选择 v-if   v-else-if  v-else  if(){return  ...}else{return ...}   //    this.a?(return ...):(return ...)   //   this.a&&console.log(123444)
列表渲染 v-for=(item,index) in list  this.list.map(item=>{<li  key={item.id}>{item.name}<li> })    map遍历谁,就要给谁加key 
样式处理 动态添加类名:   :class={redColor:this.ee===2}

行内样式  <div  style={{'color:'red','backgroundColor':'pink'}}>233<div>

 

类名: <div className='aaaa'  style={{'color:'red','backgroundColor':'pink'}}>233<div>   .aaaa{ text-align: center}

组件创建 方式  

1.使用函数创建组件 (函数名称首字母大写,函数组件必须有返回值,返回值为null,表示不渲染)  function Hello(){return ( <div>这是第一个函数组件</div>)}

2.类组件  使用es6的语法创建的组件(类首字母大写,类组件要继承React.Component父类,可以使用父类提供的方法或者属性,必须提供render方法及返回值)   class  Hello extends React.Component{

  render(){

    return (<div>这是第一个类组件</div>)

  }

}

事件处理 @加事件名字

on+事件名称 = 事件处理函数   onClick= function(){} 事件命名采取驼峰命名

export default class extends React.Component {
  clickHandle(e){
    console.log('点了')
  }
  render(){
    return (
      <div><button onClick = {this.clickHandle}>点我点我点我</button></div>
      )
    }
}

类组件与函数组件绑定事件是差不多的,只是在类组件中绑定事件函数的时候需要用到this,代表指向当前的类的引用,在函数中不需要调用this

 事件对象  类似  通过事件处理函数的参数获取到的事件对象  e   e.nativeEvent   e.preventDefault() 取消事件的默认动作。  e.stopPropagation() 阻止事件冒泡
State SwtState

state 是数据,是组件里面的私有数据,只能在组件内部使用,通过this.state来获取状态

export default class extends React.Component {
    constructor(){
        super()

        // 第一种初始化方式
        this.state = {
            count : 0
        }
    }
    // 第二种初始化方式
    state = {
        count:1
    }
    render(){
        return (
            <div>计数器 :{this.state.count}</div>
        )
    }
}

 

setState 修改状态  this.setState({要修改的数据})  作用修改state  更新ui  

事件绑定this指向  

1.利用箭头函数自身不绑定this的特点   即绑定事件使用箭头函数   2.使用bind 更改this里面的指向  使用函数 需要使用bind改变this

class App extends React.Component {
  constructor() {
    super()
    ...
    // 通过bind方法改变了当前函数中this的指向
    this.onIncrement = this.onIncrement.bind(this)
  }
  // 事件处理程序
  onIncrement() {
    ...
  }

  render() {
    ...
  }
}

 

受控组件  无  v-model双向绑定

受控组件:值受到react控制的表单元素

state添加一个值,绑定表单里面的value值,然后通过给表单绑定change事件,设置state的值

inputChange(e){
   let target = e.target;
   let value = target.type == 'checkbox' ? target.checked : target.value;  // 如果类型是checkbox,表示改变是否被选中,true,false
   this.setState({
       [e.target.name]: value
   })
}
<input type="text" value={this.state.txt} name="txt" onChange={this.inputChange}/>
<input type="checkbox" value={this.state.isChecked} name="isChecked" onChange={this.inputChange}/>

 

非受控组件  this.$ref 来获取dom节点

借助于ref,使用元素DOM方式获取表单元素值 ref的作用:获取DOM或者组件

class App extends React.Component {
    constructor(){
        super()
        
        //创建 ref
        this.txtRef = React.createRef()
    }
    // 获取文本框的值
    getTxt =() => {
        console.log(this.txtRef.current.value)
    }
    render(){
        return (
          <div>
            <input type ="text" ref={this.txtRef} />
            <button onClick ={this.getTxt}>获取值</button>
          </div>
        )
    }

 

案列:渲染评论列表  
import React, { Component } from "react";
import "./index.scss";
class index extends React.Component {
  state = {
    comments: [
      { id: 1, name: "jack", content: "沙发!!!" },
      { id: 2, name: "rose", content: "板凳~" },
      { id: 3, name: "tom", content: "楼主好人" },
    ],
    comment: "",
    sName: "",
  };
  changeValue = (e) => {
    this.setState({
      [e.target.name]: e.target.value,
    });
  };
  topinglin = () => {
    
    let {sName,comment} = this.state
    if(sName.trim()===''|| comment.trim()===''){
        alert('请输入内容')
        return
    }
    let newArr = [
        {
            id: this.state.comments.length + 1,
            name: sName,
            content: comment,
        },...this.state.comments
    ]

    this.setState({
      comments: newArr,
      comment: '',
      sName:'',
    });
  };
  renderList = () => {
    if (this.state.comments.length === 0) {
      return <div className="no-comment">暂无评论,快去评论吧~</div>;
    } else {
      return (
        <ul>
          {this.state.comments.map((item) => {
            return (
              <li key={item.id}>
                <h3>{item.name}</h3>
                <p>{item.content}</p>
              </li>
            );
          })}
        </ul>
      );
    }
  };
  render() {
    return (
      <div className="app">
        <div>
          <input
            className="user"
            name="sName"
            type="text"
            value={this.state.sName}
            onChange={this.changeValue}
            placeholder="请输入评论人"
          />
          <br />
          <textarea
            name="comment"
            className="content"
            cols="30"
            rows="10"
            placeholder="请输入评论内容"
            value={this.state.comment}
            onChange={this.changeValue}
          />
          <br />
          <button onClick={this.topinglin}>发表评论</button>
          {this.renderList()}
        </div>
      </div>
    );
  }
}
export default index;

 

 传值

 父--> 子  props

 子-->父   $emit

兄弟  bus

 函数组件通过 参数 props接收数据,类组件通过 this.props接收数据    props是只读属性,不能对值进行修改     使用类组件时,如果写了构造函数,应该将props传递给super(),否则,无法在构造函数中获取到props,其他的地方是可以拿到的

 

 

 父--> 子    父组件提供要传递的state数据   给子组件标签添加属性,值为state中的数据   子组件中通过props接收父组件中传递的数据

 

 

子 -- > 父  

利用回调函数,父组件提供回调,子组件调用,将要传递的数据作为回调函数的参数   父组件提供一个回调函数,用来接收数据  将该函数作为属性的值,传递给子组件

(假设父组件有删除的方法,子组件想调用,需要父组件将方法传过去,子组件接受方法调用)

 

 

 

兄弟组件传值:

  • 将共享状态(数据)提升到最近的公共父组件中,由公共父组件管理这个状态

  • 这个称为状态提升

  • 公共父组件职责:1. 提供共享状态 2.提供操作共享状态的方法

  • 要通讯的子组件只需要通过props接收状态或操作状态的方法

 

props进阶  

props的children属性 :表示组件标签的子节点,当组件标签有子节点后,props就有该属性   children属性与普通的props一样,值可以使任意值(文本、react元素、组件、甚至是函数)

props校验  

对于组件来说,props是外来的,无法保证组件使用者传入什么格式的数据,简单来说就是组件调用者可能不知道组件封装着需要什么样的数据   

  • 安装包 prop-types (yarn add prop-types | npm i props-types)

  • 导入prop-types 包

  • 使用组件名.propTypes={} 来给组件的props添加校验规则

  • 校验规则通过PropTypes对象来指定

生命周期 8个

组件从被创建到挂载到页面中运行,再到组件不在时卸载的过程 生命周期的每个阶段总是伴随着一些方法调用,这些方法就是生命周期的钩子函数

创建时候:

constructor()    创建组件时,最先执行                                 初始化state    为事件绑定this

render()            每次组件渲染都会触发                                渲染 UI

componentDidMount   组件挂载后(完成DOM渲染后)           发送网络请求   DOM操作

componentDidUpdate    组件更新后                                    发送网络请求   DOM操作   

componentWillUnmount    组件卸载                                    执行清理工作(比如:清理定时器)

组件更新机制  

父组件重新渲染,也会重新渲染子组件,但是只会渲染当前组件子树

性能优化   减轻state   避免不必要的重新渲染   
路由  

安装 yarn  add  react-router-dom   

导入路由的三个核心组件:Router、Route、Link

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

使用Router组件包裹这个应用

  • 两种常用的Router: HashRouter和BrowserRouter

  • HashRouter: 使用URL的哈希值实现 (localhost:3000/#/first)

  • 推荐 BrowserRouter:使用H5的history API实现(localhost3000/first)

使用link组件作为导航菜单   用于指定导航链接(a标签)

  • 最终Link会编译成a标签,而to属性会被编译成 a标签的href属性

使用Route组件配置路由规则和要展示的组件

  • path属性:路由规则,这里需要跟Link组件里面to属性的值一致

  • component属性:展示的组件

  • Route写在哪,渲染出来的组件就在哪

 

路由的执行过程

  • 当我们点击Link组件的时候,修改了浏览器地址栏中的url

  • React路由监听地址栏url的变化

  • React路由内部遍历所有的Route组件,拿着Route里面path规则与pathname进行匹配

  •  当路由规则(path)能够匹配地址栏中的pathname时,就展示该Route组件的内容
 

编程式导航

   
  • 场景:点击登陆按钮,登陆成功后,通过代码跳转到后台首页,如何实现?

  • 编程式导航:通过JS代码来实现页面跳转

  • history是React路由提供的,用于获取浏览器历史记录的相关信息

  • push(path):跳转到某个页面,参数path表示要跳转的路径

  • go(n):前进或后退功能,参数n表示前进或后退页面数量

 

默认路由

  • 现在的路由都是通过点击导航菜单后展示的,如果进入页面的时候就主动触发路由呢

  • 默认路由:表示进入页面时就会匹配的路由

  • 默认路由:只需要把path设置为 '/'

 

匹配模式

模糊匹配模式

  • 当Link组件的to属性值为 '/login' 时候,为什么默认路由也被匹配成功?

  • 默认情况下,React路由是模糊匹配模式

  • 模糊匹配规则:只要pathname以path开头就会匹配成功

精准匹配

  • 默认路由认可情况下都会展示,如果避免这种问题?

  • 给Route组件添加exact属性,让其变为精准匹配模式

  • 精确匹配:只有当path和pathname完全匹配时才会展示改路由

  

小结

  • React路由可以有效的管理多个视图实现 SPA

  • 路由先需要通过安装

  • Router组件包裹整个应用,只需要使用一次

  • Link组件是入口,Route组件是出口

  • 通过props.history实现编程式导航

  • 默认是模糊匹配,添加exact编程精确匹配

  • React路由的一切都是组件,可以像思考组件一样思考路由

 

posted @ 2020-09-28 13:59  栀夏。  阅读(91)  评论(0编辑  收藏  举报