-
Notifications
You must be signed in to change notification settings - Fork 0
dumin199101/ES6
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Folders and files
Name | Name | Last commit message | Last commit date | |
---|---|---|---|---|
Repository files navigation
项目说明: Es6语法&NodeJS&Vue&React NodeJS:一个基于V8引擎的Javascript运行环境,独立于浏览器存在,基于操作系统。 特点:基于事件驱动,单线程,异步非阻塞IO,跨平台。 null与undefined的区别: null:空对象 undefined:变量声明未初始化,函数未传参,函数没有返回值,对象没有赋值属性。 JS难点:两链一包:作用域链,原型链,闭包 原型链: 每一个函数都有一个prototype属性,构造函数通过prototype属性指向实例原型 javascript对象有一个属性叫__proto__,通过这个属性指向实例原型 每个实例原型都有一个constructor属性指向构造函数 ES5通过getPrototypeOf获取对象的实例原型 call,apply,arguments: call跟apply作用相同,obj2可以通过call方法调用obj1的方法,类似于继承,第一个参数都是上下文对象,其余参数:call方法是参数列表,apply方法是参数数组 obj1.method.call(obj2,arg1,arg2) 实例: function Person(){this.name="lilei"} function Student(){Person.call(this)} var student = new Student(); console.log(student.name); arguments对象代表形参数组列表 JSON.stringify跟JSON.parse JSON.stringify:将js对象转换为JSON字符串 JSON.parse:将JSON字符串解析为js对象 JavaScript事件传播机制 过程:捕获,目标,冒泡 事件绑定:DOM元素绑定,动态绑定,addEventListener绑定(提供第三个参数,是否在捕获阶段触发) cnpm,npm:包管理工具 全局安装cnpm:npm install cnpm -g 切换淘宝镜像:npm install jquery --registry=https://registry.npm.taobao.org 全局设置:npm config set registry https://registry.npm.taobao.org 查看设置:npm config list 常用命令:npm init,npm install,npm uninstall 第三方扩展: moment:时间处理 nodemon:node监视器 art-template:服务端模版引擎 mysql:数据库 commonJS规范: require:导入 exports/module.exports:导出 Ajax原生请求: var xhr = new XMLHttpRequest(); xhr.onreadystatechange = function(){ if(xhr.readystate == 4 && xhr.status == 200){ } } xhr.open(method,url,async); xhr.send(); ES6基础语法: ES6 == ECMAScript2015 1.let声明变量:变量不会提前声明,拥有块级作用域 变量声明未提前demo: <script> var scope = "global"; function fn(){ console.log(scope);//result:undefined var scope = "local"; console.log(scope);//result:local; } fn(); </script> 解析流程: <script> var scope = "global"; function fn(){ var scope;//提前声明了局部变量 console.log(scope);//result:undefined scope = "local"; console.log(scope);//result:local; } fn(); </script> <script> let scope = "global"; function fn(){ console.log(scope);//报错 let scope = "local"; console.log(scope);//result:local; } fn(); </script> 拥有块级作用域: <script> for(let i=1;i<5;i++){} console.log(i); 获取不到i for(var i=1;i<5;i++){} console.log(i); 可以获取到i </script> 2.const声明常量:地址值不变 3.模版字符: var i = 1; var a = `abc def${i+5} ghk `; 4.解构赋值: 字符串解构赋值: var [a,b,c] = 'def'; 数组解构赋值: var [a,b] = ['def','ghk']; 对象解构赋值:键必须一致 var obj = {name:'lisi',age:22}; var {name,age} = obj; 5.对象方法及属性简写 方法简写: var obj = { a:1, b:2, func } function func(){ return this.a+this.b; } console.log(obj.func()); 方法简写2: var obj = { func(s1,s2){ console.log("Hello"); }, func2:(s1,s2)=>{ console.log(s1+s2); } } 属性简写: var name = 'lisi'; var obj = {name}; console.log(obj.name); 6.promise解决回调地狱: var fs = require('fs'); var promise = new Promise(function(resolve,reject){ fs.readFile(file,encode,function(err,data){ err ? reject(err):resolve(data) }) }); promise.then(function (data) { //then第一个函数是成功的回调,参数是resolve(err)中的data console.log('成功:' + data); // 若成功,运行结果:成功:111 }, function (err) { //then第二个函数是失败的回调函数,参数是reject(err)中的err错误对象 console.log('失败:' + err); }); 7.箭头函数: var a = (s1,s2)=>{ return s1+s2; } 只有一个形参,可以省略括号 var a = s1=>{ return s1; } 如果没有形参,不可以省略括号 var a = ()=>{ return s1; } 如果只有函数体只有return,可以简写为: var a = (s1,s2)=>s1+s2 Express框架: 用到的组件(中间件): 1.express 2.express-art-template 3.art-template 4.formidable:表单上传组件 5.cookie-session 管理静态资源: app.use(express.static('public')) 使用模板引擎: app.engine('html',require('express-art-template')) 使用外置路由: app.use(require('./route')) route.js: const express = require('express'); //外置路由 const router = express.Router(); router.get("/",(request,response)=>{ response.end("Hello Node!"); }); //导出 module.exports = router; 使用内置路由: app.get("/",function(){}) 路由中间件: const express = require('express'); const app = express(); app.use(function (request,response,next) { console.log("333222"); next(); //如果没有next,不会往下执行 }); app.get("/",function (request,response,next) { console.log("111111"); response.end("Hello!"); next(); }); app.use(function (request,response,next) { console.log("3333333") }); app.listen(7777,function () { console.log("请访问127.0.0.1:7777") }); Vue框架: 1.vue小应用 <div id="app"> {{content}} </div> var app = new Vue({ el:"#app", data:{ "content":"Hello Vue" }, methods:{ clickMe(){ console.log("123"); } } }); console.log(app.content); 2.插值 文本:{{text}} 表达式:{{num+3}} 函数:{{func()}} 3.指令 v-text:文本替换,跟插值的区别是如果有子元素会进行覆盖 v-html:html文本替换 v-bind:绑定属性,属于单项数据绑定,简写形式用:替换v-bind即可 v-model: 属于双向数据绑定:Vue实例中的数据改变,会影响DOM元素中的数据,反之亦然。 修饰符:.lazy:取代input监听change事件,.number:转换数字,.trim:去除空白 v-on: 作用:绑定事件 可以使用@代替v-on 可以使用$event获取事件对象 事件修饰符: .prevent:调用event.preventDefault() .stop:调用event.stopPropagation() .once:只触发一次 v-show:控制显示隐藏 v-if:条件判断 v-else-if:条件判断 v-else:条件判断 v-for:循环 v-once:只渲染一次,动态改变vue实例中的数据,不受影响 v-cloak:指令保持在元素上,直至vue实例编译结束,结合css样式使用 4.devtools:Vue浏览器辅助开发插件 5.MVVM设计思想:Model/View/ViewModel(Vue框架就是充当这个角色) 6.computed计算属性:声明了一个计算属性 getFullName,函数将用作属性 vm.getFullName 的 getter 函数 7.watch侦听器:侦听data的数据变化,可同时返回NewValue跟OldValue,常用做异步监听场景检测 8.ref操作DOM元素:Vue提供了一个$refs属性可以获取DOM元素 9.过滤器filter: 全局过滤器 Vue.filter('reverse',function(value){ return value.split("").reverse().join(""); }); 局部过滤器 filters:{ 'upper':function (value) { return value.toUpperCase(); } } 10.自定义指令directive: 全局自定义指令 Vue.directive('haha2',{ 'inserted'(element){ return element.style.color = 'blue'; } }); 局部自定义指令 directives:{ 'haha':{ inserted:(element)=>{ return element.style.color = 'red'; } } } 11.过渡及动画 6个切换class:v-enter,v-enter-active,v-enter-to,v-leave,v-leave-active,v-leave-to 如果transition标签指定类名,那么切换类变为指定类名前缀即可 结合animate.css:transition标签添加enter-class,enter-active-class,enter-to-class,leave-class,leave-active-class,leave-to-class 12.利用JsonServer搭建调试接口 安装:npm install -g json-server 使用:json-server -w user.json HTTP请求:查询:GET,添加:POST,修改:PUT,删除:DELETE 13.axios发送请求 axios.get("http://127.0.0.1:3000/user") .then((response)=>{ console.log(response.data) }); 14.组件 定义:可复用的HTML代码块 全局组件: Vue.component('my-component',{ template:'<h2>我是最帅帅的</h2>', }); 局部组件: let app = new Vue({ el:'#app', components:{ 'myzujian':{ template:'<h3>我的组件</h3>' } } }); 使用组件: <div id="app"> <my-component></my-component> <myzujian></myzujian> </div> 一个组件的data必须是一个函数,否则多次调用数据会相互影响. let app = new Vue({ el:'#app', components:{ 'myzujian':{ data(){ return { 'msg':'我的组件' } }, template:'<h3>{{msg}}</h3>' } } }); 注意:Vue也是一个组件,如果有template属性会替换el选中DOM元素的内容. 父组件向子组件通过props传递数据: <div id="app"> <my :msg="message"></my> </div> <script> let app = new Vue({ el:'#app', data:{ message:'是个好天气' }, components:{ 'my':{ props:['msg'], template:'<h1>今天{{msg}}</h1>' } }, }); </script> 组件通过slot分发内容: <div id="app"> <mylists> <h1>Hello</h1> <h2 slot="header">World</h2> <h3 slot="body">Vue</h3> </mylists> </div> <script type="x-template" id="lists"> <div> <slot></slot> <slot name="header"></slot> <slot name="body"></slot> </div> </script> <script> let app = new Vue({ el: '#app', components: { mylists: { template:'#lists' } } }); </script> 自定义slot分发内容,通过scope接收变量 <div id="app"> <mylists :students="students"> <template scope="v"> <li>{{v.field.name}}</li> </template> </mylists> </div> <script type="x-template" id="lists"> <ul> <slot v-for="student in students" :field="student"></slot> </ul> </script> <script> let app = new Vue({ el: '#app', data: { students: [ {name: 'lisi', age: 22}, {name: 'wangwu', age: 26}, {name: 'zhangsan', age: 23}, ] }, components: { mylists: { props: ['students'], template: '#lists' }, } }); </script> 15.生命周期 八个阶段:beforeCreate,created,beforeMount,mounted,beforeUpdate,updated,beforeDestroy,destroyed <script> let app = new Vue({ el:'#app', data:{ msg:'Hello' }, beforeCreate(){ console.log("开始孕育"); }, created(){ console.log("创建完成,指定el或template"); }, beforeMount(){ console.log("开始template编译"); }, mounted(){ console.log("挂在完毕,创建vm.$el替换el"); console.log(this.$el); this.msg = 'World'; }, beforeUpdate(){ console.log("数据修改之前") }, updated(){ console.log("数据修改完毕,渲染数据"); this.$destroy(); }, beforeDestroy(){ console.log("销毁之前"); }, destroyed(){ console.log("销毁完毕"); } }); </script> 16.vueRouter路由组件: 常用于单页面应用 <div id="app"> <router-link to="/login">登录</router-link> <router-link to="/register">注册</router-link> <router-view></router-view> </div> <script> var router = new VueRouter({ routes:[ { path:'/login', component:{template:'<h1>登录</h1>'} }, { path:'/register', component: {template: '<h1>注册</h1>'} } ] }); let app = new Vue({ el:'#app', router }); </script> 动态路由: <div id="app"> <router-link to="/del/1">删除</router-link> <router-view></router-view> </div> <script> let router = new VueRouter({ routes:[ { path:'/del/:id', component:{template: '<h1>删除的ID是:{{$route.params.id}}</h1>'} } ] }); let app = new Vue({ el:'#app', router }); </script> 17.vue-cli工具 全局安装:npm install @vue/cli @vue/cli-init -g 创建项目:vue init webpack hello 运行项目:npm run dev Vue项目实战: 1.工具 ElementUI MarkdownPad2 axios 2.Vue中使用插件 第三方插件:通过Vue.use()使用插件,在new Vue()之前导入 axios是第三方插件,但是axios没有为Vue提供use方法,如果想在Vue中使用,必须使用install方法重新封装 自定义插件:Vue暴露install方法 import axios from 'axios' let myaxios = {} myaxios.install = function (Vue) { Vue.prototype.$axios = axios } export default myaxios 3.路由 路由对象:$route,记录当前路由的状态信息 Vue路由实例:$router 编程式导航:$router.push() 声明式导航:router-link 嵌套路由(组件中存在组件): routes: [ { path: '/', name: 'Home', component: Home, children:[ {path:'/user',name:'User',component:User} ] } ] 命名路由: <div id="app"> <router-link :to="{name:'delete',params:{id:1}}">删除</router-link> <router-view></router-view> </div> <script> let router = new VueRouter({ routes:[ { path:'/del/:id', name:'delete', component:{template: '<h1>删除的ID是:{{$route.params.id}}</h1>'} } ] }); let app = new Vue({ el:'#app', router }); </script> 命名视图: 作用:同级展示多个视图,使用components配置 <div id="app"> <router-view></router-view> <router-view name="slide"></router-view> <router-view name="content"></router-view> </div> <script type="x-template" id="menu"> <div style="width:100%"><h1>Menu</h1></div> </script> <script type="x-template" id="slide"> <div style="width:30%;float:left;"><h1>slide</h1></div> </script> <script type="x-template" id="content"> <div style="width:70%;float:right;"><h1>content</h1></div> </script> <script> const menu = {template:'#menu'} const slide = {template:'#slide'} const content = {template:'#content'} let router = new VueRouter({ routes:[ { path:'/', name:'home', components:{ default:menu, slide:slide, content:content, } } ] }); let app = new Vue({ el:'#app', router }); </script> 路由重定向与别名: 重定向与别名的区别:重定向会改变URL,别名不会改变URL 重定向: <div id="app"> <router-link :to="{name:'about'}">关于我们</router-link> <router-view></router-view> </div> <script> let router = new VueRouter({ routes:[ { path:'/del/:id', name:'delete', component:{template: '<h1>删除的ID是:{{$route.params.id}}</h1>'} }, { path:'/about', name:'about', redirect:{name:'delete',params:{'id':1}} } ] }); let app = new Vue({ el:'#app', router }); </script> 别名: <div id="app"> <router-link :to="{name:'about'}">关于我们</router-link> <router-view></router-view> </div> <script> let router = new VueRouter({ routes:[ { path:'/del/:id', name:'delete', component:{template: '<h1>删除的ID是:{{$route.params.id}}</h1>'} }, { path:'/del/2', name:'about', alias:'/about' } ] }); let app = new Vue({ el:'#app', router }); </script> 路由参数校验: <div id="app"> <router-link :to="{name:'delete',params:{id:1}}">删除</router-link> <router-view></router-view> </div> <script> let router = new VueRouter({ routes:[ { path:'/del/:id(\\d+)', name:'delete', component:{template: '<h1>删除的ID是:{{$route.params.id}}</h1>'} } ] }); let app = new Vue({ el:'#app', router }); </script> 路由默认值: <div id="app"> <router-link :to="{name:'delete'}">删除</router-link> <router-view></router-view> </div> <script> let router = new VueRouter({ routes:[ { path:'/del/:id(\\d+)?', name:'delete', component:{ data(){ return { id:0 } }, mounted(){ this.id = this.$route.params.id; if(!this.id){ this.id = 1; } console.log(this.id); }, template: '<h1>删除的ID是:{{id}}</h1>' } } ] }); let app = new Vue({ el:'#app', router }); </script> 路由守卫: // 配置路由的拦截器 router.beforeEach((to, from, next) => { // 如果访问登录的路由地址,放过 if (to.name === 'login') { next(); } else { // 如果请求的不是登录页面,验证token // 1. 获取本地存储中的token const token = localStorage.getItem('token'); if (!token) { Message({ type: 'warning', message: '请先登录!' }); // 2. 如果没有token,跳转到登录 next({ name: 'login' }); } else { // 3. 如果有token,继续往下执行 next(); } } }); 路由懒加载(首屏优化): const Foo = () => import('./Foo.vue') const Bar = () => import('./Bar.vue') 4.localStorage存储: 设置:window.localStorage.setItem(key,value) 获取:window.localStorage.getItem(key); 删除:window.localStorage.removeItem(key) 5.跨域 方案:1.JSONP 2.设置CORS响应头(Access-Control-Allow-Origin:*) 6.axios自定义配置 import axios from 'axios' let myaxios = {} myaxios.install = function (Vue) { //自定义axios var instance = axios.create({ baseURL: 'http://localhost:8888/api/private/v1/', headers: {'Authorization': window.localStorage.getItem('token')} }); Vue.prototype.$axios = instance; } export default myaxios Vuex:状态管理模式 概念: 1.state:数据 2.getters:获取数据 3.mutations:修改数据 4.actions:初始化数据 5.modules:模块 购物车实例 1.子组件结合计算属性使用vuex的state属性获取购物车数据 2.通过vuex的getters属性获取总价 3.使用vuex的mutations属性删除数据 4.使用vuex的actions属性初始化数据 5.使用vuex的modules属性模块化 Webpack项目打包: 1.项目打包:npm run build 2.CDN加速打包: module.exports = { //... externals: { //包名:类名 jquery: 'jQuery', vue:'Vue', 'vue-router':'Router' } }; 3.安装 全局:npm install webpack webpack-cli -g 局部(推荐):npm install webpack webpack-cli 4.使用 全局使用:webpack 文件名 局部使用:package.json中scripts加入可执行命令 React框架 1.前端三大框架 React:Facebook Angular:Google Vue:尤雨溪 2.构建工具create-react-app 全局安装:npm install create-react-app -g 3.构建项目 create-react-app 项目名 4.启动项目 npm start 5.jsx语法 创建元素 1.ReactDOM.render(React.createElement('h1',{'id':'myh1'},'Hello World'),document.getElementById('app')); 2.ReactDOM.render( ( <div> <h1>Hello React</h1> </div> ),document.getElementById('app') ); 循环遍历 var msg = 'Hello React' var arr = ['a','b','c'] var arr2 = arr.map(function(v,k){ return <h1 key="k">{v}</h1> }) ReactDOM.render( ( <div> <h1>{msg}</h1> <div>{arr2}</div> </div> ),document.getElementById('app') ); 6.ES6面向对象 原型继承 function Person(){ this.say=function(){ console.log(this.name) } } function Student(){ this.name = 'lisi'; } Student.prototype = new Person(); var s = new Student(); s.say(); 冒充继承 function Person(){ this.say=function(){ console.log(this.name) } } function Student(){ Person.call(this); this.name = 'lisi'; } var s = new Student(); s.say(); class类声明,不支持变量提升 class Person{ constructor(){ this.name = 'lisi' this.age = 22 } say(){ console.log(this.name+'---'+this.age); } } var p = new Person(); p.say(); 类继承 class Person{ constructor(){ this.name = 'lisi'; this.age = 22; } say(){ console.log(this.name+'---'+this.age); } } class Student extends Person{ constructor(){ super(); this.city = 'beijing'; } eat(){ console.log('eat') } } var s = new Student(); s.say(); s.eat(); 7.组件 构造函数组件(无状态组件,无私有数据) var data = { name:'lisi' } function Hello(props){ console.log(props); return <div> <h1>{props.name}</h1> </div> } ReactDOM.render(( <Hello name={data.name} /> ),document.getElementById('app')); 类组件(有状态组件,有私有数据) var data = { name:'lisi' } class Hello extends Component{ render() { return <div> <h1>{this.props.name}</h1> </div> } } ReactDOM.render(( <Hello name={data.name} /> ),document.getElementById('app')); 8.props跟state的区别 state是组件私有数据,只能在类组件中使用,可读可写 props是外部传入数据,在类组件跟函数组件中都能使用,只能读取 import React,{Component} from 'react' import 'bootstrap/dist/css/bootstrap.css' import './red.css' class CmtList extends Component{ constructor(){ super(); //私有数据 this.state = { cmtlists:[ {id:1,title:'苹果',content:'东西不错嘛'}, {id:2,title:'梨子',content:'东西不错啊'}, {id:3,title:'香蕉',content:'东西不错呀'}, {id:4,title:'橘子',content:'东西不错哦'}, ] } } render() { return ( <div> {this.state.cmtlists.map(function(v){ return (<div key={v.id}> <h1 className="red">{v.title}</h1> <hr/> <p>{v.content}</p> </div>) })} </div> ) } } export default CmtList 9.事件处理 使用箭头函数解决this的指向问题 handleClick = ()=>{ console.log(this.state.cmtlists[0].title); } <button className="btn btn-danger" onClick={this.handleClick}>按钮</button> 10.数据绑定 单向数据绑定 class Person extends Component{ constructor(){ super() this.state = { name:'lisi' } } render() { return ( <div> <button onClick={this.changeData}>改变数据</button> <h1>{this.state.name}</h1> </div> ) } changeData = () =>{ this.setState({ name:'wangwu' }) } } ReactDOM.render(<Person/>,document.getElementById('app')) 双向数据绑定 class Person extends Component{ constructor(){ super() this.state = { name:'lisi' } } render() { return ( <div> <input type="text" value={this.state.name} onChange={this.changeData}/> <h1>{this.state.name}</h1> </div> ) } changeData = (e) =>{ this.setState({ name:e.target.value }) } } ReactDOM.render(<Person/>,document.getElementById('app')) 11.refs操作DOM class Person extends Component{ constructor(){ super() this.state = { name:'lisi' } } render() { return ( <div> <input ref="btn" type="text" value={this.state.name} onChange={this.changeData}/> <h1>{this.state.name}</h1> </div> ) } changeData = () =>{ this.setState({ name:this.refs.btn.value }) } } ReactDOM.render(<Person/>,document.getElementById('app')) 12.React生命周期 钩子函数 componentWillMount:render渲染之前触发 componentDidMount:render渲染之后触发 componentWillUnmount:销毁之后触发 shouldComponentUpdate:render渲染之前触发 componentWillUpdate:render渲染之前触发 componentDidUpdate:render渲染之后触发 componentWillReceiveProps:props数据发生变化时触发 13.组件之间的通讯 父-子:props 子-父:callback class Student extends Component{ constructor(props){ super(props) this.state = { mm:props.nn } } render() { return ( <div> <button onClick={this.changeStudent}>修改</button> <h1>{this.state.mm}</h1> </div> ) } changeStudent = ()=>{ //子组件数据变化传递父组件 this.props.back(this.state.mm+1) this.setState({ mm:this.state.mm+1 }) } componentWillReceiveProps(nextProps, nextContext) { console.log(nextProps); //父组件数据变化传递子组件 this.setState({ mm:nextProps.nn }) } } class Person extends Component{ constructor(){ super() this.state = { nn:0 } } render() { return ( <div> <button onClick={this.changePerson}>修改</button> <h1>{this.state.nn}</h1> <hr/> <Student back={this.back} nn={this.state.nn} /> </div> ) } changePerson = ()=>{ this.setState({ nn:this.state.nn+1 }) } back = (data) =>{ this.setState({ nn:data }) } } ReactDOM.render((<Person />),document.getElementById('app')) 14.路由 安装:npm install reacct-router-dom 使用: const Pro1 = ()=> <h1>Hello1</h1> const Pro2 = ()=> <h1>Hello2</h1> const Pro3 = ()=> <h1>Hello3</h1> const Pro = ()=>{ return ( <div> <Router> <Link to="/Pro1">Pro1</Link> <Link to="/Pro2">Pro2</Link> <Link to="/Pro3">Pro3</Link> <Route path="/Pro1" component={Pro1}></Route> <Route path="/Pro2" component={Pro2}></Route> <Route path="/Pro3" component={Pro3}></Route> </Router> </div> ) } ReactDOM.render((<Pro />),document.getElementById('app')) 嵌套路由 路由地址要加前缀 路由参数传递 编程式导航:事件触发使用箭头函数 const Pro1 = ()=> <div> <h1>Hello1</h1> <Link to="/Pro1/Pro1-1">Pro1-1</Link> <Link to="/Pro1/Pro1-2">Pro1-2</Link> <hr/> <Route path="/Pro1/Pro1-1" component={Pro1_1}></Route> <Route path="/Pro1/Pro1-2" component={Pro1_2}></Route> </div> const Pro2 = (props)=> <h1>Hello2---{props.match.params.id}</h1> const Pro3 = (props)=> <div><button onClick={()=>goHome(props)}>跳转首页</button></div> const Pro1_1 = ()=> <h2>Hello1_1</h2> const Pro1_2 = ()=> <h2>Hello1_2</h2> var goHome = (props) =>{ console.log(props) props.history.push('/Pro1') } const Pro = ()=>{ return ( <div> <Router> <Link to="/Pro1">Pro1</Link> <Link to="/Pro2/2">Pro2</Link> <Link to="/Pro3">Pro3</Link> <Route path="/Pro1" component={Pro1}></Route> <Route path="/Pro2/:id" component={Pro2}></Route> <Route path="/Pro3" component={Pro3}></Route> </Router> </div> ) } ReactDOM.render((<Pro />),document.getElementById('app'))