博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
⑤ React 基于react脚手架构建简单项目
阅读量:3964 次
发布时间:2019-05-24

本文共 8471 字,大约阅读时间需要 28 分钟。

查看专栏其它文章:


React


本人是个新手,写下博客用于自我复习、自我总结。

如有错误之处,请各位大佬指出。
学习资料来源于:尚硅谷


构建项目

所谓“脚手架”,就是用来帮助程序员快速创建一个基于xxx库的模板项目。它包含了所有需要的配置,指定好了所有的依赖,并可以直接安装/编译/运行一个简单效果。react提供了一个用于创建react项目的脚手架库: create-react-app

在继续下面的内容前,请确保电脑中已安装了Node.JS。如果未安装,可直接去其下载。安装步骤很简单。

如果对Node.JS感兴趣,可以查阅我的文章:

检测是否安装成功:

在这里插入图片描述


创建项目

以下步骤可以在命令行中执行,也可以选择在各个开发工具中执行。

开发工具的命令行在左下角的Terminal ( Webstorm 、IDEA )

在这里插入图片描述
步骤一: npm install -g create-react-app

步骤二:create-react-app hello-react (这可能需要很长时间,请耐心等待)

随后它也会告诉你相关命令。( 我们想运行项目之后输入 npm start 即可 )

在这里插入图片描述

步骤三:cd hello-react

步骤四:npm start

然后就会自动跳转进页面。如果未跳转,在命令行中点击链接也可以。

在这里插入图片描述
到这里基础的项目已经构建完成。想运行项目就 npm start。


补充说明: 对于Google Chrome,如果新建的react项目,执行npm start后控制台报错: Uncaught TypeError: Cannot read property ‘forEach‘ of undefined,看该篇文章就可解决问题:

如果开发工具不识别 JSX (出现红色波浪线),我们可以这样设置:

在这里插入图片描述


项目结构

建好项目后,简单介绍一下项目结构:

在这里插入图片描述
在这里插入图片描述
对于普通的学习者来说,我们主要知道 src 中的文件该如何操作即可。(将在后续叙述)

简单介绍一下还应该了解的部分内容:

gitignore 会在打包的时候帮我们忽略一些不想去编译打包的文件,比如 node_modules、debug、各种开发工具的文件夹(比如.idea)等等。

package.json 主要提供项目的一些相关标识(必不可少的就是name和version)、记录一些依赖信息(必不可少的就是依赖包和它的版本号)、记录当前项目如何运行和打包。


编写应用

项目构建好后,清空src中的初始文件,然后去建我们自己的文件。

首先我们可以建一个components文件夹用来存放组件,然后其中的所有文件全是jsx文件,用来表示它是组件。然后在src层存放css文件、js文件等。(详细结构需要看个人习惯)

在这里插入图片描述


jsx组件中应该写什么内容?

和之前学习的语法一样,但是需要import React,还需要 export 暴露出去。

import React from 'react'export default class App extends React.Component {
render () {
return (
) }}

这就是最基本的结构。如果我们想引入自己的资源文件,依然选用 import 导入即可。现在举个简单的例子,展示一张图片:( app.jsx )

import React from 'react'import logo from '../logo.svg'export default class App extends React.Component {
render () {
return (
logo
) }}

组件设置好了之后,还需要设置其他内容:

入口文件 index.js 中应该写什么内容?

它的写法比较固定:import React 和 ReactDOM ,然后 import 组件,最后和之前语法一样,用 render 渲染。

import React from 'react'import ReactDOM from 'react-dom'import App from './components/app'ReactDOM.render(
, document.getElementById('root'))

在这里推荐 jsx 组件名小写,但是导入时首字母大写。

在这里插入图片描述

而在这里为什么 document.getElementById('root') ,id 为什么是 root ?

在这里插入图片描述
这是因为在 public 的 index.html(主页面)中,根标签 id 是 root。
在这里插入图片描述
通常情况下,我们不修改 index.html 中的内容。

现在就可以使用 npm start 看一下效果了。

