温馨提示×

温馨提示×

您好,登录后才能下订单哦!

密码登录×
登录注册×
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》

70react_环境搭建_组件状态

发布时间:2020-06-27 20:01:45 来源:网络 阅读:248 作者:chaijowin 栏目:编程语言

 

 

 

目录

React项目:... 1

win下开发环境的搭建:... 1

简介:... 5

例,测试程序:... 7

例,组件状态:... 9

例,复杂例子:... 11

 

 

 

React项目:

 

win下开发环境的搭建:

 

react-mobx-starter-master.zip   #解压此文件到指定位置,该位置即为项目根目录

 

$ npm install   #$npm i,会按照package.json的配置,安装依赖模块,生成node_modules目录(安装所有依赖的模块)

……

added 1212 packages in 135.079s

 

 

配置文件说明:

package.json文件:

npm init后产生的文件,记录项目信息,项目依赖;

需要修改nameversiondescriptionrepositoryauthorlicense,改好后可开始开发;

{

  "name": "react-mobx-starter",

  "version": "1.0.0",

  "description": "react mobx starter",

  "main": "index.js",

  "scripts": {   #项目管理,start指定启动webpackdev serverbuild使用webpack构建打包

    "test": "test",

    "start": "webpack-dev-server --config webpack.config.dev.js --hot --inline",

    "build": "webpack -p --config webpack.config.prod.js"

  },

  "repository": {},   #版本管理,如有用typeurl定义,"type": "git","url":"……"

  "author": "magedu",

  "license": "MIT",

  "devDependencies": {   #开发时依赖

    "babel-core": "^6.24.1",   #babel转译,因为开发用了很多ES6语法,从6.X开始babel拆分成很多插件,需要什么引入什么,babel-core为核心

    "babel-jest": "^19.0.0",

    "babel-loader": "^6.4.1",   #webpackloader,webpack是基于loader

    "babel-plugin-transform-decorators-legacy": "^1.3.4",   #转换装饰器用

    "babel-plugin-transform-runtime": "^6.23.0",

    "babel-preset-env": "^1.4.0",   #babel-preset-X,预设的转换插件

    "babel-preset-react": "^6.24.1",

    "babel-preset-stage-0": "^6.24.1",

    "css-loader": "^0.28.0",   #css相关,包括css-loaderlessless-loaderstyle-loader

    "html-webpack-plugin": "^2.28.0",

    "jest": "^19.0.2",

    "less": "^2.7.2",

    "less-loader": "^4.0.3",

    "react-hot-loader": "^3.0.0-beta.6",   #热加载插件,在改动保存后,直接在页面上就能反馈,不需要手动刷新

    "source-map": "^0.5.6",   #文件打包,js会合并或压缩,没法调试,用它来看js源文件是什么,source-map-loader也需要webpackloader

    "source-map-loader": "^0.2.1",

    "style-loader": "^0.16.1",

    "uglify-js": "^2.8.22",

    "webpack": "^2.4.1",   #打包工具

    "webpack-dev-server": "^2.4.2"   #启动一个开发的server

  },

  "dependencies": {   #运行时依赖

    "antd": "^2.9.1",   #基于react实现,蚂蚁金服开源的reactUI库,做中后台管理非常方便

    "axios": "^0.16.1",   #异步请求支持

    "babel-polyfill": "^6.23.0",   #解决浏览器api不支持的问题,可抹平差异化

    "babel-runtime": "^6.23.0",

    "mobx": "^3.1.9",   #状态管理库,透明化

    "mobx-react": "^4.1.8",

    "mobx-react-devtools": "^4.2.11",

    "prop-types": "^15.5.8",

    "react": "^15.5.4",   #react开发的主框架,reaact-dom支持DOMreact-router支持路由,react-router-domDOM绑定路由;reactmobx是强强联合

    "react-dom": "^15.5.4",

    "react-router": "^4.1.1",

    "react-router-dom": "^4.1.1"

  }

}

 

.babelrc文件:

babel转译的配置文件,按官网给的配置:

{

  "presets": [

    "react",

    "env",

    "stage-0"

  ],

  "plugins": ["transform-decorators-legacy", "transform-runtime"]

}

 

