前端框架(MV*/ReactJS/VueJS/AngularJS)

fvuMV*(MVC、MVP、MVVM)

参考:http://blog.csdn.net/kevin_1025745654/article/details/45815109

MV*

已知:M(数据与数据逻辑,例如ajax、本地存储模块)
后端的MVC:M提供数据API;V 即模板,可以直接从M获取数据,C 即控制显示哪个模板

前端的MV*
MVC : V(视图逻辑,backbone里的V即View模块),C(控制视图的显示,backbone里的C即Router模块)

MVP : P(Presenter主持人,或者Passive View被动视图。负责响应V,调用M,更新V)。也可以把backbone的View理解为P。
MVP与MVC的差别:MVC里的V直接调用M的接口,MVP中则不能,得通过中间人P。

MVVM : V(模板),VM(视图模型,即数据与视图绑定,数据逻辑与视图逻辑绑定。普通的M的对外提供接口,VM则自动绑定视图。angularJS里VM即controller组件,里面的逻辑即数据逻辑,里面的scope即数据)
MVVM与MVP的差别:P要显式操作V,而VM与V双向绑定。
优势:代码结构更好(易维护,易打包),双向绑定和组件化(易开发,易协同)

MV*的区别在于V与M之间的流程,MVC中V直接调用M。MVP中V调用P,P再调用M。MVVM中V绑定VM,VM调用M。

单页应用