补充说明: 在运行时为什么会去选择 public 下的 index.html 文件,又为什么会选择 src 文件夹下的 index.js 作为入口文件呢?

这是因为 React 帮我们配置好了这部分内容。

在每个项目中,都可以看到 node_modules 文件夹,里面存放了项目需要的所有依赖。在这里就有我们想要的答案。

在这里插入图片描述
在最初创建项目时,create-react-app 把 webpack、babel 等配置都封装到了依赖项目 react-script 中,所以你会发现在项目的 package.json 中明明没有多少依赖包,结果 node_modules 里有那么多依赖的原因。你可以在项目下运行 npm run eject,被隐藏的配置文件就会暴露到项目根路径下。当你npm start时,它会启动webpack-dev-server,会加载react-script项目config文件夹下的配置(paths.js)
在这里插入图片描述
当我们打开 paths.js 就可以看到,在里面定义了请求的默认转发路径是public文件夹,自然就找到了public下的index.html,同理index.js也是。

在这里插入图片描述


如果想要添加样式,就可以在组件中添加类名,然后在 index.css 中添加样式。同时不要忘记在入口文件 index.js 中导入样式

( index.css )

.logo {
width: 200px; height: 200px;}.title{
color: red; font-size: 25px;}

( app.jsx )

import React from 'react'import logo from '../logo.svg'export default class App extends React.Component {
render () {
return (
logo

react app 组件

) }}

( index.js )

import React from 'react'import ReactDOM from 'react-dom'import App from './components/app'import './index.css'ReactDOM.render(
, document.getElementById('root'))

在这里插入图片描述

在这里需要说明的是,在组件render中放入html时:

在html中,设置类是<p class="xxx"></p>

现在要将它们全部改成<p className="xxx"></p>

如果在html中涉及到了style:<p style='display:none'></p>

现在要将它们全部改成<p style={

{display: 'none'}}></p>

除此以外,项目能够实时更新(即 只要一次 npm start ,之后每次修改内容,项目都会自动重新编译打包)


练习:评论管理

以下内容中将不包括CSS代码

在有了之前的基础后,再简单说一下所谓 组件化编码 的步骤( 编码过程主要看个人习惯 ):

  1. 拆分组件: 拆分界面,抽取组件

  2. 实现静态组件: 使用组件实现静态页面效果

  3. 实现动态组件

    ① 动态显示初始化数据
    ② 交互功能(从绑定事件监听开始)

那无论是如何编写代码,拆分组件都应该是需要的,方便后续创建组件和管理。

在本次练习中,将完成以下界面及其功能。在这里选择将其拆分成以下几个组件。

在这里插入图片描述
通过拆分得到,根组件 app 和它的子组件 add 和 list 。list 组件的子组件为 item。因此src结构:
在这里插入图片描述
因为 app 是根组件,所以在 index.js 中:

import React from 'react'import ReactDOM from 'react-dom'import App from './components/app/app'ReactDOM.render(
, document.getElementById('root'))

整体的css文件可以放在这里:

在这里插入图片描述
调用的时候去 index.html 中:<link rel="stylesheet" href="/css/xxx.css"> 即可。


拆分好之后就需要考虑每个组件中的内容:在项目中涉及到了哪些属性和方法,分别放在哪个组件中比较合适。显然在本例中,所有属性和方法全部放在 app 组件中,再传递出去最合适。因为 app 组件是根组件。如果 add 组件存放用户名等属性,需要在 list 中展示,那还需要先传递给 app 组件再传递给 list 组件。对于方法也是一样的,因为如果想要提交,需要对属性做添加操作,还是需要找到属性。因此放在根组件中合适。

(先不考虑其他传递方式,就是最基本的传递。组件间通信将在下篇文章叙述)

构思好之后,第二步,所谓的静态组件,就是先去实现 html 和 css 部分,看能否正常显示,因为如果不能正常显示,之后做的一切也都没意义。当页面能显示后,我们就可以做第三步,动态组件:定时器、提交效果、删除效果等等效果。