webpack.config.dev.js文件:

这是一个符合commonjs的模块,webpack配置;

const path = require('path');

const webpack = require('webpack');

module.exports = {   #导出

    devtool: 'source-map',   #导出devtoolssource-map

    entry: {   #描述入口,entry如果是一个字符串,定义就是入口文件;如果是一个数组,里面包含入口文件,另一个参数可用来配置一个服务器;这里配置的是热加载插件,可自动刷新

        'app': [

            'react-hot-loader/patch',

            './src/index'

        ]

    },

    output: {   #输出,输出目录是__dirname+'dist',文件名是bundle.js

        path: path.join(__dirname, 'dist'),

        filename: 'bundle.js',

        publicPath: '/assets/'

    },

    resolve: {   #指定解析什么文件类型,此处设置对js文件解析

        extensions: ['.js']

    },

    module: {   #模块

        rules: [   #.js结尾但不在node_modules目录的文件使用热加载loader和转译babel-loader

            {

                test: /\.js$/,

                exclude: /node_modules/,   #打包排除目录,重要,一定要有,否则编译就把这个目录下所有文件拿出来,超大无比

                use: [

                    { loader: 'react-hot-loader/webpack' },

                    { loader: 'babel-loader' }

                ]

            },

            {

                test: /\.less$/,

                use: [

                    { loader: "style-loader" },

                    { loader: "css-loader" },

                    { loader: "less-loader" }

                ]

            }

        ]

    },

    plugins: [   #webpack的插件

        new webpack.optimize.OccurrenceOrderPlugin(true),

        new webpack.HotModuleReplacementPlugin(),

        new webpack.DefinePlugin({'process.env': {NODE_ENV: JSON.stringify('development')}})

    ],

    devServer: {   #开发用server,启动端口3000,支持热加载;proxy,指定访问/api开头的路径都代理到http://127.0.0.1:8080

        compress: true,

        port: 3000,

        publicPath: '/assets/',

        hot: true,

        inline: true,

        historyApiFallback: true,

        stats: {

            chunks: false

        },

        proxy: {

            '/api': {

                target: 'http://127.0.0.1:8080',

                changeOrigin: true

            }

        }

    }

};

 

jsconfig.json文件:

vscode的本地配置文件,覆盖当前配置;

{

    "compilerOptions": {

        "target": "ES6",

        "module": "commonjs",

        "experimentalDecorators": true

    }

}

 

 

$ npm start   #启动项目,在项目根目录下

70react_环境搭建_组件状态

 

http://127.0.0.1:3000/   #启动成功,访问

“查看网页源代码”   #下载到用户本地执行

F12Network,都是动态生成的;

VS中打开react-mobx-starter-master/index.html,修改<h2>段,保存,重新打开网页,网页内容会有变化;

VS中查看reac-mobx-starter-master/src/index.js

 

 

简介:

Reactfacebook开发并开源(2013年开源)的前端框架;

11年他们团队在市面上没找到合适的MVC框架,就自己写了一个js框架,用在大名鼎鼎的Instagram图片分享社区网络;

React解决的是前端MVC框架中的View视图层的问题;

 

Virtual DOM

document object model,文档对象模型;

将网页内所有内容映射到一棵树型结构的层级对象模型上,browser提供对DOM的支持,用户可用脚本调用DOM API来动态的修改DOM结点,从而达到修改网页的目的,这种修改在browser中完成,browser会根据DOM的改变重绘改变的DOM结点部分;

修改DOM重新渲染代价太高,前端框架为了提高效率,尽量减少DOM的重绘,提出了virtual dom,所有的修改都是在当前virtual dom上完成的,通过比较算法,找出browser DOM之间的差异,使用这个差异操作DOMbrowser只需要渲染这部分变化就行;

React实现了DOM diff算法,可高效比对virtual DOMDOM的差异(类似事务,一块提交);

virtual DOM实质是内存中的数据结构;

 

支持JSX语法:

JSX,是一种javascriptxml混写的语法,是javascript的扩展;不用函数调用,就可知道结构;

JSX语法是XML,要求所有元素必须闭合,如<br />不能写成<br>

