React基础

一.介绍React

用于构建用户界面的 JavaScript 库javascript

二.react特色

  • 声明式:React 能够很是轻松地建立用户交互界面。为你应用的每个状态设计简洁的视图,在数据改变时 React 也能够高效地更新渲染界面。
  • 组件化:建立好拥有各自状态的组件,再由组件构成更加复杂的界面。
  • 一次学习,随处编写:不管你如今正在使用什么技术栈,你均可以随时引入 React 开发新特性。React 也能够用做开发原生应用的框架 React Native.

三.第一个React程序

注意:在开始第一个react程序以前要搞清楚react的本质就是js代码,因此第一个程序咱们直接在HTML代码中演示css

react.htmlhtml

<!DOCTYPE html>
<html lang="">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>react基础</title>
</head>
<body>
    <div id="app">

    </div>


    <script src="https://cdn.bootcss.com/react/16.4.0/umd/react.development.js"></script>
    <script src="https://cdn.bootcss.com/react-dom/16.4.0/umd/react-dom.development.js"> </script>
    <script src="https://cdn.bootcss.com/babel-standalone/6.26.0/babel.min.js"></script>
    <script type="text/babel"> const element=<div title="welcome">hello React</div> ReactDOM.render(element,document.getElementById("app")) </script>


</body>
</html>
复制代码

分析第一个react程序的三个步骤

1.引包

cdn方式vue

<script src="https://cdn.bootcss.com/react/16.4.0/umd/react.development.js"></script>
<script src="https://cdn.bootcss.com/react-dom/16.4.0/umd/react-dom.development.js"></script>
<!-- 生产环境中不建议使用 -->
<script src="https://cdn.bootcss.com/babel-standalone/6.26.0/babel.min.js"></script>
复制代码

本地方式java

<!-- react的核心库 -->
<script src="lib/react.development.js"></script>
<!-- 提供与DOM相关的功能 -->
<script src="lib/react-dom.development.js"></script>
<!-- 将es6的语法转成es5,包括react的jsx语法,须要经过babel转换 -->
<script src="lib/babel.min.js"></script>
复制代码

注意:本地方式引包要注意相对路径,以及各个文件库的顺序,在实际的开发中比较少采用本地引包的方式,而是使用webpack打包工具以及npmreact

2.建立react元素
<script type="text/babel"> // 建立react元素 // 参数1: 元素的名称 // 参数2: 元素的属性 // 参数3: 元素的内容(子元素) const element = React.createElement('div', { title: 'welcome',className:'on' }, 'Hello React!!!') </script>
复制代码

注意:webpack

  • 若是在浏览器端使用babel,必须指定type='text/babel'git

  • createElement()方法程序员

    这个方法一共有三个参数,若某一个参数没有值,则须要用null来代替,不然将会报错es6

    这种方式来建立元素实在是太过麻烦,因此咱们使用jsx语法来写

    <script type="text/babel">
            const element=<div title="welcome">hello React</div>
       </script>
    复制代码
3.渲染元素到页面中

准备html的结构

<div id="app"></div>
复制代码

把元素渲染到页面

// 把元素渲染到页面中
// 参数1:须要渲染的react对象
// 参数2:指定渲染到页面中的容器
ReactDOM.render(
    element,
    document.getElementById('app')
)
复制代码

四.jsx语法

jsx: 一种 JavaScript 的语法扩展。 在react中推荐使用react来描述用户界面(建立react对象)

经过jsx建立react对象,实质内部仍是调用createElement方法,只不过jsx语法更加的简洁

1.jsx语法须要注意的要点

  • jsx虽然看起来像模板,可是jsx是一个js对象,并非字符串,也不是DOM对象
  • 在jsx中可使用表达式,在标签中使用须要使用{}包裹起来便可,但{}只能出现表达式,不能出现语句
  • 为了代码可读性,书写jsx的时候须要保证代码的缩进,而且给jsx的代码使用()包裹起来
  • jsx中的注释 不是//而是{/* */}
  • jsx中的元素只能有一个根元素,而且标签必须闭合,能够是单标签,可是单标签也要闭合。
  • 由于 JSX 的特性更接近 JavaScript 而不是 HTML ,因此jsx的属性是js的属性,好比class变成了className

注意:以上所说的要点在书写代码是必定要注意,不然会出现报错

2.jsx语法体验

<!DOCTYPE html>
<html lang="">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>react基础</title>
    <style> .on{ color:red; } </style>
</head>
<body>
    <div id="app">

    </div>

    <script src="https://cdn.bootcss.com/react/16.4.0/umd/react.development.js"></script>
    <script src="https://cdn.bootcss.com/react-dom/16.4.0/umd/react-dom.development.js"></script>
    <script src="https://cdn.bootcss.com/babel-standalone/6.26.0/babel.min.js"></script>
    <script type="text/babel"> function fn() { return 'hello react' } const msg = { str:'你好呀', age: 18 } const element=(<div> <h1>{msg.str}</h1> <div title="welcome" className="on">{fn()}</div> </div>) ReactDOM.render(element,document.getElementById("app")) </script>

</body>
</html>
复制代码

3.案例:实现时钟功能