单页应用的路由模块的实现原理:
1、地址栏有锚值(有 # 号),刷新时浏览器发的请求不带 # 号及后面部分
2、通过location.hash 可以读写锚值(带#号)
3、改变锚值时会增加一条历史记录,但不会重载页面
4、window.onhashchange 监听锚值变化事件

5、另有history.pushState(状态对象, 新标题, 新url)方法和 window.onpopstate 事件。state与hash是两码事,pushState或回退的时候会触发onpopstate并传入状态对象

backbone自带路由模块,不能嵌套

angularjs 路由模块:https://github.com/angular-ui/ui-router ,可嵌套

reactjs路由模块:https://github.com/reactjs/react-router,可嵌套

组成部分:MV*、模块加载工具、路由、打包工具、UI组件

前端架构

1、无模块加载系统:html 引入一个js,js为一个自调用函数(闭包)
2、有模块加载系统:html 引入模块加载库 和 入口模块,入口模块中再去加载其他模块。这些模块可以是backbone的View、Angular的controller、React的component,也可以是完全自定义的闭包揭示模块、构造器模块
3、单页应用:在2的基础上监听 state 或 hash,重新渲染页面。

数据绑定

本质上是三种方式 1、(angularjs 1.x)监控数据变化,操作DOM;2、(react)整体更新虚拟DOM,diff,操作DOM;3、(vue)监控数据变化,局部更新虚拟DOM,diff,操作DOM

监控数据变化之脏检查

     angularJS 1.x采用,在controller或$apply中改变scope的属性,会自动调用$dist,进行脏检查。发生变化的属性,调用其$watcher。view中写ng-,会自动为其创建$watcher。

监控数据变化之对象监控
Object.observe:Chrome、ES7;Object.observe(model,function(changes){ // changes里包含变化信息}),支持的浏览器少

监控数据变化之属性访问器

1、Object.defineProperty:Vue采用,原生支持
Object.defineProperty(obj,‘name’,//三个参数分别为:对象、属性名、属性描述对象

    configurable: false,  //属性是否可配置
    enumerable: true,    //属性是否可枚举
    writable: true,      //属性是否可重写,不能与set/get同存
    value: null,         //属性的默认值,不能与set/get同存
    set: undefined,     // 重写器,这里可以写入数据绑定逻辑
    get: undefined      // 读取器
})
Object.getOwnPropertyDescriptor(obj, 'name');// 获取属性描述对象

2、非原生:backbone的model,属性只能通过get 和 set访问,通过listen给他们挂钩子。backbone只给了监控数据变化的方法,不会自动操作DOM,隐藏没有数据绑定

监控数据变化之代理

用Proxy实现:Vue 3

MVVM对比

   1、如何检查model变化:脏检查(angularjs) 、 访问器(vue、backbone)、整体重新渲染,无需检查(react)
   2、如何更新视图:串行直接操作DOM(angularjs)、通过虚拟DOM
   3、数据绑定:单项(react)还是双向(angularJS、Vue)
   4、代码分离:JS、HTML是否分离,JSX需要经过编译,不好调试和定位错误
   5、体积、社区、文档等
   6、组件

Reactjs + Redux

Reactjs

demo: https://github.com/saoraozhe3hao/reactDemo

react
React为此引入了虚拟DOM(Virtual DOM)的机制:
在浏览器端用Javascript实现了一套DOM API。基于React进行开发时所有的DOM构造都是通过虚拟DOM进行,每当数据变化时,React都会重新构建整个DOM树,
然后React将当前整个DOM树和上一次的DOM树进行对比,得到DOM结构的区别,然后仅仅将需要变化的部分进行实际的浏览器DOM更新

而且React能够批处理虚拟DOM的刷新,在一个事件循环(Event Loop)内的两次数据变化会被合并

Virtual DOM :维护在内存的类似于DOM树的JavaScript对象树,对变化批量更新至Web DOM树.虚拟DOM的节点记录了元素名称,属性名称和值
组件间的通信,父组件引用子组件,子组件回调父组件,EventEmitter(npm events 包)
在componentDidMount 里面可以元素 和 body、window 绑定原生事件,在componentWillUnmount里解除


JSX 转 JS
运行时转换: <script src="reactjs/JSXTransformer.js"></script>
打包时转换:
    安装命令行工具 npm install -g react-tools

转换:jsx --watch jsx/ js/

Redux

Demo: https://github.com/saoraozhe3hao/reduxDemo

Flux

Flux是Facebook提出的一种 前端应用架构体系,其中 react 作为它的View层。

Redux

Redux 是 Flux 体系的一个实现框架

Redux实现单项数据流

import { createStore } from 'redux' // Redux 的API :createStore

import reducer from './reducer' // reducer需要自己实现,输入 state 和 action,返回新的state

const store = createStore(reducer) // 全局只创建一个 store,用于存放数据。可加第二个参数,作为store初始数据

<label>{store.getState().label}</label> // store的API:getState,获取store快照

<button onClick={() => store.dispatch({ type: 'CLICK_BUTTON' }}> // store的API:dispatch,在事件处理函数中分发action

store.subscribe(render) // store的API:subscribe,store变化时启动

事件 -> store.dispatch(action)[调用reducer,更新store] -> 触发store.subscribe注册的render或setState -> store.getState得到新的state

Redux 的API:combineReducers,用于对reducer的拆分

react-redux

import { Provider, connect } from 'react-redux' // react-redux 的 API:Provider、connect

const App = connect(

mapStateToProps, // function(state){return props}, 用于设置 UI组件的 props

mapDispatchToProps // function(dispatch){return {functions}} 用于给 UI组件的props 添加 事件处理函数,事件处理函数中调用 dispatch

)(UI 组件) // 返回一个容器组件

ReactDOM.render(

<Provider store={store}>

<App /> // 使用容器组件

</Provider>,

document.getElementById('root')

)

react-router-redux

import {browserHistory} from 'react-router'

import {createRouterMiddleware,synHistoryWithStore,push} from 'react-router-redux'

const store = createStore(

reducers,

applyMiddleware(createRouterMiddleware(browserHistory)) // 路由中间件

)

<Router history={synHistoryWithStore(browserHistory,store)}></Router> // 增强的history

store.dispatch(push('/home')) //路由操作

中间件(middleware)redux-saga 改造store.dispatch实现异步分发action

import createSagaMiddleware from 'redux-saga' // redux-saga 的API:createSagaMiddleware

const sagaMiddleware = createSagaMiddleware() // 生成中间件

const store = createStore(

reducer,

Redux.applyMiddleware(sagaMiddleware) // Redux 的API:applyMiddleware,应用中间件

);

sagaMiddleware.run(saga) // saga 是一个Generator函数,含有action和处理函数的对应关系

saga

import { call, all,take, put,takeEvery } from 'redux-saga/effects'

export default function* saga() {

yield takeEvery('ACTION_TYPE', gen) // takeEvery 相当于 while(true){take},等待一个action,去执行gen

}

function* gen(){

var result = yield fetch(url); // fetch返回一个promise,该Generator函数调用者执行promise.then(function(data){g.next(data);}),g为gen返回的遍历器

console.log(result); // g.next后才会执行到这里,result被替代为g.next传进来的data

}

reactjs、webpack、babel、eslint

demo: https://github.com/saoraozhe3hao/webpackDemo

react的优点:组件式开发,高复用、低耦合

react生命周期
render: getDefaultProps、getInitialState、componentWillMount、render、componentDidMount

props change: componentWillReceiveProps、shouldComponentUpdate、componentWillUpdate、render、componentDidUpdate

state change:shouldComponentUpdate、componentWillUpdate、render、componentDidUpdate

服务端渲染

首屏由服务端动态语言 根据数据和DOM结构 动态生成,以提高首屏渲染速度,同时利于SEO。

如果服务端用的 nodejs,浏览器端用的 reactjs ,那么可以在服务端用 ReactDOMServer.renderToString( APP ) 来生成渲染后的DOM结构,提供给浏览器。

相对于其他情况的 服务端渲染,nodejs + reactjs 这种情况不用单独去开发一套生成首屏的代码

构建
 webpack 对 CommonJS 模块进行包装,使得能在浏览器运行
 webpack 将 首屏所需的文件归纳成一个入口 chunk,并合并成bundle。非首屏所需文件,每个功能点所需的文件也归纳成一个个chunk,并合并成bundle,被按需加载。将代码拆分成不同的chunk,成为代码拆分 code splitting。
 
commonJS 模块按需加载方式
require.ensure(["module-a", "module-b"], function(require) {
  var a = require("module-a");   // ensure只加载不执行,require的时候才执行
});


AMD模块按需加载方式
require(["module-a", "module-b"], function(a, b) {
 
});


ES6 模块按需加载方式(需要babel loader)
System.import('./module1.js')  
    .then(function(module1){  
        //use module1  
    }, function(e){  
        //handle error  
    }); 
import('./module2').then((module)=>{})

模块提取(剥离)
module.exports = {
  entry: { //声明两个入口chunk
    app: "./app.js",                          
    app1: "./app1.js"
  },
  output: {  // 所有入口chunk都将被打包入bundle.js。如果配置成"[name].js" ,将一个入口chunk打包成一个js
    filename: "bundle.js"
  },
  plugins: [
    new webpack.optimize.CommonsChunkPlugin("vendor.bundle.js")   
// 将所有入口chunk用到的公共模块提取出来(同时剔除),打包成vendor.bundle.js
  ]
};
<script src="vendor.bundle.js"></script>
<script src="bundle.js"></script> 

vue 2 + Webpack 4

demo: https://github.com/saoraozhe3hao/vueDemo

常用组件

路由:vue-router

状态管理:vuex

服务器端渲染SSR:nuxt

移动端组件库:Mint UI(饿了么)、vonic、vux (WeUI规范)、京东 NutUI、滴滴 CubeUI、有赞Vant、TDesign Vue(腾讯)

桌面端组件库:elememt UI(饿了么)、muse-ui(Material Design 规范)、iView(Ant Design 规范)、N3 Components、AT UI(京东)、Ant Design Vue(阿里)、TDesign Vue(腾讯)

专题:https://www.awesomes.cn/subject/vue

Material Design:谷歌提出的一套界面设计标准

element UI

安装:npm install element-ui --save

在main.js中引入:

import'element-ui/lib/theme-default/index.css'//引入element-ui的样式

import ElementUI from 'element-ui'  // 引入 element-ui

安装使用:Vue.use(ElementUI)          // 使用插件

VUX

更新nodejs版本
安装vux: npm install vux --save
安装vux-loader: npm install vux-loader --save-dev
在 webpack.base.conf.js 里配置 vux-loader。vux-loader使得组件能按需打包。

表单生产 vue-form-making

GitHub - GavinZhuLei/vue-form-making: A visual form designer/generator base on Vue.js, make form development simple and efficient.(基于Vue的可视化表单设计器,让表单开发简单而高效。)

http://docs.form.xiaoyaoji.cn/zh/

vue 引入工具库

import moment from 'moment';

Object.definePrototype(Vue.prototype, '$moment', { value: moment });

// 相当于 Vue.prototype.$moment = moment ;

vue实例中使用 this.$moment;

组件生命周期

beforeCreate、created、beforeMount、mounted、beforeUpdate、updated、activated、deactivated、beforeDestroy、destroyed

选择vue的原因

学习成本低:国人出品,有很好的中文文档

开发效率高:angular和vue是双向绑定,react是单向绑定

运行性能高:vue和react都不用脏检查,并采用了虚拟DOM,angular需要脏检查

封装更简洁:组件要素(模板、脚本、样式)高聚合(可以写在一个文件里)低耦合(不混写)

开发更友好:react需要写JSX,angular需要写TypeScript,vue都是原生语法

实现更优雅:angular脏检查,react需要setState(),vue重写读写检查器

模板语法、computed、watch、methods的使用选择

1、简单关联逻辑,使用模板语法

2、多个属性的变化,都会影响一个属性,使用computed,减少watch

3、计算逻辑需要被重用,使用模板语法 调用 methods

4、一个属性的变化,要改变多个属性,选择使用watch 或 methods(绑定input事件)

5、不需要实时变化 或者 不需要每次变化都处理(例如重置),选择使用 methods(绑定click事件)

Router History 模式

原理:history.pushState({}, 'title', 'path') 时,url会增加/path,但是页面不会刷新

1、Router 配置

new VueRouter({
   mode:"history",   // 使得 url 中不会出现 #
   base:"/test"      // 使得 路径前始终有 /test
}

2、webpack 配置

 assetsPublicPath: '/test/'  // 使得引用文件的路径始终有 /test/

3、nginx 配置

    location /test {
        try_files $uri $uri/ /index.html;  // 使得跳到一个路由后 刷新浏览器,能把index.html返回回去
        root /usr/test/;
    }

Vue2.0双向绑定的原理 

MVVM框架的三个组成:数据监听器Observer、指令解析器Compile、订阅器Watcher

Observer:Dep是一个订阅发布模块,组件的一个 data 属性对应一个Dep实例;Vue扫描组件的 data ,用Object.defineProperty()给data的属性添加 getter / setter,在setter中触发Dep发布(Dep实例和getter / setter 在一个闭包中)

Watcher:一个组件实例对应一个Watcher实例,在Watcher中触发data属性的getter,在getter中添加Dep订阅

Compile:Compile是一个函数,用于解析模板指令,初始化渲染页面视图(将模板中的变量替换成数据),给每个指令对应的节点绑定更新函数,调用Watcher添加Dep订阅(数据有变动时,收到通知,触发更新函数,更新视图)

从视图交互变化到模型数据变化:解析模板指令时,对 v-model 的节点添加 input 事件处理函数,更新模型数据,进而触发 setter,从而触发Dep发布

监听数组变化:重写 [].__proto__ 里的方法,更改数组后,触发Dep发布

Vue 3

安装vue-cli:npm install -g @vue/cli@next
安装vue-cli-service:npm install -g @vue/cli-service-global
创建项目:vue create [project_name]

安装 axios、vue-router[4.0以上]、vuex[4.0以上]、less、less-loader(需要适配less的版本) 等依赖

页面配置:创建vue-cli配置文件 vue.config.js ,配置 pages

数据传递:

向下传:props、用$refs调用子组件的方法和变量

向上传:$emit、调用父组件传下来的props方法

任意传:利用 vuex

module.exports = {
    devServer: {
        proxy: {
            '/api': {  // 将前端发来的请求,转发到目标服务器,规避跨域问题(前端直接发请求到目标服务器)
                target: 'http://192.168.0.2:8000',  // 代理目标
                ws: true,        // 代理 websockets
                secure: false,  // 代理 https
                changeOrigin: true  // 跨域
            }
        }
    },
    pages: {
        login: {
            entry: 'src/login/main.js',  // page 的入口
            template: 'public/index.html',  // html 模板
            filename: 'login.html',  // 在 dist里 的输出
            title: '登录'  // html 模板 里用到的变量
        },
        operation: {
            entry: 'src/console/main.js',
            template: 'public/index.html',
            filename: 'index.html',
            title: '控制台'
        }
    }
};

vue-cli-service

package.js中scripts下,vue-cli-service build --mode **,--mode指示的是使用哪个.env文件

.env文件中,NODE_ENV = production/development,指示构建方式

第三方库

VueUse

Angular 4 + Webpack 4

Angular 4 + Webpack 4 Demo

https://github.com/saoraozhe3hao/angluar4Demo

npm install

npm install -g webpack-cli

npm run webpack-server

访问 http://localhost:8080/

Angular 与 AngularJS

AngularJS = AngularJS 1.x

Angular = Angular 2+ ,Angluar4兼容Angular2

AngularJS中子组件scope会继承父组件scope的字段,子组件中可以改变父组件的字段,脏检查时会出现循环往复。Angular2 编译器为每个组件自动创建各自的变化检查器,每次检查都是单向的。
Angular使用Zone.js包裹了原生的setTimeout,addEventListener、promise等异步操作,并setup了相应的钩子。异步回调时触发相应钩子,通知angular2做相应的脏检查处理,不用$scope.$apply()。
 

Angular 4

组件初始化生命周期
constructor -> ngOnChanges -> ngOnInit -> ngDoCheck -> ngAfterContentInit -> ngAfterContentChecked -> ngAfterViewInit -> ngAfterViewChecked -> ngOnDestroy
组件更新生命周期
ngOnChanges -> ngDoCheck -> ngAfterContentChecked -> ngAfterViewChecked
框架模块
@angular/core @angular/common @angular/forms @angular/http @angular/router
项目结构
index.html -> main.ts(入口文件) -> app.module.ts(主模块,应用模块) -> app.component.ts(根模块) -> 特性模块 -> 共享模块

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值