对于这整部分内容的代码,在使用上全是以前文章中用到的用法。为了更加直观和简洁,在这里就直接演示最终代码了。和以前的唯一区别,需要注意的是:不要忘记 import 。

app.jsx

import React from 'react'import CommentAdd from '../comment-add/comment-add'import CommentList from '../comment-list/comment-list'class App extends React.Component {
//构造函数 constructor (props) {
super(props) this.state = {
//初始化 comments: [] } //绑定 add不用绑是因为使用了箭头函数 this.delete = this.delete.bind(this) } componentDidMount () {
//模拟异步获取数据 setTimeout(() => {
const comments = [ {
username: "Tom", content: "ReactJS好难啊!", id: Date.now() }, {
username: "JACK", content: "ReactJS还不错!", id: Date.now() + 1 } ] this.setState({
comments}) }, 1000) } add = (comment) => {
let comments = this.state.comments comments.unshift(comment) this.setState({
comments }) } delete (index) {
let comments = this.state.comments comments.splice(index, 1) this.setState({
comments }) } render () {
return (

请发表对React的评论

) }}export default App

comment-add.jsx

import React from 'react'import PropTypes from 'prop-types'class CommentAdd extends React.Component {
//构造函数 constructor (props) {
super(props) this.state = {
//初始化 username: '', content: '' } //绑定 this.addComment = this.addComment.bind(this) this.changeUsername = this.changeUsername.bind(this) this.changeContent = this.changeContent.bind(this) } addComment () {
// 根据输入的数据创建评论对象 let {
username, content } = this.state let comment = {
username, content } // 添加到comments中, 更新state this.props.add(comment) // 清除输入的数据 this.setState({
username: '', content: '' }) } changeUsername (event) {
this.setState({
username: event.target.value }) } changeContent (event) {
this.setState({
content: event.target.value }) } render () {
return (
) }}CommentAdd.propTypes = {
add: PropTypes.func.isRequired}export default CommentAdd

comment-list.jsx

import React from 'react'import PropTypes from 'prop-types'import CommentItem from '../comment-item/comment-item'import './commentList.css'class CommentList extends React.Component {
constructor (props) {
super(props) } render () {
let comments = this.props.comments let display = comments.length > 0 ? 'none' : 'block' return (

评论回复:

暂无评论,点击左侧添加评论!!!

    {
    comments.map((comment, index) => {
    console.log(comment) return
    }) }
) }}CommentList.propTypes = {
comments: PropTypes.array.isRequired, delete: PropTypes.func.isRequired}export default CommentList

comment-item.jsx

import React from 'react'import PropTypes from 'prop-types'import './commentItem.css'class CommentItem extends React.Component {
constructor (props) {
super(props) this.deleteComment = this.deleteComment.bind(this) } deleteComment () {
let username = this.props.comment.username if (window.confirm(`确定删除${
username}的评论吗?`)) {
this.props.delete(this.props.index) } } render () {
let comment = this.props.comment return (
  • {

    comment.username}说:

    {

    comment.content}

  • ) }}CommentItem.propTypes = {
    comment: PropTypes.object.isRequired, index: PropTypes.number.isRequired, delete: PropTypes.func.isRequired}export default CommentItem

    转载地址:http://emyki.baihongyu.com/

    你可能感兴趣的文章
    Java 数据类型
    查看>>
    UTF-16 编码简介
    查看>>
    Java 变量名
    查看>>
    Java 四舍五入运算
    查看>>
    Spring Batch 例子: 运行系统命令
    查看>>
    括号及后向引用
    查看>>
    Spring Batch 核心概念
    查看>>
    Spring Batch 例子: 导入定长文件到数据库
    查看>>
    正则表达式
    查看>>
    Java I/O
    查看>>
    序列化
    查看>>
    Perl 精萃
    查看>>
    Perl 简介
    查看>>
    Perl 注释
    查看>>
    数据类型之标量
    查看>>
    调试 Perl 脚本
    查看>>
    增强的for循环语句
    查看>>
    方法的可变参数
    查看>>
    静态导入
    查看>>
    java 泛型
    查看>>