JSX规范:

首字母小写就是html标记,首字母大写就是组件;

要求严格的html标记,要求所有标签必须闭合,如<br />/前留一空格;

单行省略小括号,多行使用小括号;

元素有嵌套建议多行,注意缩进;

jsx表达式,使用{}括起来,如果大括号内使用了引号,会当作字符串处理,如<div>{'2>1?true:false'}</div>,里面的表达式就为字符串了;

React.render(

  <div>

    <div>

      <div>content</div>

    </div>

  </div>,

  document.getElementById('example')

);

 

state组件状态:

每一个React组件都有一个状态变量(各是各的),它是一个javascript对象,可为它定义属性来保存值,如果状态变化了,会触发UI的重新渲染;

state是组件自己内部使用的,是组件私有的属性;

 

组件是封装的最小单位;

jsx内只允许表达式,三目运算符即为表达式(换为if...else即为语句);

getElementById,通常用id找,也有用name找;

render()内,一般认为state是变化过的,建议不要再对state作变化;

setTimeout()setInterval()是异步处理的,是在render()之后改的;

state对象中,属性的值可以是字符串、对象、数组等,只要这个值发生了变化就可以;

组件间的通信用props

 

 

例,测试程序:

src/index.js

import React from 'react';   //导入React模块,主框架

import ReactDom from 'react-dom';   //导入ReactDom模块

 

class Root extends React.Component {   //1,推荐用jsx语法,组件类定义,从React.Component类上继承,这个类生成JSXElement对象,即react元素;叫react组件,或react元素,或jsx元素

  render() {   //渲染函数,返回组件中渲染的内容,只能返回唯一一个顶级元素,重要

    return <div>hello magedu</div>   //必须返回一个顶级元素,若为<div>aa</div><hr>则报错,JSX语法是XML,要求所有元素必须闭合

  }

}

 

// class Root extends React.Component {   //2

//   render() {

//     return React.createElement('div', null, 'welcome to magedu.');

//   }

// }

 

 

ReactDom.render(<Root />, document.getElementById('root'));   //第一个参数<Root />JSXElement对象,第二个参数document.getElementById('root')DOMElement元素,将React元素添加到DomElement元素中并渲染,此处root要与index.html<div id="root"></div>对应

// ReactDom.render(React.createElement(Root), document.getElementById('root'));   //2还可使用React.createElement创建react元素,第一参数是React组件或一个HTML的标签名称(如divspan

 

src/index.js保存后,会自动编译,并重新装载刷新browser端界面;


 

增加一个子元素:

import React from 'react';

import ReactDom from 'react-dom';

 

class SubEle extends React.Component {

  render() {

    return <div>sub content</div>;

    // return <div>{1 + 2}</div>;   //V

    // return <div>{1<2?'true':'false'}</div>;   //V

    // return <div>{'1<2?true:false'}</div>;   //X,表格式显示为字符串

    // return <div>{1<2?true:false}</div>;   //Xtruefalse去掉引号,browser将不会显示

  }

}

 

class Root extends React.Component {

  render() {

    return (

      <div>   //首字母小写是html标记

        <h3>welcome magedu.com</h3>

        <br />

        <SubEle />   //首字母大写是组件

      </div>

    );

  }

}

 

ReactDom.render(<Root />, document.getElementById('root'));


 

http://127.0.0.1:3000/api/index.js

504 Gateway Timeout 

注:可用于做代理事情;

 

 

例,组件状态:

import React from 'react';

import ReactDom from 'react-dom';

 

class SubEle extends React.Component {

  render() {

    return <div>sub content</div>;

  }

}

 

class Root extends React.Component {

  state = {   //内部私有,此类之外是不允许访问的,这种方式不好

    p1:'magedu',

    p2:'.com'

  };

 

  dealsth() {

    this.setState({p1:'www.magedu'});

  }

 

