十年网站开发经验 + 多家企业客户 + 靠谱的建站团队
量身定制 + 运营维护+专业推广+无忧售后,网站问题一站解决
目前成都创新互联公司已为近1000家的企业提供了网站建设、域名、虚拟主机、网站托管、服务器托管、企业网站设计、铜梁网站维护等服务,公司将坚持客户导向、应用为本的策略,正道将秉承"和谐、参与、激情"的文化,与客户和合作伙伴齐心协力一起成长,共同发展。
目录
React项目:...1
win下开发环境的搭建:...1
简介:...5
例,测试程序:...7
例,组件状态:...9
例,复杂例子:...11
react-mobx-starter-master.zip #解压此文件到指定位置,该位置即为项目根目录
$ npm install #或$npm i,会按照package.json的配置,安装依赖模块,生成node_modules目录(安装所有依赖的模块)
……
added 1212 packages in 135.079s
配置文件说明:
package.json文件:
npm init后产生的文件,记录项目信息,项目依赖;
需要修改name、version、description、repository、author、license,改好后可开始开发;
{
"name": "react-mobx-starter",
"version": "1.0.0",
"description": "react mobx starter",
"main": "index.js",
"scripts": { #项目管理,start指定启动webpack的dev server,build使用webpack构建打包
"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": { #开发时依赖
"babel-core": "^6.24.1", #babel转译,因为开发用了很多ES6语法,从6.X开始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", #转换装饰器用
"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-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", #热加载插件,在改动保存后,直接在页面上就能反馈,不需要手动刷新
"source-map": "^0.5.6", #文件打包,js会合并或压缩,没法调试,用它来看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" #启动一个开发的server
},
"dependencies": { #运行时依赖
"antd": "^2.9.1", #基于react实现,蚂蚁金服开源的react的UI库,做中后台管理非常方便
"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支持DOM,react-router支持路由,react-router-dom,DOM绑定路由;react和mobx是强强联合
"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', #导出devtools是source-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 #启动项目,在项目根目录下
http://127.0.0.1:3000/ #启动成功,访问
“查看网页源代码” #下载到用户本地执行
F12,Network,都是动态生成的;
VS中打开react-mobx-starter-master/index.html,修改
VS中查看reac-mobx-starter-master/src/index.js;
React是facebook开发并开源(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之间的差异,使用这个差异操作DOM,browser只需要渲染这部分变化就行;
React实现了DOM diff算法,可高效比对virtual DOM和DOM的差异(类似事务,一块提交);
virtual DOM实质是内存中的数据结构;
支持JSX语法:
JSX,是一种javascript和xml混写的语法,是javascript的扩展;不用函数调用,就可知道结构;
JSX语法是XML,要求所有元素必须闭合,如
不能写成
;
JSX规范:
首字母小写就是html标记,首字母大写就是组件;
要求严格的html标记,要求所有标签必须闭合,如
,/前留一空格;
单行省略小括号,多行使用小括号;
元素有嵌套建议多行,注意缩进;
jsx表达式,使用{}括起来,如果大括号内使用了引号,会当作字符串处理,如
React.render(
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
}
}
// class Root extends React.Component { //方2
// render() {
// return React.createElement('div', null, 'welcome to magedu.');
// }
// }
ReactDom.render(
// ReactDom.render(React.createElement(Root), document.getElementById('root')); //方2,还可使用React.createElement创建react元素,第一参数是React组件或一个HTML的标签名称(如div、span)
src/index.js保存后,会自动编译,并重新装载刷新browser端界面;
增加一个子元素:
import React from 'react';
import ReactDom from 'react-dom';
class SubEle extends React.Component {
render() {
return
// return
// return
// return
// return
}
}
class Root extends React.Component {
render() {
return (
);
}
}
ReactDom.render(
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
}
}
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使用setState,browser的Console上有警告Warning
setTimeout(()=> this.setState({p1:'magedu',p2:'.net'}),5000); //V,可用延时函数操作,5s后页面自动刷新;this.setState({p1:'magedu'})并不会把state对象的所有属性覆盖掉,只是改了对应p1属性的值
// this.dealsth(); //X,通过方法操作也不可以
return (
);
}
}
ReactDom.render(
this.setState({p1:'www.magedu'}); //X,表现如下
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编程方式:
{/*
function getEventTrigger(event) {
x = event.target;
alert("trigger's element id is: " + x.id);
}
click me,it will be trigger a event,and alert window
*/}
注:
head与http的响应头没关系,head是响应头中body部分的头,head中的