70react_環(huán)境搭建_組件狀態(tài)

?

目前成都創(chuàng)新互聯(lián)公司已為近1000家的企業(yè)提供了網(wǎng)站建設(shè)、域名、虛擬主機(jī)、網(wǎng)站托管、服務(wù)器托管、企業(yè)網(wǎng)站設(shè)計(jì)、銅梁網(wǎng)站維護(hù)等服務(wù),公司將堅(jiān)持客戶導(dǎo)向、應(yīng)用為本的策略,正道將秉承"和諧、參與、激情"的文化,與客戶和合作伙伴齊心協(xié)力一起成長(zhǎng),共同發(fā)展。

?

?

目錄

React項(xiàng)目:...1

win下開(kāi)發(fā)環(huán)境的搭建:...1

簡(jiǎn)介:...5

例,測(cè)試程序:...7

例,組件狀態(tài):...9

例,復(fù)雜例子:...11

?

?

?

React項(xiàng)目:

?

win下開(kāi)發(fā)環(huán)境的搭建:

?

react-mobx-starter-master.zip?? #解壓此文件到指定位置,該位置即為項(xiàng)目根目錄

?

$ npm install?? #或$npm i,會(huì)按照package.json的配置,安裝依賴模塊,生成node_modules目錄(安裝所有依賴的模塊)

……

added 1212 packages in 135.079s

?

?

配置文件說(shuō)明:

package.json文件:

npm init后產(chǎn)生的文件,記錄項(xiàng)目信息,項(xiàng)目依賴;

需要修改name、version、description、repository、author、license,改好后可開(kāi)始開(kāi)發(fā);

{

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

? "version": "1.0.0",

? "description": "react mobx starter",

? "main": "index.js",

? "scripts": {?? #項(xiàng)目管理,start指定啟動(dòng)webpack的dev server,build使用webpack構(gòu)建打包

??? "test": "test",

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

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

? },

? "repository": {},?? #版本管理,如有用type和url定義,"type": "git","url":"……"

? "author": "magedu",

? "license": "MIT",

? "devDependencies": {?? #開(kāi)發(fā)時(shí)依賴

??? "babel-core": "^6.24.1",?? #babel轉(zhuǎn)譯,因?yàn)殚_(kāi)發(fā)用了很多ES6語(yǔ)法,從6.X開(kāi)始babel拆分成很多插件,需要什么引入什么,babel-core為核心

??? "babel-jest": "^19.0.0",

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

??? "babel-plugin-transform-decorators-legacy": "^1.3.4",?? #轉(zhuǎn)換裝飾器用

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

??? "babel-preset-env": "^1.4.0",?? #babel-preset-X,預(yù)設(shè)的轉(zhuǎn)換插件

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

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

??? "css-loader": "^0.28.0",?? #css相關(guān),包括css-loader、less、less-loader、style-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",?? #熱加載插件,在改動(dòng)保存后,直接在頁(yè)面上就能反饋,不需要手動(dòng)刷新

??? "source-map": "^0.5.6",?? #文件打包,js會(huì)合并或壓縮,沒(méi)法調(diào)試,用它來(lái)看js源文件是什么,source-map-loader也需要webpack的loader

??? "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"?? #啟動(dòng)一個(gè)開(kāi)發(fā)的server

? },

??"dependencies": {?? #運(yùn)行時(shí)依賴

??? "antd": "^2.9.1",?? #基于react實(shí)現(xiàn),螞蟻金服開(kāi)源的react的UI庫(kù),做中后臺(tái)管理非常方便

??? "axios": "^0.16.1",?? #異步請(qǐng)求支持

??? "babel-polyfill": "^6.23.0",?? #解決瀏覽器api不支持的問(wèn)題,可抹平差異化

??? "babel-runtime": "^6.23.0",

??? "mobx": "^3.1.9",?? #狀態(tài)管理庫(kù),透明化

??? "mobx-react": "^4.1.8",

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

??? "prop-types": "^15.5.8",

??? "react": "^15.5.4",?? #react開(kāi)發(fā)的主框架,reaact-dom支持DOM,react-router支持路由,react-router-dom,DOM綁定路由;react和mobx是強(qiáng)強(qiáng)聯(lián)合

??? "react-dom": "^15.5.4",

??? "react-router": "^4.1.1",

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

? }

}

?

.babelrc文件:

babel轉(zhuǎn)譯的配置文件,按官網(wǎng)給的配置:

{

? "presets": [

??? "react",

??? "env",

??? "stage-0"

? ],

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

}

?

webpack.config.dev.js文件:

這是一個(gè)符合commonjs的模塊,webpack配置;

const path = require('path');

const webpack = require('webpack');

module.exports = {?? #導(dǎo)出

??? devtool: 'source-map',?? #導(dǎo)出devtools是source-map

??? entry: {?? #描述入口,entry如果是一個(gè)字符串,定義就是入口文件;如果是一個(gè)數(shù)組,里面包含入口文件,另一個(gè)參數(shù)可用來(lái)配置一個(gè)服務(wù)器;這里配置的是熱加載插件,可自動(dòng)刷新

?????? ?'app': [

??????????? 'react-hot-loader/patch',

??????????? './src/index'

??????? ]

??? },

??? output: {?? #輸出,輸出目錄是__dirname+'dist',文件名是bundle.js

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

??????? filename: 'bundle.js',

??????? publicPath: '/assets/'

?? ?},

??? resolve: {?? #指定解析什么文件類(lèi)型,此處設(shè)置對(duì)js文件解析

??????? extensions: ['.js']

??? },

??? module: {?? #模塊

??????? rules: [?? #對(duì).js結(jié)尾但不在node_modules目錄的文件使用熱加載loader和轉(zhuǎn)譯babel-loader

??????????? {

??????????????? test: /\.js$/,

??????????????? exclude: /node_modules/,?? #打包排除目錄,重要,一定要有,否則編譯就把這個(gè)目錄下所有文件拿出來(lái),超大無(wú)比

??????????????? 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: {?? #開(kāi)發(fā)用server,啟動(dòng)端口3000,支持熱加載;proxy,指定訪問(wèn)/api開(kāi)頭的路徑都代理到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的本地配置文件,覆蓋當(dāng)前配置;

{

??? "compilerOptions": {

??????? "target": "ES6",

??????? "module": "commonjs",

??????? "experimentalDecorators": true

??? }

}

?

?

$ npm start?? #啟動(dòng)項(xiàng)目,在項(xiàng)目根目錄下

70react_環(huán)境搭建_組件狀態(tài)

?

http://127.0.0.1:3000/?? #啟動(dòng)成功,訪問(wèn)

“查看網(wǎng)頁(yè)源代碼”?? #下載到用戶本地執(zhí)行

F12,Network,都是動(dòng)態(tài)生成的;

VS中打開(kāi)react-mobx-starter-master/index.html,修改<h2>段,保存,重新打開(kāi)網(wǎng)頁(yè),網(wǎng)頁(yè)內(nèi)容會(huì)有變化;

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

?

?

簡(jiǎn)介:

React是facebook開(kāi)發(fā)并開(kāi)源(2013年開(kāi)源)的前端框架;

11年他們團(tuán)隊(duì)在市面上沒(méi)找到合適的MVC框架,就自己寫(xiě)了一個(gè)js框架,用在大名鼎鼎的Instagram圖片分享社區(qū)網(wǎng)絡(luò);

React解決的是前端MVC框架中的View視圖層的問(wèn)題;

?

Virtual DOM:

document object model,文檔對(duì)象模型;

將網(wǎng)頁(yè)內(nèi)所有內(nèi)容映射到一棵樹(shù)型結(jié)構(gòu)的層級(jí)對(duì)象模型上,browser提供對(duì)DOM的支持,用戶可用腳本調(diào)用DOM API來(lái)動(dòng)態(tài)的修改DOM結(jié)點(diǎn),從而達(dá)到修改網(wǎng)頁(yè)的目的,這種修改在browser中完成,browser會(huì)根據(jù)DOM的改變重繪改變的DOM結(jié)點(diǎn)部分;

修改DOM重新渲染代價(jià)太高,前端框架為了提高效率,盡量減少DOM的重繪,提出了virtual dom,所有的修改都是在當(dāng)前virtual dom上完成的,通過(guò)比較算法,找出browser DOM之間的差異,使用這個(gè)差異操作DOM,browser只需要渲染這部分變化就行;

React實(shí)現(xiàn)了DOM diff算法,可高效比對(duì)virtual DOM和DOM的差異(類(lèi)似事務(wù),一塊提交);

virtual DOM實(shí)質(zhì)是內(nèi)存中的數(shù)據(jù)結(jié)構(gòu);

?

支持JSX語(yǔ)法:

JSX,是一種javascript和xml混寫(xiě)的語(yǔ)法,是javascript的擴(kuò)展;不用函數(shù)調(diào)用,就可知道結(jié)構(gòu);

JSX語(yǔ)法是XML,要求所有元素必須閉合,如<br />不能寫(xiě)成<br>;

JSX規(guī)范:

首字母小寫(xiě)就是html標(biāo)記,首字母大寫(xiě)就是組件;

要求嚴(yán)格的html標(biāo)記,要求所有標(biāo)簽必須閉合,如<br />,/前留一空格;

單行省略小括號(hào),多行使用小括號(hào);

元素有嵌套建議多行,注意縮進(jìn);

jsx表達(dá)式,使用{}括起來(lái),如果大括號(hào)內(nèi)使用了引號(hào),會(huì)當(dāng)作字符串處理,如<div>{'2>1?true:false'}</div>,里面的表達(dá)式就為字符串了;

React.render(

?<div>

???<div>

?????<div>content</div>

???</div>

?</div>,

?document.getElementById('example')

);

?

state組件狀態(tài):

每一個(gè)React組件都有一個(gè)狀態(tài)變量(各是各的),它是一個(gè)javascript對(duì)象,可為它定義屬性來(lái)保存值,如果狀態(tài)變化了,會(huì)觸發(fā)UI的重新渲染;

state是組件自己內(nèi)部使用的,是組件私有的屬性;

?

組件是封裝的最小單位;

jsx內(nèi)只允許表達(dá)式,三目運(yùn)算符即為表達(dá)式(換為if...else即為語(yǔ)句);

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

render()內(nèi),一般認(rèn)為state是變化過(guò)的,建議不要再對(duì)state作變化;

setTimeout()和setInterval()是異步處理的,是在render()之后改的;

state對(duì)象中,屬性的值可以是字符串、對(duì)象、數(shù)組等,只要這個(gè)值發(fā)生了變化就可以;

組件間的通信用props;

?

?

例,測(cè)試程序:

src/index.js

import React from 'react';?? //導(dǎo)入React模塊,主框架

import ReactDom from 'react-dom';?? //導(dǎo)入ReactDom模塊

?

class Root extends React.Component {?? //方1,推薦用jsx語(yǔ)法,組件類(lèi)定義,從React.Component類(lèi)上繼承,這個(gè)類(lèi)生成JSXElement對(duì)象,即react元素;叫react組件,或react元素,或jsx元素

?render() {?? //渲染函數(shù),返回組件中渲染的內(nèi)容,只能返回唯一一個(gè)頂級(jí)元素,重要

???return <div>hello magedu</div>?? //必須返回一個(gè)頂級(jí)元素,若為<div>aa</div><hr>則報(bào)錯(cuò),JSX語(yǔ)法是XML,要求所有元素必須閉合

? }

}

?

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

//?? render() {

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

//?? }

// }

?

?

ReactDom.render(<Root />,document.getElementById('root'));?? //第一個(gè)參數(shù)<Root />是JSXElement對(duì)象,第二個(gè)參數(shù)document.getElementById('root')是DOM的Element元素,將React元素添加到Dom的Element元素中并渲染,此處root要與index.html的<div id="root"></div>對(duì)應(yīng)

// ReactDom.render(React.createElement(Root), document.getElementById('root'));?? //方2,還可使用React.createElement創(chuàng)建react元素,第一參數(shù)是React組件或一個(gè)HTML的標(biāo)簽名稱(如div、span)

?

src/index.js保存后,會(huì)自動(dòng)編譯,并重新裝載刷新browser端界面;

?

增加一個(gè)子元素:

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>;?? //X,true和false去掉引號(hào),browser將不會(huì)顯示

? }

}

?

class Root extends React.Component {

?render() {

???return (

?????<div>?? //首字母小寫(xiě)是html標(biāo)記

???????<h3>welcome magedu.com</h3>

???????<br />

???????<SubEle />?? //首字母大寫(xiě)是組件

?????</div>

??? );

? }

}

?

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

?

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

504 Gateway Timeout?

注:可用于做代理事情;

?

?

例,組件狀態(tài):

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 = {?? //內(nèi)部私有,此類(lèi)之外是不允許訪問(wèn)的,這種方式不好

???p1:'magedu',

???p2:'.com'

? };

?

?dealsth() {

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

? }

?

?render() {

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

???// this.setState({p1:'www.magedu'});?? //X,不可以對(duì)還在更新中的state使用setState,browser的Console上有警告Warning

???setTimeout(()=> this.setState({p1:'magedu',p2:'.net'}),5000);?? //V,可用延時(shí)函數(shù)操作,5s后頁(yè)面自動(dòng)刷新;this.setState({p1:'magedu'})并不會(huì)把state對(duì)象的所有屬性覆蓋掉,只是改了對(duì)應(yīng)p1屬性的值

???// this.dealsth();?? //X,通過(guò)方法操作也不可以

?

???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,表現(xiàn)如下

70react_環(huán)境搭建_組件狀態(tài)

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會(huì)重繪;

?

?

例,復(fù)雜例子:

傳統(tǒng)的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> */}

注:

head與http的響應(yīng)頭沒(méi)關(guān)系,head是響應(yīng)頭中body部分的頭,head中的<script>是不顯示的;可在此head中加title(即browser中標(biāo)簽部分),另title上一行可加<meta>元信息(給SE或爬蟲(chóng)看的);

div的id是t1,鼠標(biāo)按下事件(onmousedown,另還有onmouseup和onmouseclick)捆綁了一個(gè)函數(shù),只要鼠標(biāo)按下就會(huì)觸發(fā)調(diào)用getEventTrigger函數(shù),瀏覽器會(huì)送給它一個(gè)參數(shù)event(event是瀏覽器送進(jìn)來(lái)的對(duì)象),event是事件對(duì)象,當(dāng)事件觸發(fā)時(shí),event包含觸發(fā)這個(gè)事件的對(duì)象;

?

用react實(shí)現(xiàn):

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("觸發(fā)的元素的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小駝峰,一般用這個(gè)就夠了,另onMouseUp和onMouseDown要結(jié)合;this.handleClick.bind(this)此處是返回函數(shù),在之前的對(duì)象模型中解決this指針問(wèn)題用到的bind最后要函數(shù)調(diào)用

?????點(diǎn)擊這句話,會(huì)觸發(fā)一個(gè)事件,并彈出一個(gè)警示框<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'));

注:

傳統(tǒng)方式是分開(kāi)寫(xiě)(混著寫(xiě),html+css+js都要會(huì)),現(xiàn)合到一個(gè)class里了;與顯示相關(guān)的放到render里了;

鼠標(biāo)操作都是通過(guò)事件來(lái)捕捉的,僅是在指定的div上點(diǎn),在其它地方點(diǎn)和這個(gè)div上的事件沒(méi)關(guān)系;

項(xiàng)目根下的index.html即模板文件,一個(gè)網(wǎng)頁(yè)即解決所有問(wèn)題(換底圖除外),即SPA,single page web application只有一張web頁(yè)面的應(yīng)用,在<div>里嵌入不同的內(nèi)容;

Toggle類(lèi),有自己的state屬性;

當(dāng)render完成后,網(wǎng)頁(yè)上有一個(gè)div標(biāo)簽,div標(biāo)簽對(duì)象捆綁了一個(gè)click事件的處理函數(shù),div標(biāo)簽內(nèi)有文本內(nèi)容;如果點(diǎn)擊左鍵,就觸發(fā)了onClick關(guān)聯(lián)的handleClick函數(shù),在這個(gè)函數(shù)里對(duì)狀態(tài)值改變,狀態(tài)值state的改變將引發(fā)render重繪;

如果組件自己的state變了,只會(huì)觸發(fā)自己的render方法重繪;

{this.handleClick.bind(this)},表達(dá)式內(nèi)不能加引號(hào),要綁定this,否則當(dāng)觸發(fā)捆綁的函數(shù)時(shí),this是函數(shù)執(zhí)行的上下文決定的,this已經(jīng)不是觸發(fā)事件的對(duì)象了;

console.log(event.target.id),取回產(chǎn)生事件的對(duì)象的id,但是這不是我們封裝的組件對(duì)象,所以console.log(event.target===this)為false,所以這里一定要用this,而這個(gè)this是通過(guò)綁定來(lái)的;

?

?

?

?

?

?

本文名稱:70react_環(huán)境搭建_組件狀態(tài)
URL鏈接:http://bm7419.com/article6/psshig.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供小程序開(kāi)發(fā)、搜索引擎優(yōu)化、定制網(wǎng)站、網(wǎng)站策劃、靜態(tài)網(wǎng)站建站公司

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請(qǐng)盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如需處理請(qǐng)聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來(lái)源: 創(chuàng)新互聯(lián)

網(wǎng)站建設(shè)網(wǎng)站維護(hù)公司