<!DOCTYPE html>
<html lang="">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
</head>
<body>
    <div id="app"></div>

    <script src="https://cdn.bootcss.com/react/16.4.0/umd/react.development.js"></script>
    <script src="https://cdn.bootcss.com/react-dom/16.4.0/umd/react-dom.development.js"></script>
    <!-- 生产环境中不建议使用 -->
    <script src="https://cdn.bootcss.com/babel-standalone/6.26.0/babel.min.js"></script>
    <script type="text/babel"> function tick(){ //定义react对象 const element=( <div> <h1>北京时间</h1> <h2>当前时间:{new Date().toLocaleString()}</h2> </div> ) //把react对象渲染到页面中 ReactDOM.render(element,document.getElementById("app")) } setInterval(tick, 1000); </script>
</body>
</html>
复制代码

五.React中的虚拟DOM与diff算法

注意:面试官的最爱

React 中最值得称道的部分莫过于 Virtual DOM 与 diff 的完美结合,特别是其高效的 diff 算法,让用户能够无需顾忌性能问题而”任性自由”的刷新页面

我没有能力用代码这种高大尚的方式来演绎什么是虚拟DOM,什么是diff算法,以及虚拟DOM与真实的DOM的区别,下面就讲一下理解吧

1.真实的DOM

DOM就是文档对象模型的意思,html中的每个标签元素能够理解为一个DOM节点,一个网页就是由许许多多的DOM节点构成

2.虚拟的DOM

  • 使用js对象来描述一个DOM结构,在react框架中,这种方式描述一个DOM的对象称为虚拟DOM
  • 页面的更新能够先所有反映在js对象上,操做内存中的js对象的速度显然要快多了,不须要重绘与回流
  • 等更新完后,再将最终的js对象映射成真实的DOM,交由浏览器去绘制。

3.diff算法

diff算法,就是用来找出两段文本之间的差别的一种算法。

4.为何要使用diff算法

DOM操做是很是昂贵的,所以咱们须要尽可能地减小DOM操做。这就须要找出本次DOM必须更新的节点来更新,其余的不更新,这个找出的过程,就须要应用diff算法。

5.为何使用虚拟的DOM

要理解为何要使用虚拟的DOM,这里有必要了解浏览器的渲染机制

浏览器是怎么样渲染一个代码量庞大的页面的呢?

6.React中DOM的更新方式

1.使用虚拟DOM(JavaScript)对象结构表示 DOM 树的结构,根据虚拟DOM渲染出真正的DOM树

2.当状态变动的时候,从新构造一棵新的对象树。而后用新的树和旧的树进行比较,记录两棵树差别(diff算法)

3.把2所记录的差别应用到步骤1所构建的真正的DOM树上,视图就更新了

六.组件

组件:组件就是一个自定义的标签,在react中,组件有两类,函数组件 ,类组件

1.函数组件

  • 自定义一个函数,返回一个react对象,函数名首字母要大小,用于区分普通的html标签

  • render渲染到页面上时要注意 :

    把组件当作自定义标签来使用,并包含在根节点以内

<!DOCTYPE html>
<html lang="">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
</head>
<body>
    <div id="app"></div>

    <script src="https://cdn.bootcss.com/react/16.4.0/umd/react.development.js"></script>
    <script src="https://cdn.bootcss.com/react-dom/16.4.0/umd/react-dom.development.js"></script>
    <!-- 生产环境中不建议使用 -->
    <script src="https://cdn.bootcss.com/babel-standalone/6.26.0/babel.min.js"></script>
    <script type="text/babel"> //定义函数组件 function Template1(){ return ( <h1>你们好呀,我是第一个测试组件</h1> ) } function Template2(){ return ( <h2>我是第二个测试组件</h2> ) } //渲染到页面中 //把组件当作自定义标签来使用,并包含在根节点以内 ReactDOM.render( <div> <Template1></Template1> <Template2></Template2> </div>,document.getElementById('app') ) </script>
</body>
</html>
复制代码

函数组件是怎么传值的

  • props参数传值
  • 带有形参的组件在外部声明,使用时能够嵌套在别的组件里面并传入实参
  • 渲染的是别的组件
  • 有一个缺点,没有状态,状态也就是数据,函数组件本身没有数据
<!DOCTYPE html>
<html lang="">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
</head>
<body>
    <div id="app"></div>

    <script src="https://cdn.bootcss.com/react/16.4.0/umd/react.development.js"></script>
    <script src="https://cdn.bootcss.com/react-dom/16.4.0/umd/react-dom.development.js"></script>
    <!-- 生产环境中不建议使用 -->
    <script src="https://cdn.bootcss.com/babel-standalone/6.26.0/babel.min.js"></script>
    <script type="text/babel"> //定义函数组件 function Template1(props){ return ( <div> <h1>你们好呀,我是第一个测试组件</h1> <p>{props.name}</p> <p>{props.age}</p> </div> ) } function Template2(){ return ( <div> {/* 在Template2组件内部,嵌套Template1 */} <Template1 name="zs" age="18"/> </div> ) } //渲染到页面中的组件是Template2 ReactDOM.render( <div> <Template2></Template2> </div>,document.getElementById('app') ) </script>
</body>
</html>
复制代码

注意:函数组件的props是只读的,并不能修改,好比这样是错误的

//定义函数组件
     function Template1(props){
        // props.name = '李四'
        // props.age = 22
        return (
          <div> <h1>你们好呀,我是第一个测试组件</h1> <p>{props.name}</p> <p>{props.age}</p> </div>
         
        )
     }
复制代码

案例:实现时钟功能

<body>
  <div id="app"></div>

   	<script src="https://cdn.bootcss.com/react/16.4.0/umd/react.development.js"></script>
    <script src="https://cdn.bootcss.com/react-dom/16.4.0/umd/react-dom.development.js">	</script>
    <!-- 生产环境中不建议使用 -->
    <script src="https://cdn.bootcss.com/babel-standalone/6.26.0/babel.min.js"></script>

  <script type="text/babel">
    //定义一个Clock组件,专门用于显示时间    
    function Clock (props) {
      return (
        <div>
          <h1>北京时间</h1>
          <h2>当前时间:{props.date.toLocaleString()}</h2>
        </div>
      )
    }
    setInterval(() => {
      // 如何渲染的Clock组件
      ReactDOM.render(
        <Clock date={new Date()}/>,
        document.getElementById('app')
      )
    }, 1000)
  </script>
</body>

复制代码

2.类组件

为了帮助你们理解类组件,这里先给你们介绍一下ES6语法中的类

ES6中的类

<!DOCTYPE html>
<html lang="">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>react基础</title>
</head>
<body>
    <script> class Person{ //指定构造函数 constructor(name,age){ this.name=name; this.age=age; } //给对象添加方法 sayhi(){ console.log("hello world"); } } var person=new Person(); person.sayhi();//helle world </script>

</body>
</html>
复制代码

ES6中的类继承

  • 经过super()来继承父类的构造方法,其余方法自动继承
  • 在继承的同时也能够定义本身的属性,方法
<!DOCTYPE html>
<html lang="">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>react基础</title>
</head>
<body>
    <script> class Person{ //指定构造函数 constructor(name,age){ this.name=name; this.age=age; } //给对象添加方法 sayhi(){ console.log("你们好呀"); } } class chinese extends Person{ constructor(name,age){ super(name,age);//继承父类的构造方法 this.color='yellow'; } read(){ console.log("我喜欢读中文的书"); } } var student=new chinese("zhangsan","18"); student.sayhi();//你们好呀 console.log(student.name);//zhangsan console.log(student.age);//18 </script>

</body>
</html>
复制代码

类组件基本模型

  • 定义一个类组件必须继承于React.Component
  • 在类中使用render()函数返回模板
  • 渲染到页面中
<!DOCTYPE html>
<html lang="">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>react基础</title>
</head>
<body>
    <div id="app"></div>

    <script src="https://cdn.bootcss.com/react/16.4.0/umd/react.development.js"></script>
    <script src="https://cdn.bootcss.com/react-dom/16.4.0/umd/react-dom.development.js"> </script>
    <!-- 生产环境中不建议使用 -->
    <script src="https://cdn.bootcss.com/babel-standalone/6.26.0/babel.min.js"></script>

    <script type="text/babel"> //定义一个类组件 class Hello extends React.Component{ constructor(){ super(); } render(){ return ( <h1>hello world</h1> ) } } //渲染组件 ReactDOM.render( <Hello/>,document.getElementById('app') ) </script>

</body>
</html>
复制代码

怎么给类组件传值

  • 在类组件中想要获取传递过来的值,也是经过props来获取
  • 除了props,类组件还能够本身提供状态(数据)
<!DOCTYPE html>
<html lang="">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>react基础</title>
</head>
<body>
    <div id="app"></div>

    <script src="https://cdn.bootcss.com/react/16.4.0/umd/react.development.js"></script>
    <script src="https://cdn.bootcss.com/react-dom/16.4.0/umd/react-dom.development.js"> </script>
    <!-- 生产环境中不建议使用 -->
    <script src="https://cdn.bootcss.com/babel-standalone/6.26.0/babel.min.js"></script>

    <script type="text/babel"> //定义一个类组件 class Hello extends React.Component{ constructor(props){ super(props); {/*除了props,类组件还能够本身提供状态(数据)*/} this.state={ msg:'你好呀' } } render(){ return ( <div> <h1>{this.props.name}</h1> <h1>{this.props.age}</h1> <h1>{this.state.msg}</h1> </div> ) } } //渲染组件 ReactDOM.render( <Hello name="zhangsan" age="18"/>,document.getElementById('app') ) </script>

</body>
</html>
复制代码

3.函数组件和类组件混合使用

<!DOCTYPE html>
<html lang="">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>react基础</title>
</head>
<body>
    <div id="app"></div>

    <script src="https://cdn.bootcss.com/react/16.4.0/umd/react.development.js"></script>
    <script src="https://cdn.bootcss.com/react-dom/16.4.0/umd/react-dom.development.js"> </script>
    <!-- 生产环境中不建议使用 -->
    <script src="https://cdn.bootcss.com/babel-standalone/6.26.0/babel.min.js"></script>

    <script type="text/babel"> //定义一个函数组件 function Template1(){ return ( <h1>你们好呀,我是第一个测试组件</h1> ) } //定义一个类组件 class Template2 extends React.Component{ constructor(props){ super(props); } render(){ return ( <Template1 /> ) } } //渲染组件 ReactDOM.render( <Template2 />,document.getElementById('app') ) </script>
</body>
</html>
复制代码

七.事件

  • 在react中注册事件与给DOM注册事件基本是同样的, onclick onmouseenter onblur onkeyup
  • 在react中注册事件,采用驼峰命名法, onClick onMouseEnter onBlur
  • 在react中注册事件,经过{}传入的是一个函数, 而不是一个字符串
  • 在react中,若是想要阻止浏览器的默认行为,不要使用return false,使用e.preventDefault()
<!DOCTYPE html>
<html lang="">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>react基础</title>
</head>
<body>
    <div id="app"></div>

    <script src="https://cdn.bootcss.com/react/16.4.0/umd/react.development.js"></script>
    <script src="https://cdn.bootcss.com/react-dom/16.4.0/umd/react-dom.development.js"> </script>
    <!-- 生产环境中不建议使用 -->
    <script src="https://cdn.bootcss.com/babel-standalone/6.26.0/babel.min.js"></script>

    <script type="text/babel"> //定义一个类组件 class Hello extends React.Component{ render(){ return ( <div> <button onClick={this.fn}>点我</button> <a href="http://www.baidu.com" onClick={this.fn}>跳转</a> </div> ) } fn(e){ //阻止默认事件 e.preventDefault(); console.log("hello world"); } } //渲染组件 ReactDOM.render( <Hello />,document.getElementById('app') ) </script>

</body>
</html>
复制代码

1.react事件中的this丢失以及解决方案

点击修改数据按钮实现修改显示的文字

<!DOCTYPE html>
<html lang="">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>react基础</title>
</head>
<body>
    <div id="app"></div>

    <script src="https://cdn.bootcss.com/react/16.4.0/umd/react.development.js"></script>
    <script src="https://cdn.bootcss.com/react-dom/16.4.0/umd/react-dom.development.js"> </script>
    <!-- 生产环境中不建议使用 -->
    <script src="https://cdn.bootcss.com/babel-standalone/6.26.0/babel.min.js"></script>

    <script type="text/babel"> //定义一个类组件 class Hello extends React.Component{ constructor(props){ super(props); this.state={ msg:'你好呀' } } render(){ return ( <div> <h1>{this.state.msg}</h1> <button onClick={this.fn}>修改msg数据</button> </div> ) } fn(){ console.log(this) this.setState({ msg:'呵呵' }) } } //渲染组件 ReactDOM.render( <Hello />,document.getElementById('app') ) </script>

</body>
</html>
复制代码

注意:

按照咱们原来的规则,上面的代码在运行时出现报错,fn函数中打印的this是undefined

缘由是什么呢?

  • 在react注册事件的时候,提供的事件处理函数的内部this指向undefined
  • 没办法访问到this,没有办法访问到当前实例,没有办法访问到数据
  • 若是想要修改react的状态,不能直接经过this.setState()去修改

下面提供三种解决方案

  • bind方法: 任何一个函数,都有bind方法,bind方法能够用来修改函数内部的this指向,能够在构造函数中,去处理事件处理函数的this问题

    <!DOCTYPE html>
    <html lang="">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <meta http-equiv="X-UA-Compatible" content="ie=edge">
        <title>react基础</title>
    </head>
    <body>
        <div id="app"></div>
    
        <script src="https://cdn.bootcss.com/react/16.4.0/umd/react.development.js"></script>
        <script src="https://cdn.bootcss.com/react-dom/16.4.0/umd/react-dom.development.js"> </script>
        <!-- 生产环境中不建议使用 -->
        <script src="https://cdn.bootcss.com/babel-standalone/6.26.0/babel.min.js"></script>
    
        <script type="text/babel"> //定义一个类组件 class Hello extends React.Component{ constructor(props){ super(props); this.state={ msg:'你好呀' } //在构造函数中,去处理事件处理函数的this问题 this.fn=this.fn.bind(this) } render(){ return ( <div> <h1>{this.state.msg}</h1> <button onClick={this.fn}>修改msg数据</button> </div> ) } fn(){ console.log(this) this.setState({ msg:'呵呵' }) } } //渲染组件 ReactDOM.render( <Hello />,document.getElementById('app') ) </script>
    
    </body>
    </html>
    复制代码
  • 属性初始化器语法, 提供了一个箭头函数,将匿名函数改成箭头函数

    <!DOCTYPE html>
    <html lang="">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <meta http-equiv="X-UA-Compatible" content="ie=edge">
        <title>react基础</title>
    </head>
    <body>
        <div id="app"></div>
    
        <script src="https://cdn.bootcss.com/react/16.4.0/umd/react.development.js"></script>
        <script src="https://cdn.bootcss.com/react-dom/16.4.0/umd/react-dom.development.js"> </script>
        <!-- 生产环境中不建议使用 -->
        <script src="https://cdn.bootcss.com/babel-standalone/6.26.0/babel.min.js"></script>
    
        <script type="text/babel"> //定义一个类组件 class Hello extends React.Component{ constructor(props){ super(props); this.state={ msg:'你好呀' } } render(){ return ( <div> <h1>{this.state.msg}</h1> <button onClick={this.fn}>修改msg数据</button> </div> ) } fn=()=>{ console.log(this) this.setState({ msg:'呵呵' }) } } //渲染组件 ReactDOM.render( <Hello />,document.getElementById('app') ) </script>
    
    </body>
    </html>
    复制代码
  • 点击事件里面提供一个匿名函数,在匿名函数中调用修改数据的方法(不建议这种写法)

    <!DOCTYPE html>
    <html lang="">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <meta http-equiv="X-UA-Compatible" content="ie=edge">
        <title>react基础</title>
    </head>
    <body>
        <div id="app"></div>
    
        <script src="https://cdn.bootcss.com/react/16.4.0/umd/react.development.js"></script>
        <script src="https://cdn.bootcss.com/react-dom/16.4.0/umd/react-dom.development.js"> </script>
        <!-- 生产环境中不建议使用 -->
        <script src="https://cdn.bootcss.com/babel-standalone/6.26.0/babel.min.js"></script>
    
        <script type="text/babel"> //定义一个类组件 class Hello extends React.Component{ constructor(props){ super(props); this.state={ msg:'你好呀' } } render(){ return ( <div> <h1>{this.state.msg}</h1> <button onClick={ ()=>{ this.fn(); } }>修改msg数据</button> </div> ) } fn(){ console.log(this) this.setState({ msg:'呵呵' }) } } //渲染组件 ReactDOM.render( <Hello />,document.getElementById('app') ) </script>
    
    </body>
    </html>
    复制代码

2.事件传参问题

在项目中常常会将一些操做的逻辑代码封装成一个函数,好比删除某条记录,这就会涉及函数传参问题,那么react中函数通常是怎么写的呢?请看上面的案例,函数传参也是在这基础上的

函数传参的两种方法

  • 在注册事件的时候,经过bind的方式进行传参,若还想要获取事件对象, 把事件对象做为最后一个参数
<!DOCTYPE html>
<html lang="">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>react基础</title>
</head>
<body>
    <div id="app"></div>

    <script src="https://cdn.bootcss.com/react/16.4.0/umd/react.development.js"></script>
    <script src="https://cdn.bootcss.com/react-dom/16.4.0/umd/react-dom.development.js"> </script>
    <!-- 生产环境中不建议使用 -->
    <script src="https://cdn.bootcss.com/babel-standalone/6.26.0/babel.min.js"></script>

    <script type="text/babel"> //定义一个类组件 class Hello extends React.Component{ constructor(props){ super(props); this.state={ msg:'你好呀' } //在构造函数中,去处理事件处理函数的this问题 this.fn=this.fn.bind(this,id) } render(){ return ( <div> <h1>{this.state.msg}</h1> <button onClick={this.fn}>修改msg数据</button> </div> ) } fn(id,e){ console.log(id); console.log(e); } } //渲染组件 ReactDOM.render( <Hello />,document.getElementById('app') ) </script>
</body>
</html>
复制代码
  • 点击事件里面提供一个匿名函数,在匿名函数中调用方法时传参
<!DOCTYPE html>
<html lang="">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>react基础</title>
</head>
<body>
    <div id="app"></div>

    <script src="https://cdn.bootcss.com/react/16.4.0/umd/react.development.js"></script>
    <script src="https://cdn.bootcss.com/react-dom/16.4.0/umd/react-dom.development.js"> </script>
    <!-- 生产环境中不建议使用 -->
    <script src="https://cdn.bootcss.com/babel-standalone/6.26.0/babel.min.js"></script>

    <script type="text/babel"> //定义一个类组件 class Hello extends React.Component{ constructor(props){ super(props); this.state={ msg:'你好呀' } } render(){ return ( <div> <h1>{this.state.msg}</h1> <button onClick={ ()=>{ this.fn(3); } }>修改msg数据</button> </div> ) } fn(id){ console.log(id); } } //渲染组件 ReactDOM.render( <Hello />,document.getElementById('app') ) </script>

</body>
</html>
复制代码

八.组件渲染

1.条件渲染

根据条件不一样,渲染不一样的内容,和js中的if-else不一样

<!DOCTYPE html>
<html lang="">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>react基础</title>
</head>
<body>
    <div id="app"></div>

    <script src="https://cdn.bootcss.com/react/16.4.0/umd/react.development.js"></script>
    <script src="https://cdn.bootcss.com/react-dom/16.4.0/umd/react-dom.development.js"> </script>
    <!-- 生产环境中不建议使用 -->
    <script src="https://cdn.bootcss.com/babel-standalone/6.26.0/babel.min.js"></script>

    <script type="text/babel"> function UserGreeting() { return <div>欢迎回来,尊贵的v12用户</div> } function GuestGreeting() { return <div>你好,请先登陆</div> } class App extends React.Component { constructor(props) { super(props) this.state = { isLogin: true } } // 完成了条件渲染,根据isLogin来渲染不一样的内容 render() { if (this.state.isLogin) { return <UserGreeting /> } else { return <GuestGreeting /> } } } ReactDOM.render(<App />, document.getElementById('app')) </script>

</body>
</html>
复制代码
在条件渲染中变量的使用
  • 声明变量来保存react的对象,初始值设为null
  • 不一样条件下的结果赋值给该变量
<!DOCTYPE html>
<html lang="">

	<head>
		<meta charset="UTF-8">
		<meta name="viewport" content="width=device-width, initial-scale=1.0">
		<meta http-equiv="X-UA-Compatible" content="ie=edge">
		<title>react基础</title>
	</head>
	<body>
		<div id="app"></div>

		<script src="https://cdn.bootcss.com/react/16.4.0/umd/react.development.js"></script>
		<script src="https://cdn.bootcss.com/react-dom/16.4.0/umd/react-dom.development.js"> </script>
		<!-- 生产环境中不建议使用 -->
		<script src="https://cdn.bootcss.com/babel-standalone/6.26.0/babel.min.js"></script>
		<script type="text/babel"> class Score extends React.Component { constructor(props) { super(props) this.state = { score: 100 } } render() { // 可使用变量来保存react的对象 let content = null if (this.state.score >= 90) { // 元素变量, 把一个react对象赋值给一个变量 content = <p>A</p> } else if (this.state.score >= 80) { content = <p>B</p> } else if (this.state.score >= 70) { content = <p>C</p> } else if (this.state.score >= 60) { content = <p>D</p> } else { content = <p>E</p> } return ( <div> <h3>提示消息</h3> <p>你本次的成绩是</p> {content} </div> ) } } ReactDOM.render(<Score />, document.getElementById('app')) </script>
	</body>
</html>
复制代码
在条件渲染中运算符的使用
<!DOCTYPE html>
<html lang="">

	<head>
		<meta charset="UTF-8">
		<meta name="viewport" content="width=device-width, initial-scale=1.0">
		<meta http-equiv="X-UA-Compatible" content="ie=edge">
		<title>react基础</title>
	</head>
	<body>
		<div id="app"></div>

		<script src="https://cdn.bootcss.com/react/16.4.0/umd/react.development.js"></script>
		<script src="https://cdn.bootcss.com/react-dom/16.4.0/umd/react-dom.development.js"> </script>
		<!-- 生产环境中不建议使用 -->
		<script src="https://cdn.bootcss.com/babel-standalone/6.26.0/babel.min.js"></script>
		<script type="text/babel"> class App extends React.Component { constructor(props) { super(props) this.state = { score: 90, age: 18 } } render() { return ( <div> <h3>提示消息</h3> {this.state.age >= 18 ? <div>成年人</div> : <div>未成年人</div>} </div> ) } } ReactDOM.render(<App />, document.getElementById('app')) </script>
	</body>
</html>
复制代码
在条件渲染中return null的使用

return null就表示后面的代码都不执行了

<!DOCTYPE html>
<html lang="">

	<head>
		<meta charset="UTF-8">
		<meta name="viewport" content="width=device-width, initial-scale=1.0">
		<meta http-equiv="X-UA-Compatible" content="ie=edge">
		<title>react基础</title>
	</head>
	<body>
		<div id="app"></div>

		<script src="https://cdn.bootcss.com/react/16.4.0/umd/react.development.js"></script>
		<script src="https://cdn.bootcss.com/react-dom/16.4.0/umd/react-dom.development.js"> </script>
		<!-- 生产环境中不建议使用 -->
		<script src="https://cdn.bootcss.com/babel-standalone/6.26.0/babel.min.js"></script>
		<script type="text/babel"> class App extends React.Component { constructor(props) { super(props) this.state = { age: 18 } } render() { if(this.state.age<18){ return null; } return ( <div> <h3>提示消息</h3> <div>系统已监测你已经成年,能够玩这款游戏</div> </div> ) } } ReactDOM.render(<App />, document.getElementById('app')) </script>
	</body>
</html>
复制代码

2.列表渲染

在学习列表渲染以前,这里一下数组的遍历方法map():

map()方法返回一个新数组,数组中的元素为原始数组元素调用函数处理后的值。

[].map(function(value, index, array) {
    //第一个参数是值
    //第二个参数是索引值
    //第三个是原始的数组
});
复制代码
var array1 = [1,4,9,16];
var a=array1.map(v =>v*2);
console.log(a);//2,8,18,32
复制代码
数组遍历

人物列表

<!DOCTYPE html>
<html lang="">

	<head>
		<meta charset="UTF-8">
		<meta name="viewport" content="width=device-width, initial-scale=1.0">
		<meta http-equiv="X-UA-Compatible" content="ie=edge">
		<title>react基础</title>
	</head>
	<body>
		<div id="app"></div>

		<script src="https://cdn.bootcss.com/react/16.4.0/umd/react.development.js"></script>
		<script src="https://cdn.bootcss.com/react-dom/16.4.0/umd/react-dom.development.js"> </script>
		<!-- 生产环境中不建议使用 -->
		<script src="https://cdn.bootcss.com/babel-standalone/6.26.0/babel.min.js"></script>
		<script type="text/babel"> class List extends React.Component{ constructor(props){ super(props) this.state={ list:["张飞","赵云","马超","貂蝉"] } } render(){ let content=this.state.list.map((item,index)=>( <li key={index}>{item}</li> )) return ( <div> <h3>人物列表</h3> <ul>{content}</ul> </div> ) } } ReactDOM.render(<List />, document.getElementById('app')) </script>
	</body>
</html>
复制代码
对象遍历

人物列表

<!DOCTYPE html>
<html lang="">

	<head>
		<meta charset="UTF-8">
		<meta name="viewport" content="width=device-width, initial-scale=1.0">
		<meta http-equiv="X-UA-Compatible" content="ie=edge">
		<title>react基础</title>
	</head>
	<body>
		<div id="app"></div>

		<script src="https://cdn.bootcss.com/react/16.4.0/umd/react.development.js"></script>
		<script src="https://cdn.bootcss.com/react-dom/16.4.0/umd/react-dom.development.js"> </script>
		<!-- 生产环境中不建议使用 -->
		<script src="https://cdn.bootcss.com/babel-standalone/6.26.0/babel.min.js"></script>
		<script type="text/babel"> class List extends React.Component{ constructor(props){ super(props) this.state={ list:[ { id: 1, name: 'zs', age: 18, gender: '男' }, { id: 2, name: 'ls', age: 19, gender: '男' }, { id: 3, name: 'ww', age: 20, gender: '女' } ] } } render(){ let content=this.state.list.map(item=>( <tr key={item.id}> <td>{item.id}</td> <td>{item.name}</td> <td>{item.age}</td> <td>{item.gender}</td> </tr> )) return ( <div> <h3>人物列表</h3> <table> <tbody>{content}</tbody> </table> </div> ) } } ReactDOM.render(<List />, document.getElementById('app')) </script>
	</body>
</html>
复制代码

评论列表

能够直接在jsx中使用map函数

<!DOCTYPE html>
<html lang="">

	<head>
		<meta charset="UTF-8">
		<meta name="viewport" content="width=device-width, initial-scale=1.0">
		<meta http-equiv="X-UA-Compatible" content="ie=edge">
		<title>react基础</title>
	</head>
	<body>
		<div id="app"></div>

		<script src="https://cdn.bootcss.com/react/16.4.0/umd/react.development.js"></script>
		<script src="https://cdn.bootcss.com/react-dom/16.4.0/umd/react-dom.development.js"> </script>
		<!-- 生产环境中不建议使用 -->
		<script src="https://cdn.bootcss.com/babel-standalone/6.26.0/babel.min.js"></script>
		<script type="text/babel"> class Comment extends React.Component { constructor(props) { super(props) // 添加状态 this.state = { list: [ { id: 1, name: '张三', content: '沙发' }, { id: 2, name: '李四', content: '板凳' }, { id: 3, name: '王五', content: '卖瓜子' }, { id: 4, name: '赵六', content: '今天吃了没' } ] } } render() { return ( <div> <h1>评论案例</h1> <ul> {this.state.list.map(item => ( <li key={item.id}> <h3> 评论人: {item.name} </h3> <p> 评论内容: {item.content} </p> </li> ))} </ul> </div> ) } } ReactDOM.render(<Comment />, document.getElementById('app')) </script>
	</body>
</html>
复制代码

评论列表

经过多个组件传值实现

<!DOCTYPE html>
<html lang="">

	<head>
		<meta charset="UTF-8">
		<meta name="viewport" content="width=device-width, initial-scale=1.0">
		<meta http-equiv="X-UA-Compatible" content="ie=edge">
		<title>react基础</title>
	</head>
	<body>
		<div id="app"></div>

		<script src="https://cdn.bootcss.com/react/16.4.0/umd/react.development.js"></script>
		<script src="https://cdn.bootcss.com/react-dom/16.4.0/umd/react-dom.development.js"> </script>
		<!-- 生产环境中不建议使用 -->
		<script src="https://cdn.bootcss.com/babel-standalone/6.26.0/babel.min.js"></script>
		<script type="text/babel"> // 评论组件 class Comment extends React.Component { constructor(props) { super(props) // 添加状态 this.state = { list: [ { id: 1, name: '张三', content: '沙发' }, { id: 2, name: '李四', content: '板凳' }, { id: 3, name: '王五', content: '卖瓜子' }, { id: 4, name: '赵六', content: '今天吃了没' } ] } } render() { return ( <div> <h1>评论案例</h1> <ul> {this.state.list.map(item => ( <Item key={item.id} data={item} /> ))} </ul> </div> ) } } // 评论项组件,没有状态,数据是父组件传递过来的 function Item(props) { return ( <li> <h3> 评论人: {props.data.name} </h3> <p>评论内容 {props.data.content}</p> </li> ) } ReactDOM.render(<Comment />, document.getElementById('app')) </script>
	</body>
</html>
复制代码

九.表单

react中的表单分为两种:受控表单,非受控表单

react操做表单的目的是获取用户输入的内容

1.受控表单

受控表单的基本模型
  • 当前组件中的表单受到了react的控制,当表单元素的内容发生了改变,react对应的状态也要发生改变
  • react的状态发生改变,对应的表单内容也要发生改变
  • 相似于vue的双向数据绑定
  • 在表单标签中绑定一个onChange事件,必定是onChange事件
  • 在函数体重传入e参数,利用e.target.value来获取表单元素的值
<!DOCTYPE html>
<html lang="">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>react基础</title>
</head>
<body>
    <div id="app">

    </div>

    <script src="https://cdn.bootcss.com/react/16.4.0/umd/react.development.js"></script>
    <script src="https://cdn.bootcss.com/react-dom/16.4.0/umd/react-dom.development.js"> </script>
    <!-- 生产环境中不建议使用 -->
    <script src="https://cdn.bootcss.com/babel-standalone/6.26.0/babel.min.js"></script>

    <script type="text/babel"> //定义一个类组件 class Hello extends React.Component{ constructor(props){ super(props); this.state={ msg:'你好呀' } } render(){ return ( <div> <p> <input type="text" onChange={this.handleChange}/> </p> <p> {this.state.msg} </p> </div> ) } handleChange=e=>{ this.setState({ msg:e.target.value }) } } //渲染组件 ReactDOM.render( <Hello />,document.getElementById('app') ) </script>
</body>
</html>
复制代码
受控表单的统一处理模型

从受控表单的基本模型知道,若是要对一个组件中不少的表单标签作控制也就意味着要写不少个事件,因此须要封装一个函数来统一处理

<!DOCTYPE html>
<html lang="">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>react基础</title>
</head>
<body>
    <div id="app">

    </div>

    <script src="https://cdn.bootcss.com/react/16.4.0/umd/react.development.js"></script>
    <script src="https://cdn.bootcss.com/react-dom/16.4.0/umd/react-dom.development.js"> </script>
    <!-- 生产环境中不建议使用 -->
    <script src="https://cdn.bootcss.com/babel-standalone/6.26.0/babel.min.js"></script>

    <script type="text/babel"> //定义一个类组件 class Hello extends React.Component{ constructor(props){ super(props); this.state={ username:"zhangsan", content:"我是内容呀", city:"1" } } render(){ return ( <div> <div> <h3>input</h3> <input type="text" value={this.state.username} onChange={this.handleChange} name="username" /> <p>{this.state.username}</p> <h3>textarea</h3> <textarea cols="30" rows="10" value={this.state.content} onChange={this.handleChange} name="content" /> <p>{this.state.content}</p> <h3>select</h3> <select value={this.state.city} onChange={this.handleChange} name="city" > <option value="1">北京</option> <option value="2">上海</option> <option value="3">广州</option> <option value="4">深圳</option> </select> <p>{this.state.city}</p> </div> </div> ) } handleChange=e=>{ //先获取标签元素 var name=e.target.name //再获取标签元素的值,es6的属性名表达式 this.state[name]=e.target.value //修改值 this.setState(this.state) } } //渲染组件 ReactDOM.render( <Hello />,document.getElementById('app') ) </script>

</body>
</html>
复制代码

2.非受控表单

咱们通常采用受控表单来获取表单元素的值,也能够采用非受控表单的形式

要编写一个非受控组件,而不是为每一个状态更新都编写数据处理函数,你能够 使用 ref来从 DOM 节点中获取表单数据。

非受控表单基本模型
  • 在构造函数中,须要本身建立一个引用 ref
  • 咱们建立的ref与表单元素绑定,咱们建立的ref能够在任意地方使用
  • 经过ref.current.value来获取值
<!DOCTYPE html>
<html lang="">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>react基础</title>
</head>
<body>
    <div id="app">

    </div>

    <script src="https://cdn.bootcss.com/react/16.4.0/umd/react.development.js"></script>
    <script src="https://cdn.bootcss.com/react-dom/16.4.0/umd/react-dom.development.js"> </script>
    <!-- 生产环境中不建议使用 -->
    <script src="https://cdn.bootcss.com/babel-standalone/6.26.0/babel.min.js"></script>

    <script type="text/babel"> //定义一个类组件 class Form extends React.Component { constructor(props) { super(props) // 1. 建立ref this.usernameRef = React.createRef() this.buttonRef = React.createRef() } render() { return ( <div> {/* 2. 咱们建立的ref能够 在组件的任意地方使用 */} <input ref={this.usernameRef} type="text" /> <button ref={this.buttonRef} onClick={this.get}> 获取value值 </button> </div> ) } get = () => { // 手动获取到DOM的value值 // refs: 用于操做DOM的 // 3. 经过this.usernameRef.current console.log(this.usernameRef.current.value) } } //渲染组件 ReactDOM.render( <Form />,document.getElementById('app') ) </script>
</body>
</html>
复制代码

3.图书管理案例

实现图书的增删查改

<!DOCTYPE html>
<html lang="">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>react基础</title>
</head>
<body>
    <div id="app">

    </div>

    <script src="https://cdn.bootcss.com/react/16.4.0/umd/react.development.js"></script>
    <script src="https://cdn.bootcss.com/react-dom/16.4.0/umd/react-dom.development.js"> </script>
    <!-- 生产环境中不建议使用 -->
    <script src="https://cdn.bootcss.com/babel-standalone/6.26.0/babel.min.js"></script>

    <script type="text/babel"> //定义一个类组件 class Book extends React.Component { constructor(props) { super(props) this.state = { list: [ { id: 1, name: '红楼梦', desc: '一堆乱七八糟的破事' }, { id: 2, name: '西游记', desc: '小时候的经典' }, { id: 3, name: '权威指南', desc: 'js程序员必读' } ], name: '', desc: '', id: '', index: 3 } } render() { return ( <div className="container"> <div className="form"> 书名: <input type="text" value={this.state.name} onChange={this.handleChange} name="name" /> 描述: <input type="text" value={this.state.desc} onChange={this.handleChange} name="desc" /> <button onClick={this.addBook}>添加</button> </div> <table> <thead> <tr> <th>编号</th> <th>书名</th> <th>描述</th> <th>操做</th> </tr> </thead> <tbody> {this.state.list.map((item, index) => ( <tr key={item.id}> <td>{index + 1}</td> <td>{item.name}</td> <td>{item.desc}</td> <td> <a href="#" onClick={this.delBook.bind(this, item.id)}> 删除 </a> | <a href="#" onClick={this.showEdit.bind(this, item)}> 修改 </a> </td> </tr> ))} </tbody> </table> </div> ) } addBook = () => { // 判断是否有id值,若是有,是修改,不然是添加 if (this.state.id) { // 修改 // 根据id找到须要修改的下标 let idx = this.state.list.findIndex(item => item.id === this.state.id) this.state.list[idx].name = this.state.name this.state.list[idx].desc = this.state.desc } else { // 添加 // 添加图书 this.state.list.push({ id: ++this.state.index, name: this.state.name, desc: this.state.desc }) } // 清空name和desc this.state.name = '' this.state.desc = '' this.state.id = '' this.setState(this.state) } handleChange = e => { let { name, value } = e.target this.setState({ [name]: value }) } delBook(id, e) { e.preventDefault() // 删除须要id // 根据id获取到下标 let idx = this.state.list.findIndex(item => item.id === id) // 删除对应的数据 this.state.list.splice(idx, 1) this.setState(this.state) } showEdit = (book, e) => { e.preventDefault() this.state.id = book.id this.state.name = book.name this.state.desc = book.desc this.setState(this.state) } } ReactDOM.render(<Book />, document.getElementById('app')) </script>
</body>
</html>
复制代码

十.组件之间的通信

  • 在实际的项目中老是会各类组件嵌套使用,可是每一个组件的状态是私有的,别的组件时不能直接访问的
  • 组件之间的通信主要分为:父组件向子组件传值,子组件向父组件传值

1.父组件传值给子组件

  • 嵌套在别的类中的组件是子组件
  • 父组件若向子组件传值,在引用子组件时就把值传过去
  • 子组件经过props在本身的内部便可接受父组件传过来的值
  • 渲染的父组件
<!DOCTYPE html>
<html lang="">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>react基础</title>
</head>
<body>
    <div id="app">

    </div>

    <script src="https://cdn.bootcss.com/react/16.4.0/umd/react.development.js"></script>
    <script src="https://cdn.bootcss.com/react-dom/16.4.0/umd/react-dom.development.js"> </script>
    <!-- 生产环境中不建议使用 -->
    <script src="https://cdn.bootcss.com/babel-standalone/6.26.0/babel.min.js"></script>

    <script type="text/babel"> //定义一个父组件 class Father extends React.Component{ constructor(props){ super(); this.state={ msg:'你们好呀,我是爸爸' } } render(){ return ( <div> <h3>我是父组件</h3> <Son msg={this.state.msg} name="zhangsan" age="18" /> </div> ) } } //定义一个子组件 class Son extends React.Component{ constructor(props){ super(props); } render(){ return ( <div> <p>{this.props.msg}</p> <p>{this.props.name}</p> <p>{this.props.age}</p> </div> ) } } ReactDOM.render(<Father />, document.getElementById('app')) </script>
</body>
</html>
复制代码

2.子组件向父组件传值

  • 首先父组件提供一个接收数据的方法

  • 子组件嵌套在父组件中

  • 子组件提供一个传数据的方法,在方法体中将props赋值给父组件接收数据的方法,调用父组件接收数据的方法

  • 渲染的是父组件

<!DOCTYPE html>
<html lang="">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>react基础</title>
</head>
<body>
    <div id="app">

    </div>

    <script src="https://cdn.bootcss.com/react/16.4.0/umd/react.development.js"></script>
    <script src="https://cdn.bootcss.com/react-dom/16.4.0/umd/react-dom.development.js"> </script>
    <!-- 生产环境中不建议使用 -->
    <script src="https://cdn.bootcss.com/babel-standalone/6.26.0/babel.min.js"></script>

    <script type="text/babel"> //定义一个父组件 class Father extends React.Component{ constructor(props){ super(); this.state={ msg:'你们好呀,我是爸爸' } } render(){ return ( <div> <h3>我是父组件</h3> <Son getData={this.getData} /> </div> ) } //提供一个接收数据的方法 getData(msg){ console.log(msg) } } //定义一个子组件 class Son extends React.Component{ constructor(props){ super(props); this.state={ msg:'你们好,我是子组件' } } render(){ return ( <div> <button onClick={this.sendData}>给父组件传递数据</button> </div> ) } sendData=()=>{ //给父组件传递数据 let {getData}=this.props getData(this.state.msg) } } ReactDOM.render(<Father />, document.getElementById('app')) </script>
</body>
</html>
复制代码
相关文章
相关标签/搜索