vue的mvvm属于双向绑定,view层,model数据层,vm实现双向绑定的控制层javascript
此种模式,再某一类项目种颇有优点:管理系统 ( OA, ERP , CRM , CMS.....) ,由于其中存在着大量表单操做css
react的mvc属性单向数据绑定,view层,model层(数据),controller(控制层)html
1.两种都是操做数据来影响视图的,告别了传统操做DOM的时代前端
model层控制view层vue
2.都必定存在DOM的差别化渲染 (DOM DIFF)java
每一次数据更改,只把须要改变的视图部分进行渲染node
3.react默认只实现了单向控制(只有数据影响视图),而vue基于v-model实现了双向控制 (其实,在视图影响数据方式上,咱们本身也能实现,即react也能实现双向绑定)react
题外话:在先后端整个项目的结构上,vue和react也算是只有v层,即视图层,mvc也是整个项目架构的名词(model层 :建立数据模型,controller:业务层,实现各类业务逻辑,view层,即前端层),这里的react和vue都只能说是前端 局部 的mvc和mvvmwebpack
官方脚手架:create-react-appgit
$npm i -g create-react-app $create-react-app xxx 基于脚手架建立项目 $npm start / build 生成项目 $npm eject 暴露webpack配置项
还有其余热门脚手架DvaJs , UmiJs(阿里)
脚手架默认安装
-react
-react-dom 开发HTML页面程序 (react-native 开发原生App的)
-react-scripts
和Vue同样,React脚手架也默认把配置好的webpack那些东西隐藏到node_modules中了
=> vue是提供了vue.config.js让用户本身去修改配置项 (详情查看vue cli官方文档)
=>想要修改React中的webpack配置项
1.先把配置项暴露出来 yarn eject / npm run eject
2.细节点: 不可逆转(暴露了不能再隐藏回去)+ 若是有git 先要保存修改项
config webpack配置项
|-webpack.config.js
|-webpackDevServer.config.js
|-path.js 存放各配置的地址文件信息(入口文件等)
|.....
scripts
|-start.js 开发环境下 npm run start 先执行这个文件
|-build.js 生产环境下 npm build 先执行这个文件
|......
1.默认状况下,咱们会把全部须要开发引入的资源(样式|图片。。。)和编写的模块等都放到SRC目录中(webpack自己就是打包src目录,更具入口的index.js)
2.可是有些东西咱们仍是须要写在public下的 index.html中
=>页面导入最后打包的css/js ,因为打包后的文件比较大,第一次请求页面须要一点时间,这个时间段内,咱们看到的就是白屏效果
1)为了解决白屏效果,咱们会在index.html中设置loading效果(这些内容是一加载页面就展现出来)=>这个有对应插件
2)给资源作304缓存
..........
=>有一些模块不支持CommonJs /ES6Module这种导入导出规范,此时须要咱们把这些模块在index.html中单独script导入进来
=>还能够把一些公共资源直接在这里导入 (这样webpack打包的时候就不会把内容打包在一块儿了)
jsx :javascript and xml
其实也能够将xml理解为html ,可是这里的html代码并非直接运行,更像是xml里咱们为标签订义意义
jsx的基本使用: 1.最外层只能有一个根节点(通常用空标记,由于若是用div,会真实渲染一个没有真正意义只用来包裹的div) 2.动态数据绑定用 : {} ,{}中存放js表达式(js执行代码得有返回的结果) =>{}中能够放数组:把数组中的每一项都呈现,不含逗号 =>{}中通常状况不能放对象, => 可是若是是jsx的虚拟DOM对象,是直接能够渲染的 3.设置行内样式,必须是style = {{ color:'red'}} ,设置样式类名须要使用的是className而不是class 4.jsx中进行的判断通常都要基于三元运算符来完成 5.jsx中遍历数组中的每一项,动态绑定多个jsx元素,通常都是基于数组中的map来实现(map迭代数组的同时,支持返回值)(和vue同样,循环的对象也要加key值) =>咱们要在ul li中渲染 let arr= [{name:'张三',age:25},{name:'李四',age:26}] =>就须要这样:<ul> {arr.map((item,index)=>{ return <li> 姓名:{item.name} 年龄:{item.age} })} <ul>
JSX的优势: 1.JSX语法具有很强的编程性,这是vue中模板语法不具有的,因此vue重新版本(v2.xx)开始,支持了jsx语法 =>举例:咱们传回一个数据,根据这个数据的不一样的,渲染不一样的组件,在vue的template语法中,咱们要写一堆html代码,每一个不一样的组件都须要写出来,而后根据if-else来控制display的隐藏于显示来控制具体须要展现哪个,而在jsx语法中,咱们可使用代码将html结构动态的组建起来,好比'h'+this.i ,这个i就能够控制要使用第几档的标题标签 =>这就是jsx的强编程性和template的弱编程性 2.JSX语法具有过滤效果(过滤非法内容),有效防止XSS攻击 =>自行了解XSS安全优化
1.基于babel-preset-react-app把JSX语法变为React.createElement的模式 =>如div标签都会转换成React.createElement("div",null,React.createElement(..)) =>React.createElement的第一个属性为div的标签名,第二个为标签的属性(对象),第三个为子元素 =>每遇到元素标签(或者组件)都要createElement React.createElement = function (type,props,...children){ let jsxOBJ ={ type:type props:{} }; //=>传递了属性,把传递的属性都放置到jsx-OBJ的props中 if(props !==null){ //基于es6实现浅克隆 jsxOBJ.props= {...props} } //=>若是传递了子元素,还须要给jsxOBJ的props中设置children属性 if(children.length > 0){ jsxOBJ.props.children = children; //若是只有一项,则把第一项赋值给jsxOBJ.props.children便可 if(children.length ===1){ jsxOBJ.props.children = children[0] } } return jsxOBJ; }; 2.基于React.createElement方法的执行,建立出虚拟DOM对象(jsx对象) =>首先是一个对象 =>type属性存储的是标签名(或者组件) =>props属性:没有传递任何属性,也没有任何的子元素,则为空对象,把传递给createElement的属性,都赋值给props;若是有子元素,则默认新增一个children的属性,多是一个值,也多是一个数组 3.基于ReactDOM.render把建立的虚拟DOM对象渲染到页面指定的容器中 =>ReactDOM.render([JSX-OBJ],[container],[callback]) =>参数意义:1.虚拟dom 2.容器 3.回调函数(在这个回调函数中,能够获取到真实的dom,只不过项目中通常不用这个参数) ReactDOM.render = function render (jsxobj ,container,callback){ let {type ,props}= jsxOBJ; //=>建立dom元素 if(typeof type === "string"){ //建立dom对象(真实dom) let element = document.createElement(type); //给dom设置传入的属性 for(let key in props){ if( !props.hasOwnProperty(key)) break; if(key === 'className'){ element.setAttribute('class',props[key]); continue; } if(key === 'style'){ let styOBJ = props['style'] for(let attr in styOBJ){ if(!styOBJ.hasOwnProperty(attr)) break; element.style[attr] = styOBJ; } } //关于子元素的处理 if(key === 'children'){ //统一为数组 let children = props['children']; !Array.isArray(children) ? children = [children] : null ; //循环子元素 children.forEach(item=>{ //若是是文本,直接建立文本节点赋值给element便可,若是是新的虚拟dom对象则须要重复调用render方法,把新建的dom对象增长给element(递归) if(typeof item ==== "string"){ element.appendChild(document.createTextNode(item)) return; } render(item,element); }); continue; } element.setAttribute(key,props[key]); } //增长到指定容器当中 container.appendChild(element); //触发回调函数 callback && callback() }; }