版权声明:复制发表请附上原创博客地址 https://blog.csdn.net/weixin_41077029/article/details/83341842
文档正在不停完善中,欢迎各位提建议和修改错误。
vue2.0 | react | angular2 | angular(官方不维护了) | |
基础 | Vue.js 的目标是通过尽可能简单的 API 实现响应的数据绑定和组合的视图组件。 | |||
作者 | 尤雨溪 | |||
官网 | https://reactjs.org/ | https://cn.vuejs.org/ | https://www.angular.cn/ | |
框架 | MVVM | 不是一个MVC框架,只是其中一个层次(V)。 | MVC | MVVM |
时间 | 2014 | 2013 | 2016 | 2009 |
大小 | 25k | 151k | 764k | 143k |
语言 | JSX ES5 ES6 | JSX ES5 ES6 | TypeScript | JavaScript |
DOM | Virtual | Vitual | ||
Mobile Support | Weex | React Native | Ionic | Ionic |
Designing | Templates | JS Centric | JS into HTML | JS into HTML |
数据绑定 | 双向 | 单向 | 双向 | 双向 |
Rendering | 服务器端 | 服务器端 | 服务器端 | 客户端 |
应用场景 | 对于不会持续的小型的 Web 应用,使用 Vue 能带来短期内较高的开发效率。 | React 配合严格的 Flux 架构,适合超大规模多人协作的复杂项目。 | 面向大型企业应用 | 适合 SPA,面向较小的应用程序。 |
优点 | o 有完整的官方中文文档。 o 数据双向绑定思路与 Angular 类似。 o 组件化与数据流则与 React 类似,不同组件间单项数据流可防止主模块数据被污染。 o 使用脚手架工具 vue-cli 可以快速地构建项目:单文件 Vue 组件,热加载,保存时检查代码,单元测试等,优秀的组件化,配合 router 等大型项目也可以轻易拿下。 o Vue.js 中指令和组件分得更清晰。指令只封装 DOM 操作,而组件代表一个自给自足的独立单元(有自己的视图和数据逻辑)。 |
o 采用 Virtual DOM 的思路,速度快,性能好。 o 可以直接使用 ES6 的语法,通过 webpack 编译成浏览器兼容的 ES5,可以提高开发效率。 o 状态管理时,都是使用this.setData,简单直观。 o React 可以在服务器上预渲染应用再发送到客户端。它可以从预渲染的静态内容中恢复一样的记录到动态应用程序中。搜索引擎的爬虫程序依赖的是服务端响应而不是 JavaScript 的执行,预渲染你的应用有助于搜索引擎优化。 React更加关注UI的组件化,能较好的实现代码重用。 |
o 有 Angular 1.0 的优点。 o 可以使用 ES6 的语法。 o 可以通过懒加载来引入依赖注入。 |
o 是一套完整的框架,Angular 有自带的数据绑定、render 渲染、AngularUI 库,过滤器,directive(模板),服务 q(defer), http,inject(依赖注入), factory, provide 等等一系列工具。 o 整个框架充满了 DI 的思路,耦合性非常低。 |
缺点 | o 单项数据流,父子组件或平行组件间传递大量数据时需要基于 Vuex。 o 不内置例如 AJAX,Route 等功能到核心包,而是以插件的方式加载。 o 社区/组件生态相对 Angular 和 React 来说不够强大,现成的插件和组件不够完善。 o 大量数据时,首次渲染性能不如 React。 |
o 和 Angular 相比,React 的组件比较少, o React 比较“轻”,只有一个 view 层,当业务比较复杂,需要较完整的框架时,要引入 Flux, Redux。 o 本身内容比较新,API 存在较大变化的风险。 |
o Angular 的 2.0 版本几乎是推翻 1.0 版本重做的,要学习大量的东西,如模块、控制器、指令等,学习成本高。 o 新,资料少,缺乏开发经验。 o 环境搭建耗时。 |
o 官方不在维护该框架。 |
脚手架 | vue-cli,vue-iview-cli | react-iview | angular-cli 安装:npm install -g @angular/clio React |
|
属性绑定 | ||||
数据绑定 | ||||
通过分析选择用vue的原因 | 通过分析框架的特点并结合项目分析对比后,最终决定选择 Vue 框架来进行开发。 原因如下: 1. Vue 是通过 Virtual Dom 抽象层来实现页面渲染,避免了高成本的常规 DOM 操作,尽管 Vue 和 React 都使用了 Virtual Dom 实现这一点,但 Vue 的 Virtual Dom 实现(复刻自 snabbdom)是更加轻量化的,所以在这里给 Vue 续一秒(查水表)。 2. 对比 Vue 和 React,它们都是 JavaScript 编写的,听起来这十分简单和优雅。然而不幸的事实是,React 中 JavaScript 内的 HTML 和 CSS 会产生很多痛点。JSX vs Templates,Templates 可读性,书写优雅,逻辑清晰…所以给 Vue 再续一秒(+1s)。 3. Vue 的一些语法和 Angular 的很相似,但在 API 与设计两方面上 Vue.js 都比 Angular 1 简单得多,因此你可以快速地掌握它的全部特性并投入开发。所以 Vue + 1s。 4. Angular 1 使用双向绑定,Vue 在不同组件间强制使用单向数据流。这使应用中的数据流更加清晰易懂。所以 Vue++。 5. Angular 2 的学习曲线是非常陡峭的。即使不包括 TypeScript,它的开始指南中所用的就有 ES2015 标准的 JavaScript,18个 NPM 依赖包,4 个文件和超过 3 千多字的介绍,这一切都是为了完成个 Hello World。而Vue’s Hello World就非常简单。甚至我们并不用花费一整个页面去介绍它。所以如果项目经理选 Angular 2那也只好去学习(ci zhi)。 6. jQuery 和 Zepto 不在考虑范围内。 |
|||
基本构架 | <div id="app"> {{ message }} </div> var app = new Vue({ el: '#app', data: { message: 'Hello Vue!' } }) |
class HelloBox extends React.Component { render() { return ( <div> Hello {this.props.name} </div> ); } } ReactDOM.render( <HelloBox name="Taylor" />, mountNode ); 注意: 1.<script>标签的type必须为 type="text/babel",因为需要browser.min.js来解析jsx的语法内容 2.MessageBox的首字母必须大写,否则直接解析成一个标签,并且不作显示 3.所有标签都要闭合 <MessageBox/>的结束符“/”必须要有 <br/> 4.标签内的class属性必须写出className,因为他可能和createClass可能产生冲突 5.样式必须是驼峰式写法(fontSize) 6.render里的标签尤其只有一个分结点(即最外层只能有一个标签包含其他的标签) |
||
循环 | v-for <div id="app-4"> <ol> <li v-for="todo in todos"> {{ todo.text }} </li> </ol> </div> |
.map/for循环 ,没有自己的循环语句 <script type="text/babel"> var arr = ["张三","李四","王五"]; ReactDOM.render( <ul> { arr.map(function(name){ return <li>{name}</li> <span style="color:#ff0000;">//必须要return出来否则在dom中不会显示</span> }) } </ul>, document.querySelector("#example") ) </script> |
ngFor <li *ngFor="let hero of heroes"> <span class="badge">{{hero.id}}</span> {{hero.name}} </li> |
|
钩子函数(生命周期) | 1.beforeCreate: 组件实例刚被创建,组件属性计算之前,如data属性等(可以在这加个loading事件) 2.created:组件实例创建完成,属性已绑定,但DOM还未生成,$el属性还不存在(在这结束loading,还做一些初始化,实现函数自执行) 3.beforeMount:模板编译/挂载之前(完成了 el 和 data 初始化) 4.mounted:模板编译/挂载之后(ajax获取数据阶段。在这发起后端请求,拿回数据,配合路由钩子做一些事情) 5.beforeUpdate:组件更新之前(指view层的数据变化前,不是data中的数据改变前触发) 6.updated:组件更新之后(data里的值被修改后触发) 7.activated:for keep-alive,组件被激活时调用 8.deactivated:for keep-alive,组件被移除时调用 9.beforeDestory:组件销毁前调用(你确认删除XX吗?) 10.destoryed:组件销毁后调用(Vue实例销毁。当前组件已被删除,清空相关内容) |
一、Mounted阶段:加载阶段或者说初始化阶段,这个阶段组件由jsx转换成真实的Dom。 1.getDefaultProps:设置默认属性 2.getInitialState:设置默认状态 3.componentWillMount:组件即将加载时候运行的函数(通常在这里执行ajax等操作) 4.render:必不可少 5.componentDidMount:组件加载完毕时候运行的函数。 二、Update阶段:组件运行中阶段,当组件修改自身状态或者父组件修改子组件属性时候发生的阶段。 1.componentWillReceiveProps:组件将要接受新组件 2.shouldComponentUpdate:组件是否更新 //组件进行性能提升的时候就是靠 shouldComponentUpdate这个函数 shouldComponentUpdate:function(nextProps){//是一个问句,要不要随父组件更新,如果写了这个函数,即使里面没有设置return false/true,都不会随父组件更新,即默认是return false // console.log(nextProps)//返回{name:input里输入的值} console.log('b.shouldComponentUpdate') // return false;//表示子组件不随父组件不更新,只执行a.b.cde函数都不执行,执行顺序为1234d54ab4ab4ab... return true;//表示子组件随父组件的更新而更新,abcde都执行,执行顺序为1234d54abcdeabcde... }, 3.componentWillUpdate: 组件即将更新 4.render:必不可少 5.componentDidUpdate:组件更新完毕时候运行的函数。 三、Unmount阶段:组件卸载阶段,这个一般是组件被浏览器回收的阶段。(一般不需要关注的阶段) 1.componentWillUnmount:开发者需要来销毁(组件真正删除之前调用,比如计时器和事件监听器) |
ngOnChanges:当被绑定的输入属性的值发生变化时调用,首次调用一定会发生在 ngOnInit之前。(接口:OnChanges)(范围:指令和组件) ngOnInit:在第一轮 ngOnChanges 完成之后调用。 ( 译注:也就是说当每个输入属性的值都被触发了一次 ngOnChanges 之后才会调用 ngOnInit ,此时所有输入属性都已经有了正确的初始绑定值 )(接口:OnInit)(范围:指令和组件) ngDoCheck:在每个 Angular 变更检测周期中调用。(接口:DoCheck)(范围:指令和组件) ngAfterContentInit:当把内容投影进组件之后调用。(接口:AfterContentInit)(范围:组件) ngAfterContentChecked:每次完成被投影组件内容的变更检测之后调用。(接口:AfterContentChecked)(范围:组件) ngAfterViewInit:初始化完组件视图及其子视图之后调用。after initializing the component’s views and child views.(接口:AfterViewInit)(范围:组件) ngAfterViewChecked每次做完组件视图和子视图的变更检测之后调用。(接口:AfterViewChecked)(范围:组件) ngOnDestroy当 Angular 每次销毁指令 / 组件之前调用。(接口:OnDestroy)(范围:指令和组件) |
|
路由 | vue-router 官网:https://router.vuejs.org/zh-cn/ routes.js 1.引入模块 import Home from './components/Home.vue'; import User from './components/user/User.vue'; 2.定义路由并暴露接口 export const routes = [ {path:'/',component:Home,name:'home'},//name给路由设置名字,为了方便router-link的时候不用拼接字符串,方便些 {path:'/user',component:User,children:[// /user user下的模块 {path:"",component:UserStart},// /user/ {path:":id",component:UserDetail},// /user/:id {path:":id/edit",component:UserEdit,name:'userEdit'}// /user/:id/edit ]} ] Notice:url设参(/:id) 接参:在对应的component后的.vue中,本处为User.vue里 main.js中 3.1引用下载的VueRouter和配置的路由(routes.js) import VueRouter from 'vue-router';//1.引用路由模块 import {routes} from './routes';//3.引用路由配置变量 3.2使用 Vue.use(VueRouter);//2. 3.3创建router实例,然后传routes配置参数 const router=new VueRouter({//4.创建实例 routes//routes:routes的简写 //5.将路由变量实例化成路由对象 }) 3.4在new Vue中实例化router new Vue({ el: '#app', router, render: h => h(App) }) 在app.vue里的html里显示路由 <router-view></router-view> 知识点: 在app.vue主组件中显示路由内容需要用<router-view></router-view> 来进行渲染 在路由中设置name属性后可以利用router-link来设置:to参数,以便跳转到指定的组件模块 |
react-router 官网:https://github.com/ReactTraining/react-router2 分为router2和router4 本处将router2 index.js(入口文件) var React = require('react'); var ReactDOM = require('react-dom'); //引入路由部分 var Router = require('react-router').Router;//路由的模块 var Route = require('react-router').Route;//路由 var hashHistory = require('react-router').hashHistory; //引入模块 var App = require('./modules/App') var About = require('./modules/About') var Repos = require('./modules/Repos') var Index = React.createClass({ render:function(){ return( <Router history = {hashHistory}> <Route path="/" component={App}/> <Route path="/about" component={About}/> <Route path="/repos" component={Repos}/> </Router> ) } }) ReactDOM.render(<Index/>,document.getElementById('app')) App.js中 1.引入链接 var Link = require('react-router').Link; 2.render下的div标签内写点击链接跳转的代码 <ul> <li><Link to="/about">About</Link></li> <li><Link to="/repos">Repos</Link></li> </ul> router4 3.在App.js里面直接引用 3.1引用 import {Home} from './Components' 3.2div里换成 ReactDOM.render( <BrowserRouter>{/*BrowserRouter相当于2.0的Router*/} <div> <ul> <li><NavLink to="/" activeClassName="active">Home</NavLink></li> </ul> <Route path="/" component={Home} exact={true}/>{/*Route在4.0是拿来渲染的,相当于2.0的{this.props.children}。在2.0是拿来设置路由的。*/} </div> </BrowserRouter>, document.getElementById('app') ) |
angular/router二函数。 官网:https://www.angular.cn/guide/router 案例: index.html <base href="/"> .module.ts(import) import { RouterModule, Routes } from '@angular/router'; .module.ts(except) const appRoutes: Routes = [ { path: 'crisis-center', component: CrisisListComponent }, { path: 'hero/:id', component: HeroDetailComponent }, { path: 'heroes', component: HeroListComponent, data: { title: 'Heroes List' } }, { path: '', redirectTo: '/heroes', pathMatch: 'full' }, { path: '**', component: PageNotFoundComponent } ]; @NgModule({ imports: [ RouterModule.forRoot( appRoutes, { enableTracing: true } // <-- debugging purposes only ) // other imports here ], ... }) export class AppModule { } .compontent.ts(template)//实现点击跳转 <h1>Angular Router</h1> <nav> <a routerLink="/crisis-center" routerLinkActive="active">Crisis Center</a> <a routerLink="/heroes" routerLinkActive="active">Heroes</a> </nav> <router-outlet></router-outlet> 注意:path不能以斜杠(/)开头 |
|
路由的钩子函数 | 全局钩子函数: before each:意思是在 每次每一个路由改变的时候都得执行一遍。 它的三个参数: to: (Route路由对象) 即将要进入的目标 路由对象 to对象下面的属性: path params query hash fullPath matched name meta(在matched下,但是本例可以直接用) from: (Route路由对象) 当前导航正要离开的路由 next: (Function函数) 一定要调用该方法来 resolve 这个钩子。 调用方法:next(参数或者空) ***必须调用 next(无参数的时候): 进行管道中的下一个钩子,如果走到最后一个钩子函数,那么 导航的状态就是 confirm afterEach:after 钩子没有 next 方法,不能改变导航,代表已经确定好了导航怎么去执行后,附带的一个执行钩子函数 组件内的钩子函数:( beforeRouteEnter 和 beforeRouteLeave 再加一个 watch函数 ) |
每个路由都有Enter和Leave钩子,用户进入或离开该路由时触发。 1.onEnter钩子函数 <Route path="inbox" component={Inbox}> <Route path="messages/:id" onEnter={ ({params}, replace) => replace(`/messages/${params.id}`) } /> </Route> 2.setRouteLeaveHook方法为Leave钩子指定routerWillLeave函数 componentDidMount() { this.props.router.setRouteLeaveHook( this.props.route, this.routerWillLeave ) } routerWillLeave(nextLocation) { return '确认要离开?'; } |
Router Event路由器事件(即钩子函数) NavigationStart:本事件会在导航开始时触发。 RoutesRecognized:本事件会在路由器解析完URL,并识别出了相应的路由时触发 RouteConfigLoadStart: 本事件会在Router对一个路由配置进行惰性加载之前触发。 RouteConfigLoadEnd:本事件会在路由被惰性加载之后触发。 NavigationEnd:本事件会在导航成功结束之后触发。 NavigationCancel:本事件会在导航被取消之后触发。 这可能是因为在导航期间某个路由守卫返回了false。 NavigationError:这个事件会在导航由于意料之外的错误而失败时触发。 路由器部件 Router(路由器):为激活的URL显示应用组件。管理从一个组件到另一个组件的导航 RouterModule(路由器模块):一个独立的Angular模块,用于提供所需的服务提供商,以及用来在应用视图之间进行导航的指令。 Routes(路由数组):定义了一个路由数组,每一个都会把一个URL路径映射到一个组件。 Route(路由):定义路由器该如何根据URL模式(pattern)来导航到组件。大多数路由都由路径和组件类构成。 RouterOutlet(路由出口):该指令(<router-outlet>)用来标记出路由器该在哪里显示视图。 RouterLink(路由链接):该指令用来把一个可点击的HTML元素绑定到路由。 点击带有绑定到字符串或链接参数数组的routerLink指令的元素就会触发一次导航。 RouterLinkActive(活动路由链接):当HTML元素上或元素内的routerLink变为激活或非激活状态时,该指令为这个HTML元素添加或移除CSS类。 ActivatedRoute(激活的路由):为每个路由组件提供提供的一个服务,它包含特定于路由的信息,比如路由参数、静态数据、解析数据、全局查询参数和全局碎片(fragment)。 RouterState(路由器状态):路由器的当前状态包含了一棵由程序中激活的路由构成的树。它包含一些用于遍历路由树的快捷方法。 链接参数数组:这个数组会被路由器解释成一个路由操作指南。我们可以把一个RouterLink绑定到该数组,或者把它作为参数传给Router.navigate方法。 路由组件:一个带有RouterOutlet的Angular组件,它根据路由器的导航来显示相应的视图。 |
|
ajax数据请求 | axios,resource | |||
ref传值 | 1.传值 <input type="text" value="调试 vuejs 2.0" ref="input1"> 2.接参 this.$refs.input1可以访问到该组件实例,其实就是dom元素节点。 |
1.传值 <input ref="myInput" /> 2.接参 var input = this.refs.myInput; |
0 0 0 0 0 0 0 0 0 0 |
|
url传参 | 方法一: this.$router.push({ name: 'routePage', query/params: { routeParams: params } 方法二: 两种方式 <a v-link="{ name: 'history', params: { deviceId: deviceId, dataId: dataId }}">history</a> |
学习网址:http://blog.csdn.net/qq_23158083/article/details/68488831 一.props.params 传一个对象: 1.在路由设置里 <Route path='/user/:data' component={UserPage}></Route> 2.在跳转文件里 import {Link,hashHistory} from 'react-router'; var data = {id:3,name:sam,age:36}; data = JSON.stringify(data); var path = `/user/${data}`; 方法一:<Link to={path}>用户</Link>> 方法二:ashHistory.push(path); 3.在跳转到的文件里: 接参:var data = JSON.parse(this.props.params.data); var {id,name,age} = data; 传一个值: 1.在路由设置里 <Route path='/user/:name' component={UserPage}></Route> 2.在跳转文件里 import {Link,hashHistory} from 'react-router'; 方法一:<Link to="/user/sam">用户</Link> 方法二:hashHistory.push("/user/sam"); 3.在跳转到的文件里: 接参:this.props.params.name 二、query 1.在路由设置里 <Route path='/user' component={UserPage}></Route> 2.在跳转文件里 import {Link,hashHistory} from 'react-router'; var data = {id:3,name:sam,age:36}; var path = { pathname:'/user', query:data, } 方法一:<Link to={path}>用户</Link> 方法二:hashHistory.push(path); 3.在跳转到的文件里: 接参:var data = this.props.location.query; var {id,name,age} = data; 三.state 1.在路由设置里 <Route path='/user' component={UserPage}></Route> 2.在跳转文件里 import {Link,hashHistory} from 'react-router'; var data = {id:3,name:sam,age:36}; var path = { pathname:'/user', state:data, } 方法一:<Link to={path}>用户</Link> 方法二:hashHistory.push(path); 3.在跳转到的文件里: 接参:var data = this.props.location.query; var {id,name,age} = data; state方式依然可以传递任意类型的数据,而且可以不以明文方式传输。 |
||
url参数的获取方法 | this.$route.params 例如: ready: function(){ console.log('deviceid: ' + this.$route.params.deviceId); console.log('dataId: ' + this.$route.params.dataId); } |
this.props. 例如: router4的获取参数值方式 { this.props.match.params.id } router2的获取方式 参考网址:http://blog.csdn.net/starwmx520/article/details/50772943 //通过this.props.params.XX //通过this.props.location.query.XX |
||
vuex | redux | |||
含义 | 在Vue中,多组件的开发给我们带来了很多的方便,但同时当项目规模变大的时候,多个组件间的数据通信和状态管理就显得难以维护。而Vuex就此应运而生。将状态管理单独拎出来,应用统一的方式进行处理,在后期维护的过程中数据的修改和维护就变得简单而清晰了。Vuex采用和Redux类似的单向数据流的方式来管理数据。用户界面负责触发动作(Action)进而改变对应状态(State),从而反映到视图(View)上 | |||
State设置状态,但它不会进行直接状态的修改。负责存储整个应用的状态数据,一般需要在使用的时候在跟节点注入store对象,后期就可以使用this.$store.state直接获取状态 mapState 辅助函数。当一个组件需要获取多个状态时候,将这些状态都声明为计算属性会有些重复和冗余。为了解决这个问题,我们可以使用 mapState 辅助函数帮助我们生成计算属性,让你少按几次键 ...mapState使用对象展开运算符将此对象混入到外部对象中 Getter 只获取状态,不做任何修改 mapGetters 辅助函数 Mutation } } } commit:提交载荷、】store.commit('increment', 10) } } } Action } } } } } } Module } } } } } } } } } } } } } } } } } } } http://blog.csdn.net/sinat_17775997/article/details/54943797 } } } |
} } } } } } } } } } } } |
|||
State Getter Mutation Action Module |
||||
angular2 | MVC | |||