  render() {

    // this.state.p1 = 'www.magedu';   //V,可以更新

    // this.setState({p1:'www.magedu'});   //X,不可以对还在更新中的state使用setStatebrowserConsole上有警告Warning

    setTimeout(() => this.setState({p1:'magedu',p2:'.net'}),5000);   //V,可用延时函数操作,5s后页面自动刷新;this.setState({p1:'magedu'})并不会把state对象的所有属性覆盖掉,只是改了对应p1属性的值

    // this.dealsth();   //X,通过方法操作也不可以

 

    return (

      <div>

        <h3>welcome to {this.state.p1}{this.state.p2}</h3>

        <br />

        <SubEle />

      </div>

    );

  }

}

 

ReactDom.render(<Root />, document.getElementById('root'));

 

 

this.setState({p1:'www.magedu'});   //X,表现如下

70react_环境搭建_组件状态

Warning: setState(...): Cannot update during an existing state transition (such as within `render` or another component's constructor). Render methods should be a pure function of props and state; constructor side-effects are an anti-pattern, but can be moved to `componentWillMount`.

 

5s会重绘;

 

 

例,复杂例子:

传统的html编程方式:

{/* <html>

  <head>

    <script type="text/javascript">

      function getEventTrigger(event) {

        x = event.target;

        alert("trigger's element id is: " + x.id);

      }

    </script>

  </head>

  <body>

    <div id="t1" onmousedown="getEventTrigger(event)">

      click me,it will be trigger a event,and alert window

    </div>

  </body>

</html> */}

注:

headhttp的响应头没关系,head是响应头中body部分的头,head中的<script>是不显示的;可在此head中加title(即browser中标签部分),另title上一行可加<meta>元信息(给SE或爬虫看的);

dividt1,鼠标按下事件(onmousedown,另还有onmouseuponmouseclick)捆绑了一个函数,只要鼠标按下就会触发调用getEventTrigger函数,浏览器会送给它一个参数eventevent是浏览器送进来的对象),event是事件对象,当事件触发时,event包含触发这个事件的对象;

 

react实现:

import React from "react";

import ReactDom from 'react-dom';

 

class Toggle extends React.Component {

  state = {

    flag: true

  };

 

  handleClick(event) {

    console.log(event);

    console.log(event.target);

    console.log(event.target.id);

    console.log(event.target === this);

    console.log(this);

    console.log(this.state);

    let x = event.target;

    alert("触发的元素的id是:" + x.id);

    this.setState({flag:!this.state.flag});

  }

 

  render() {

    let text = this.state.flag?'true':'flase';

    return (<div id='t1' onClick={this.handleClick.bind(this)}>   //onClick小驼峰,一般用这个就够了,另onMouseUponMouseDown要结合;this.handleClick.bind(this)此处是返回函数,在之前的对象模型中解决this指针问题用到的bind最后要函数调用

      点击这句话,会触发一个事件,并弹出一个警示框<br />

      flag = {text}

    </div>);

  }

}

 

class Root extends React.Component {

  render() {

    return (<div>

      my first test<hr />   //此处的<h3>已不完全是html了,可用css控制或js控制

      <Toggle />

    </div>);

  }

}

 

ReactDom.render(<Root />, document.getElementById('root'));


注:

传统方式是分开写(混着写,html+css+js都要会),现合到一个class里了;与显示相关的放到render里了;

鼠标操作都是通过事件来捕捉的,仅是在指定的div上点,在其它地方点和这个div上的事件没关系;

项目根下的index.html即模板文件,一个网页即解决所有问题(换底图除外),即SPAsingle page web application只有一张web页面的应用,在<div>里嵌入不同的内容;

Toggle类,有自己的state属性;

render完成后,网页上有一个div标签,div标签对象捆绑了一个click事件的处理函数,div标签内有文本内容;如果点击左键,就触发了onClick关联的handleClick函数,在这个函数里对状态值改变,状态值state的改变将引发render重绘;

如果组件自己的state变了,只会触发自己的render方法重绘;

{this.handleClick.bind(this)},表达式内不能加引号,要绑定this,否则当触发捆绑的函数时,this是函数执行的上下文决定的,this已经不是触发事件的对象了;

console.log(event.target.id),取回产生事件的对象的id,但是这不是我们封装的组件对象,所以console.log(event.target===this)false,所以这里一定要用this,而这个this是通过绑定来的;

 

 

 

 

 

 


向AI问一下细节

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

AI