zoukankan      html  css  js  c++  java
  • react脚手架和深入理解jsx语法

    react的mvc和vue的mvvm

    vue的mvvm属于双向绑定,view层,model数据层,vm实现双向绑定的控制层

    此种模式,再某一类项目种很有优势:管理系统 ( OA, ERP , CRM , CMS.....) ,因为其中存在着大量表单操作

    react的mvc属性单向数据绑定,view层,model层(数据),controller(控制层)

    1.两种都是操作数据来影响视图的,告别了传统操作DOM的时代

    model层控制view层

    • Vue基于数据劫持,拦截到最新的数据,从而重新渲染视图
    • React是提供对应的API,通过我们操作API,让最新数据渲染视图

    2.都一定存在DOM的差异化渲染 (DOM DIFF)

    每一次数据更改,只把需要改变的视图部分进行渲染

    3.react默认只实现了单向控制(只有数据影响视图),而vue基于v-model实现了双向控制 (其实,在视图影响数据方式上,我们自己也能实现,即react也能实现双向绑定)

    题外话:在前后端整个项目的结构上,vue和react也算是只有v层,即视图层,mvc也是整个项目架构的名词(model层 :创建数据模型,controller:业务层,实现各种业务逻辑,view层,即前端层),这里的react和vue都只能说是前端 *局部 * 的mvc和mvvm

    脚手架

    官方脚手架:create-react-app

    $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打包的时候就不会把内容打包在一起了)

    配置向后兼容

    • browserList
    • Polyfill

    JSX基础语法与JSX语法的优点

    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安全优化
    

    把JSX语法=>虚拟DOM对象=>真实DOM

    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()
            };
            
        }
    
  • 相关阅读:
    OpenCV图像数字化
    Matplotlib从兴趣到实践
    NumPy矩阵
    NumPy排序
    NumPy统计函数
    NumPy算输符
    产品路线图详解:主要功能、常见类型和线路图构建技巧
    敏捷和DevOps:是敌是友?
    如何让Git适应敏捷开发流程?
    如何让敏捷中的每日站会发挥最大效果?
  • 原文地址:https://www.cnblogs.com/JCDXH/p/12333962.html
Copyright © 2011-2022 走看看