【亚洲必赢官网】前端组件化开发mobile,大型单页面应用的进阶挑衅

大型单页面应用的进阶挑战

2015/09/30 · HTML5,
JavaScript ·
单页应用

初稿出处: 林子杰(@Zack__lin)   

翻阅须知:那里的巨型单页面应用(SPA Web
App)是指页面和功用组件在一个某部量级以上,举个栗子,比如
30+个页面100+个零部件,同时伴随着大批量的多少交互操作和八个页面的多寡同步操作。并且那里提到的页面,均属于
hash 页面,而多页面概念的页面,是一个独立的 html
文档。基于那些前提,大家再来啄磨,否则自身怕大家 Get 不到同一个 G 点上去。

前者发展与现状

大家都知晓前端是由HTML、CSS、Js组成的,一开始那样写出来的页面,不可以有些加载,复用性相比差,重复工作比较多。微软就推出了ifram标签,就是相当于在网页中嵌套一个网页,切换目录只是切换ifram中的网页,仍然一贯加载某个完整的html界面。接着ajax的面世,达成了有的刷新,优化了用户体验。后来进来了jQuery时代,jQuery封装了广大原生方法,收缩了代码量。现在我们前端进入了左右端分离时代,流行
MV* 框架(MVC、MVP、MVVM),MVVM框架有Angular、Vue、React。

亚洲必赢官网 1

MVVM框架

前几天我们后台管理序列是依照Vue开发的单页面应用(SPA)。

本文头阵于TalkingCoder,一个有逼格的程序员社区。转发请申明出处和小编。

本文版权归微博和小编吴双本人共同持有 转发和爬虫请评释原文地址
www.cnblogs.com/tdws

挑衅一:前端组件化

按照大家所说的前提,首个面对的挑衅是组件化。那里仍旧要强调的是组件化根本目的不是为了复用,很五个人平素没想精通那点,总是觉得造的车轱辘其他事情可以用,说不定未来也可以用。

实际前端发展迭代这么快,交互变化也快,各类适配更新数见不鲜。今天造的车轱辘,过阵子别人造了个高级轮子,大家都会选更尖端的轮子,所以现在前端界有一个气象就是为了让别人用自己的车轮,自己努力不停地造。

在前者工业化生产趋势下,即使要增进生产功效,就必须让组件规范化标准化,达到怎么着的水准吗?一辆车除了底盘和车身框架须要自己规划制作之外,其余标准化零件都能够购买组装(专业学得差,有吗谬误请指正)。也就是说,除了
UI
和前端架构需要自己解决之外,其余的零件都是可以普及拿来主义的,如果打算让自行车跑得更稳更安全,可以对组件进行打磨优化完善。

说了那般说,倒不如看看徐飞的篇章《2015前端组件化框架之路》 里面写的始末都是通过一定实践得出的想法,所以半数以上情节本身是同情而且深有体会的。

Vue不难介绍

1、Vue.js是一个构建数据驱动的web框架
2、Vue.js已毕了数量的双向绑定和组件化
3、Vue.js只需求关周详据的变型,无需繁琐的得到和操作dom
诸如给一个因素绑定事件并赋值,jQuery的做法是:

<input class="ipt" type="text">
<button class="btn"></button>
<script type="text/javascript">
$.ready(function () {
        $('.ipt').value();
        $('.btn').click(function() {    
        })
 })
</script>

vue的写法是:

<input class="ipt" v-model="value" type="text">
<button class="btn" @click="click"></button>

.vue文件的写法

<template>
    这里写HTML
</template>
<script type="text/ecmascript-6">
    这里写数据和方法
</script>
<style lang="stylus" rel="stylesheet/stylus">
    这里写css
</style>

写在眼前

一.写在面前

类型上线有一段时间了,一个基于webpack+vue+ES6的无绳电话机端多页面使用。其实说是多页面使用,实际上在webpack中属于八个app,
 假诺真是做纯单页面,那应该有二三十个页面吗。所以自己那里的多页面使用,是分为七个SPA。比如微信最上边,有八个导航,微信,通信录,发现,我。
那么这三个导航,就是自我的三个SPA,配置多个入口即可。

在那边就不说太多代码了,项目结构将会安置github上,地址在后头给出,以供参考,上传的大体只是一个索引加上配置景况,其实关键点也就在webpack.config.js了,那里最主要安顿了entry,loader,plugins,output目录啥的。

在此间先附上package.json和webpack.config.js吧:

 

亚洲必赢官网 2亚洲必赢官网 3

 1 {
 2   "name": "my-web",
 3   "version": "1.0.0",
 4   "description": "desc",
 5   "main": "index.js",
 6   "scripts": {
 7     "test": "echo \"Error: no test specified\" && exit 1",
 8     "start": "webpack-dev-server --inline --hot",
 9     "dev1": "webpack-dev-server --open",
10     "dev": "webpack-dev-server --inline --hot",
11     "build": "set NODE_ENV=production&&webpack"
12   },
13   "author": "ws",
14   "license": "ISC",
15   "devDependencies": {
16     "babel-core": "^6.24.1",
17     "babel-loader": "^7.0.0",
18     "babel-plugin-transform-runtime": "^6.23.0",
19     "babel-preset-es2015": "^6.24.1",
20     "babel-runtime": "^6.23.0",
21     "css-loader": "^0.28.4",
22     "extract-text-webpack-plugin": "^2.1.0",
23     "glob": "^7.1.2",
24     "html-webpack-plugin": "^2.28.0",
25     "jquery": "^3.2.1",
26     "node-sass": "^4.5.3",
27     "sass-loader": "^6.0.5",
28     "slideout": "^1.0.1",
29     "style-loader": "^0.18.2",
30     "url-loader": "^0.5.8",
31     "vue": "^2.3.3",
32     "vue-croppa": "^0.1.0",
33     "vue-hot-reload-api": "^2.1.0",
34     "vue-html-loader": "^1.2.4",
35     "vue-ios-alertview": "^1.1.1",
36     "vue-loader": "^12.2.1",
37     "vue-resource": "^1.3.3",
38     "vue-router": "^2.7.0",
39     "vue-style-loader": "^3.0.1",
40     "vue-template-compiler": "^2.3.3",
41     "vue-touch": "^2.0.0-beta.4",
42     "webpack": "^2.6.1",
43     "webpack-dev-server": "^2.4.5"
44   }
45 }

View Code

 

亚洲必赢官网 4亚洲必赢官网 5

  1 var path = require('path');
  2 var webpack = require('webpack');
  3 // 将样式提取到单独的 css 文件中,而不是打包到 js 文件或使用 style 标签插入在 head 标签中
  4 var ExtractTextPlugin = require('extract-text-webpack-plugin');
  5 // 生成自动引用 js 文件的HTML
  6 var HtmlWebpackPlugin = require('html-webpack-plugin');
  7 var glob = require('glob');
  8 
  9 var entries = getEntry('./source/**/*.js'); // 获得入口 js 文件
 10 var chunks = Object.keys(entries);
 11 console.log('输出chunks', chunks);
 12 module.exports = {
 13     entry: entries,
 14     output: {
 15         path: path.resolve(__dirname, 'public'), // html, css, js 图片等资源文件的输出路径,将所有资源文件放在 Public 目录
 16         publicPath: '/public/',                  // html, css, js 图片等资源文件的 server 上的路径
 17         filename: 'js/[name].js',         // 每个入口 js 文件的生成配置
 18         chunkFilename: 'js/[id].[hash].js'
 19     },
 20     externals: {
 21         jquery: "$",
 22         EXIF: "EXIF",
 23         wx: "wx"
 24     },
 25     resolve: {
 26         extensions: ['.js', '.vue'],
 27         alias: {
 28             'vue': __dirname + '/lib/vue/vue.js',
 29             //'vue-alert': __dirname + '/lib/vue-alert/vue-alert.js'
 30         },
 31     },
 32 
 33     module: {
 34         loaders: [
 35             {
 36                 test: /\.css$/,
 37                 // 使用提取 css 文件的插件,能帮我们提取 webpack 中引用的和 vue 组件中使用的样式
 38                 //loader: "style-loader!css-loader",
 39                 loader: ExtractTextPlugin.extract({ fallback: 'style-loader', use: 'css-loader' })
 40             },
 41             {
 42                 // vue-loader,加载 vue 组件
 43                 test: /\.vue$/,
 44                 loader: 'vue-loader',
 45                 options: {
 46                     //解析.vue文件中样式表
 47                     loaders: {
 48                         // Since sass-loader (weirdly) has SCSS as its default parse mode, we map
 49                         // the "scss" and "sass" values for the lang attribute to the right configs here.
 50                         // other preprocessors should work out of the box, no loader config like this necessary.
 51                         //'scss': 'vue-style-loader!css-loader!sass-loader',
 52                         //'css': 'vue-style-loader!css-loader!sass-loader',
 53                         //'js': 'babel-loader',
 54                         //'sass': 'vue-style-loader!css-loader!sass-loader?indentedSyntax'
 55                         css: ExtractTextPlugin.extract({ fallback: 'vue-style-loader', use: 'css-loader' }),
 56                         //exclude: [
 57                         //    path.resolve(__dirname, ""),
 58                         //    //path.resolve(__dirname, "app/test")
 59                         //]
 60                         //exclude:'/source/course/course-detail/course-detail.css'
 61                     }
 62                     // other vue-loader options go here
 63                 }
 64             },
 65             {
 66                 test: /\.js$/,
 67                 // 使用 es6 开发,这个加载器帮我们处理
 68                 loader: 'babel-loader',
 69                 exclude: /node_modules/
 70             },
 71             {
 72                 test: /\.(png|jpg|gif|svg)$/,
 73                 // 图片加载器,较小的图片转成 base64
 74                 loader: 'url-loader',
 75                 query: {
 76                     limit: 10000,
 77                     name: './imgs/[name].[ext]?[hash:7]'
 78                 }
 79             }
 80         ]
 81     },
 82     plugins: [
 83         // 提取公共模块
 84         new webpack.optimize.CommonsChunkPlugin({
 85             name: 'vendors', // 公共模块的名称
 86             chunks: chunks,  // chunks 是需要提取的模块
 87             minChunks: chunks.length
 88         }),
 89         // 配置提取出的样式文件
 90         new ExtractTextPlugin('css/[name].css')
 91     ]
 92 };
 93 
 94 var prod = process.env.NODE_ENV === 'production';
 95 module.exports.plugins = (module.exports.plugins || []);
 96 if (prod) {
 97     module.exports.devtool = 'source-map';
 98     module.exports.plugins = module.exports.plugins.concat([
 99         // 借鉴 vue 官方的生成环境配置
100         new webpack.DefinePlugin({
101             'process.env': {
102                 NODE_ENV: '"production"'
103             }
104         }),
105          new webpack.optimize.UglifyJsPlugin({
106              compress: {
107                  warnings: false
108              }
109          })
110     ]);
111 } else {
112     module.exports.devtool = 'eval-source-map';
113     module.exports.output.publicPath = '/view/';
114 }
115 
116 var pages = getEntry('./source/**/*.html');
117 for (var pathname in pages) {
118     // 配置生成的 html 文件,定义路径等
119     var conf = {
120         filename: prod ? '../views/' + pathname + '.html' : pathname + '.html', // html 文件输出路径
121         template: pages[pathname], // 模板路径
122         inject: true,              // js 插入位置
123         minify: {
124             removeComments: true,
125             collapseWhitespace: false
126         },
127         hash:true
128     };
129     if (pathname in module.exports.entry) {
130         conf.chunks = ['vendors', pathname];
131         //conf.hash = false;
132     }
133     // 需要生成几个 html 文件,就配置几个 HtmlWebpackPlugin 对象
134     module.exports.plugins.push(new HtmlWebpackPlugin(conf));
135 }
136 
137 // 根据项目具体需求,输出正确的 js 和 html 路径
138 function getEntry(globPath) {
139     var entries = {},
140         basename, tmp, pathname;
141 
142     glob.sync(globPath).forEach(function (entry) {
143         basename = path.basename(entry, path.extname(entry));
144         tmp = entry.split('/').splice(-3);
145         pathname = tmp.splice(0, 1) + '/' + basename; // 正确输出 js 和 html 的路径
146         entries[pathname] = entry;
147     });
148     console.log(entries);
149     return entries;
150 }

View Code

【亚洲必赢官网】前端组件化开发mobile,大型单页面应用的进阶挑衅。 

亚洲必赢官网,开发工具使用的VS2017,本来使用WS,但是用习惯VS的自我或者受不了,毕竟17依旧太强大了嘛。既然是vue项目,那数据请求肯定就是vue-res,
路由就是vue-loader,编译es6豪门都是babel。 上面是体系社团预览:

亚洲必赢官网 6亚洲必赢官网 7亚洲必赢官网 8她俩各自是图片资源,引用库资源,宣布打包后的js和css,src源码和包裹后的html

挑战二:路由去中央化

依照大家所说的前提,中央化的路由维护起来很坑爹(即使做一多少个页面 DEMO
的就没需求出来现眼了)。MV*
架构就是存在那样个坑爹的题目,必要注解主题化 route(angular 和 react
等都亟待先注脚页面路由社团),针对不相同的路由加载哪些组件模块。一旦页面多起来,甚至只要有人偷懒直接在某个路由写了有些事务耦合的逻辑,这几个route 的可维护性就变得稍微不好了。而且用户访问的第三个页面,都亟需加载
route,就算其余路由的代码跟当前页面毫不相关。

我们再回过头来思考静态页面简单的加载形式。大家只要把 nginx 搭起来,把
html 页面放在对应的静态资源目录下,启动 nginx 服务后,在浏览器地址栏输入
127.0.0.1:8888/index.html
就可以访问到那几个页面。再繁杂一点,大家把目录整成上面的方式:

/post/201509151800.html /post/201509151905.html /post/201509152001.html
/category/js_base_knowledge.html /category/css_junior_use.html
/category/life_is_beautiful.html

1
2
3
4
5
6
/post/201509151800.html
/post/201509151905.html
/post/201509152001.html
/category/js_base_knowledge.html
/category/css_junior_use.html
/category/life_is_beautiful.html

那种目录结构很熟吧,对 SEO
很温馨吧,当然那是后话了,跟我们前几日说的不是四回事。那种目录结果,不用大家去给
Web Server 定义一堆路由规则,页面存在即重临,否则重返404,完全不须要多余的注明逻辑。

依照那种目录结构,我们得以抽象成那规范:

/{page_type}/{page_name}.html

1
/{page_type}/{page_name}.html

实际仍能更简单:

/p/{name}.html

1
/p/{name}.html

从组件化的角度出发,还足以那样子:

/p/{name}/name.js /p/{name}/name.tpl /p/{name}/name.css

1
2
3
/p/{name}/name.js
/p/{name}/name.tpl
/p/{name}/name.css

据此,依据大家简化后的逻辑,大家只须求一个 page.js
那样一个路由加载器,按照大家约定的资源目录结构去加载相应的页面,大家就不必要去干申明路由并且中央化路由那种蠢事了。具体来看代码。咱也无意去分析了,里面有注释。

品种协会

├── build // 构建相关
│ ├── build.js
│ ├── check-versions.js
│ ├── dev-client.js
│ ├── dev-server.js
│ ├── utils.js
│ ├── vue-loader.conf.js
│ ├── webpack.base.conf.js
│ ├── webpack.dev.conf.js
│ └── webpack.prod.conf.js
├── comm// 打包后生成的目录
│ ├── favicon.ico
│ ├── index.html
│ └── static
├── config // 配置相关
│ ├── dev.env.js
│ ├── index.js
│ └── prod.env.js
├── package.json //开暴发产依赖
├── server //服务及mock数据
│ ├── controller
│ └── mock
├── src //源代码
│ ├── App.vue // 入口页面
│ ├── api // 所有请求
│ ├── assets // 字体等静态资源
│ ├── common // 全局公用方法
│ ├── components // 全局公用组件
│ ├── favicon.ico
│ ├── index.html // html模板
│ ├── main.js // 入口js 加载组件 初步化等
│ ├── pages // 所有页面
│ ├── plugins // 全局工具
│ ├── router // 路由
│ └── store // 全局store管理
└── static // 第三方不打包资源
├── async.js
├── css
├── img
├── jquery-1.8.3.min.js
├── jquery.ztree.js
├── md5.js
├── paopao.js
├── spark-md5.js
├── tinymce
├── upload.js
├── upyun-mu.js
└── vue-style-loader

正文为浩如烟海小说,总共分四节,指出按顺序阅读:

二.几点紧要的取得

1.组件化开发爽啊,
调用者只须求关切输入和出口,代码明朗,不难有限支撑

2.vue-res promise异步风格太美观,太喜欢了。然而有坑,ios8.x,使用基础浏览器运行js,
不支持promise语法,所以须要在进口中,import多少个npm下载的node
module:

 npm i whatwg-fetch core-js es6-promise –save-dev

 亚洲必赢官网 9

3.记得之前做一个手机端项目,完全没有自动化,各种页面间跳转慢的一比,一点也不流利,项目布局不便于管理,重复代码尤其多。

 近百个页面js版本得不到控制,管理js,css引用困难。微信静态资源缓存如此惨重,没有版本控制,每个页面js版本的修改要人命。

4.解决缓存问题,应明令禁止html缓存,由于使用extract-text-webpack-plugin,可以确保你html入口中唯有简单的几行代码,等着自动化帮您引入所需js,所以即便禁止html缓存,也不会影响响应速度,毕竟我们的html文件
     也就1-2k左右.html禁止缓存的原因是防备,js更新后,js
hash版本已转移,但浏览器缓存的html中,如故是呼吁旧版本js文件,那样一来js版本控制变得没有意义。

  1. js调用手机壁画,
    调用安卓手机拍照不简单呀,所以若是只想在微信上采纳网页的话,指出选用微信js SDK。

6.
三星手机和个别安卓手机,使用原生input调用录像后,图片到页面中会出现旋转问题,所以在微信上
使用js sdk, 在其他浏览器上,就用EXIF.js  手动将其旋转90度
或者180度举行校订。

7.推荐一款mobile用的正确的弹窗组件
vue-ios-alert.  ios风格的弹窗。地址以及github:  
 http://isay.me/vue-ios-alertview/example/![](https://images2017.cnblogs.com/blog/686162/201709/686162-20170904231146210-1849602734.png)

 

8.手机上的 日期
时分秒选取器,推荐一个有坑的货
 https://github.com/k186 
有坑哦,使用的话,请看closed的首先个issue。别的日期选拔仍然相比较推荐原生。加上时分秒的话原生的恐怕就不佳用。亚洲必赢官网 10

9.页面touch切换tag 使用的一个vue-tab
 github找一找,ios8不辅助flex-shrink,要运用-webkit-flex-shrink。

  1. 上拉加载更加多用的vue-loadmore,侧方滑动菜单 使用了jquery的slideout

11.
假如路由比较多的话,提议路由独立分一个js配置,并且一定要按需加载,否则打包文件太大。假诺是用户点击率极高的路由,可以直接require进去。

12.局地js库,就不要通过require了,直接在html引入进来算了,毕竟这个库基本不会改变,也没必要决定版本

13.前端AOP,
 vue-res的拦截器点个赞,我得以在拦截器中,为自己每一个请求
都拉长authentication
header等音讯,像用jq的时候,我只好手动把ajax包装一层

14.像有些数据的加载,文字方面,最好预先给出加载中那种唤醒,无法给空白。列表的加载
要多考虑加载中,加载成功和暂无数据的拍卖。见过众多app和网页都是跻身到列表页,首先一个暂无数据的背景图给出去 
       了,结果稍等一下,数据又加载出来了….

15.即便早已组件化了,但自己还提出有一个每个页面公用需求require的js,我一般都叫application.js
 在此地 能够放一些您的常量,枚举,公共措施,helpers,utils,ajax
等配备,并且在此处可以import footer header vue-res vue-alert
等一些各样组件或者页面都须要的话的零件

16.热互换是必须的,比往日用gulp
livereload方便

17.手机端页面调试,推荐vConsole(去github找)。
示例:亚洲必赢官网 11亚洲必赢官网 12

18.透过babel编译es5的都没问题.。
 我有个独立的小成效,没用es6,直接谷歌(谷歌)调试开发,结果到了ios9.x上
 不襄助也不报错,未来防止踩进去吧。上面是代码:

亚洲必赢官网 13

19. IOS上测算时间 须求new Date(‘2017/09/09’)的格式,
 而无法应用横杠的格式

挑衅三:领域数据中央化

对于单向数据流循环和数码双向绑定哪个人优何人劣是永久也探究没结果的题目,要看是怎么业务场景什么事情逻辑,即使那几个前提没统一好说吗都是对牛弹琴。当然,这几个挑衅的前提是非后台的单页面应用,后台的前端根本就不必要考虑前端内存缓存多少的处理,直接跟接口数据库交互就行了。明确了这一个前提,大家随后切磋哪些叫世界数据主旨化。

眼前议论到两种多少绑定的措施,但是只要反复跟接口交互:

  • 内存数据销毁了,重新请求数据耗时浪费流量
  • 一经多少个接口字段部分不等同只是使用情况一样
  • 多少个页面一贯有一对的数码一致,不过先来后到导致某些计数字段不雷同
  • 多个页面的多寡一致,其中一些数据发生用户操作行为招致数据爆发变更

故此,我们须要在业务视图逻辑层和多少接口层中间增添一个
store(领域模型),而以此 store 须要有一个合并的 内存缓存 cache,那一个cache 就是中央化的数目缓存。那这一个 store 究竟是用来弄啥勒?

亚洲必赢官网 14

Store 具有多形态,每个 store
好比某一类物品的储存(领域,换个词不难通晓),如蔬果店 fruit-store,
衣裳店
clothes-store,蔬果店可以放苹果香蕉黑木耳,衣服店能够放半袖底裤人字拖。即使品种过于繁多,大家能够把蔬果店精细化运营变成香蕉专卖店,苹果专卖店(!==
appstore),甚至是木耳专卖店…( _
_)ノ|,蔬果种类不均等,不过也都是称重按斤卖嘛。

var bannerStore = new fruitStore();

var appleStore = new fruitStore();

有了那个囤积之后,咱们可以放心的把数量丢给视图逻辑层大胆去用。想修改数据?直接让
store 去改就行了,其余页面的 DOM
文本内容也得修改吧?那是其他页面的业务逻辑做的事,我们把事件抛出去就好了,他们处不处理那是他俩的事,咱别瞎操心(业务隔离)。

那么 store 具体弄啥勒?

亚洲必赢官网 15

  • 32
    个赞地点可点赞或者打消,多个页面的赞数须要共同,按钮点赞与打消的景观也要联合。
  • 条目是不是已收藏,取消收藏后 Page B 必要删除数据,Page A+C
    必要一起状态,假设在 Page C 又有收藏操作,Page B
    须求相应增减数据,Page A 状态须要共同。
  • 发评论,Page C 要求更新评论列表和评论数,Page A+B
    必要立异评论数。如若 Page B 没有被加载过,那时候 Page B
    获得的多寡应该是新型的,要求一块给 A+C 页面对应的数量进行创新。

由此,store
干的活就是数码状态读写和一道,假诺把数据状态的操作放到各样页面自己去处理,页面一旦多了或者复杂起来,就会时有暴发各样页面数据和景观恐怕不一样等,页面之前双向引用(业务耦合严重)。store
还有另一个效用就是数额的输入输出格式化,简单举个栗子:亚洲必赢官网 16

  • 其他接口 API 重返的数额,都亟需经过 input format
    举办统一格式化,然后再写入
    cache,因为读取的多寡已依照大家约定的规范举行的拍卖,所以我们运用的时候也不需要理会接口是回来怎么样的数据类型。
  • 好几零部件需求的多寡字段格式可能差距,假使把数据处理放在模板进行处理,会造成模板不可能更加简洁通用(业务耦合),所以须求output format 进行处理。

据此,store
就是扮演着那样的角色——是数据状态读写和同步,以及数额输入输出的格式化处理。

此地来大约讲一下src文件

《Vue+Webpack使用专业》

三.部分瑕疵

 1.脑子抽风啊,分为多个SPA,
整套项目下来,感觉如故应该做一个SPA。毕竟SPA之间切换,一个SPA切换到另一个SPA
还是加载东西太多,不够流畅。纵然微信浏览器缓存“严重”

2.档次布局划分依旧不够合理,但感到也还是可以应付用。

3.组件化没有表明到极致,自己vue组件间通讯没做好,md找子组件,我居然还有通过遍历的不二法门。

4.有些组件用的jquery的,搭配的不是很通畅,导致个别操作强行使用dom操作。

5.自身有三个条件,开发,测试,demo, 线上。
每回发表到一个条件
 都亟待改了安插后,重新包装,很难受啊,关于那一点有如何好的方法吧? 

挑战四:Hybrid App 化

今昔 Hybrid App 架构应用很火啊 _
(:3」∠)_,不搞一下都糟糕意思说自己是做 H5的。那里所说的 Hybrid App
可不是这种内置打包的 html 源码那种,而是直接去服务端请求 html
文档那种,可能会采取离线缓存。有的人以为只要要使用 Hybrid
架构,就不能够动用 SPA 的法子,其实 Hybrid 架构更应当采用 SPA。

遭逢的多少个问题,我大致列举一下:

  • 客户端通过 url 传参

    倘使经过 http get 请求的 query 参数举办传参,会导致命中不到 html
    文档缓存,所以通过 SPA 的 hash query 传参,可以规避那些题目。

  • 与其余 html 页面举行跳转

    那种情景下,进入新页面和重临旧页面导致 webview 会重新加载本地的
    html 文档缓存,视觉体验很不爽,即使页面使用了离线缓存,而 SPA
    可以避开这一个问题。

  • 使用了离线缓存的页面须要匡助代码多版本化

    由于使用了非覆盖性资源发表办法,所以要求照旧保留旧的代码一段时间,以预防用户使用旧的
    html
    文档访问一些按需加载功效或消除了本土缓存数据而拿不到旧版本代码。

  • js 和 css 资源 离线化

    由于离线缓存的资源必要先在 manifest
    文件宣称,你也不容许一连手动去体贴须要引用的 js 和 css
    资源,并且那个按需加载的功力也会由此失去按需加载的意义。所以必要将
    js 和 css 缓存到
    localstorage,直接省去这一步维护操作。至于用户清除
    localstorage,参考第三点解决方案。

  • 图标资源离线化

    将图标文件举行 base64 编码后存入 css 文件,方便离线使用。

api 和 views

咱俩公司后台项目如今大致有十多少个api模块。随着工作的迭代,模块会越加多。所以那边依照作业模块来划分pages,并且将pages
和 api 多个模块一一对应,方便维护,如下图

亚洲必赢官网 17

aip和pages.png

这般无论项目怎么累加,api和pages相比好维护。

《Vue+Webpack开发可复用的单页面富应用学科(配置篇)》

四.写在终极

 那几个类型产品将一而再支付,但是下一阶段还有个类型,我将运用一个SPA落成,关于vue有哪些好的种种mobile组件,希望dalao不吝推荐。

 

 

设若,您觉得读书那篇博客让你有些收获,不妨点击一下右下加【推荐】按钮。
若是,您愿意更便于地发现自家的新博客,不妨点击下方灰色【关心】的。
因为,我的分享热情也离不开您的自然协理。

感谢您的阅读,我将不断输出分享,我是蜗牛,
保持学习,谨记谦虚。不端不装,有趣有梦。

挑衅五:性能优化

@前端农民工 在 别处 已经说得很通晓了,直接传送门过去看吗,那里不罗嗦了。

 

1 赞 2 收藏
评论

亚洲必赢官网 18

components

此处的components放置的都是大局公用的一些组件,如上传组件,富文本等等。

亚洲必赢官网 19

components.png

《Vue+Webpack开发可复用的单页面富应用学科(组件篇)》

store

vex要按照须要去行使,我们后台项目来说,就算工作模块比较多,还有权力,但事情之间的耦合度是很低的,所以根本没有须求运用vuex来储存data,每个页面里存放自己的data就行。当然有些数据或者要求用vuex来归并管理的,如登录,用户新闻,依然用vuex管理有利于。

《Vue+Webpack开发可复用的单页面富应用学科(技巧篇)》

Router

路由那么些定义初始是在后台出现的,浏览器发出请求,服务器根据请求,解析url路径,根据服务器的路由配置,重临相应
html 字串。我们前端路由的兑现精神上就是检测 url 的变通,截获 url
地址,然后解析来匹配路由规则,每一回 hash 值的变迁,会触发 hashchange
这些事件,通过轮换 DOM
的章程来促成页面的切换,还有通过HTML5的五个api,pushState 和
replaceState落成记住路由。

在上一节中,大家介绍了在项目https://github.com/icarusion/vue-vueRouter-webpack中有关webpack的一部分基础配置,包涵支付环境和生育环境,在本节中,我们重点介绍使用Vue.js和vue-router,通过组件化的措施来支付单页面富应用的相干内容。读者可以clone或下载那几个类型,结合具体代码来看本文。

router-view

<router-view> 是用来渲染路径匹配到的组件。<router-view>
还足以内嵌<router-view>,落成路由嵌套。

 <keep-alive>
        <router-view v-if="$route.meta.keepAlive"></router-view>
 </keep-alive>

基础知识扫盲

最后

明日自己只是给大家简单来说了须臾间后台管理的构造和vue的简单知识,我们倘诺有趣味可以去领会一下,也可以每天互换~

本段主要介绍部分前端的根基概念,老司机可以一向跳过。

单页面富应用(SPA)和前端路由

单页面富应用(即Single Page Web
Application,以下简称SPA)应该是新近几年火起来的,更加是在Angular框架诞生后,很多SPA的网站以及基于Electron或Ionic的桌面App和移动App见惯司空,比如Teambition。

SPA的着力即是前者路由。何为路由呢?说的通俗点就是网址,比如www.talkingcoder.com/article/list;专业点就是历次GET或者POST等请求,在服务端有一个特意的正则配置列表,然后匹配到现实的一条路子后,分发到分化的Controller,然后进行种种操作后,最后将html或数额重返给前端,那就完事了一回IO。当然,近年来大多数的网站都是那种后端路由,也就是多页面的,这样的益处有无数,比如页面可以在服务端渲染好间接回到给浏览器,不用等待前端加载任何js和css就足以平昔体现网页内容,再例如对SEO的团结等。那SPA的症结也是很显眼的,就是模板是由后端来保证或改写。前端开发者须求设置任何的后端服务,需求还得上学像PHP或Java那一个非前端语言来改写html结构,所以html和数量、逻辑混为一谈,维护起来即臃肿也麻烦。然后就有了前后端分离的开支格局,后端只提供API来回到数据,前端通过Ajax获取到数码后,再用自然的主意渲染到页面里,这么做的长处就是前后端做的业务分的很清楚,后端专注在数额上,前端专注在竞相和可视化上,从此前后搭配,干活不累,即便将来再支付移动App,这就恰恰能动用一套API了,当然缺点也很明确,就是首屏渲染要求时日来加载css和js。那种支付形式被过多商家肯定,也应运而生了不少前端技术栈,比如以jQuery+artTemplate+Seajs(requirejs)+gulp为主的费用方式所谓是万金油了。在Node.js出现后,那种情况有了改正,就是所谓的大前端,得益于Node.js和JavaScript的语言特征,html模板可以完全由前端来支配,同步或异步渲染完全由前端自由支配,并且由前端维护一套模板,这就是为啥在服务端使用artTemplate、React以及将要生产的Vue2.0原因了。那说了如此多,到底什么算是SPA呢,其实就是在内外端分离的底子上,加一层前端路由。

前端路由,即由前端来爱慕一个路由规则。完毕有二种,一种是接纳url的hash,就是常说的锚点(#),JS通过hashChange事件来监听url的更动,IE7及以下需求用轮询;另一种就是HTML5的History情势,它使url看起来像普通网站那样,以”/”分割,没有#,但页面并从未跳转,不过使用那种情势须求服务端协助,服务端在收受到所有的伏乞后,都对准同一个html文件,不然会出现404。所以,SPA唯有一个html,整个网站有着的内容都在这个html里,通过js来拍卖。

前端路由的亮点有许多,比如页面持久性,像半数以上音乐网站,你都得以在播放歌曲的同时,跳转到其余页面而音乐没有停顿,再比如前后端彻底分手。前端路由的框架,通用的有Director,越多仍然整合具体框架来用,比如Angular的ngRouter,React的ReactRouter,以及大家前面用到的Vue的vue-router。那也牵动了新的付出情势:MVC和MVVM。近期前端也可以MVC了,那也是干什么那么多搞Java的钟爱于Angular。

付出一个前端路由,首要考虑到页面的可插拔、页面的生命周期、内存管理等。

编制可复用的代码、模块化、组件

编制可复用的代码是对编程质料的一个反映。写一个通用工具函数、维护一个对象,这个都得以说是可复用的,然则大家那边探讨的,重假使运用CommonJS规范来开展模块化开发。那代码复用和模块化有哪些关系呢,其实模块化的一个缘由就是可以使代码复用,你付出的模块可以提需要其余人用,一个模块可以是小到一个配备文件,也得以大到一个日历组件。把一个页面拆分成不一样的模块,然后来组装,那样既能升高支付效能,又有利于维护。那组件又是何许吗?如果说模块化是一种开发格局,那组件就是那种情势的现实性达成。比如一个Button按钮、一个输入框,或者一个上传控件都足以打包为一个零部件,在接纳的时候,可能只用写一行,就能兑现公文上传功用,甚至足以支撑拖拽上传、大小和格式限制等。那多少个零部件具体怎么支付呢,那就是本文前面重点讨论的情节了。

Vue的路由和它的组件化

在项目https://github.com/icarusion/vue-vueRouter-webpack中,大家接纳的技术栈是vue.js+vue-router+webpack,其中webpack的效应早已在上篇小说中详细介绍了。在说vue-router此前,大家先聊聊Vue的机件。

组件的构造

Vue的组件可以说是Vue中最神奇也是最难懂的一部分了,这有的懂了,vue也就懂了。vue组件的风味是可插拔、独立作用域、观望者形式、完整的生命周期。大家来看一个零件的基本构成:

Vue.component(‘child’, {    props: [‘msg’],    template:'{{ msg }}’, 
  data:function(){return{            title:’TalkingCoder’}    },   
methods: {// …},    ready:function(){    },   
beforeDestroy:function(){    },    events: {// …}});

一个组件基本跟一个vue实例是接近的,也有自己的methods和data,只不过data是透过一个function来回到了一个对象,具体原因可以查看vue的文档。

props是从父级通过html特性传递来的多少,它可以是字符串、数字、布尔、数组、对象,默认是单向的,也足以安装为双向绑定的。props里的参数能够一贯通过像this.msg那种艺术调用,那与data的里的数目是一律的。

template是其一组件使用的html片段,可以直接是字符串,也可以像’#child’那样标识一个dom节点。

ready和beforeDestroy是五个常用的生命周期,ready是在组件准备好时的一个回调,一般在那边大家得以行使获取数据、实例化第三方组件、绑定事件等,beforeDestroy正好相反,是在组件即将被销毁时接触回调,在此处大家销毁自定义的实例、解绑自定义事件、定时器等。

什么行使组件

组件一般是由它的父级来呈现调用的,比如上面的child组件,我们就足以在父级中选用:

newVue({    data:
{        msg1:’Hello,TalkingCoder’,        msg2:’你好,TalkingCoder’}})

上例使用了两回child组件,使用props传递了一个参数msg,并且首个零部件的参数是双向绑定的,在双向绑定后,无论修改父级依然子元素的msg,双方的多少和view都会响应到,而单向绑定后,子组件修改是不会影响到父级的。

在渲染完,的始末就会交替为组件template内的字符串了,尽管选用的是同一个child组件,但是一回接纳的功能域是单身的,那也是怎么在组件内data要选择function来回到一个目标的原委。

父子组件间的通讯

在Vue.js中,父子之间的通讯主要透过事件来已毕,那种就是大家熟习的寓目者情势(或叫订阅-公布方式),很多框架也都利用了这种设计格局,比如Angular。父组件通过Vue内置的$broadcast()向下播放事件和传递数据,子组件通过$dispatch()向上派发事件和传递数据,双方都足以在events对象内接受自定义事件,并且处理各自的作业逻辑。

父组件使用了多少个相同子组件,怎么样区分呢?譬如我们地点的demo使用了五次child组件,可是怎么来区分那多个吗,也就是说要是给child广播事件,如何给内部指定的一个播放呢,因为广播后,它俩都会吸收到事件的。大家得以行使v-ref来标识组件:

newVue({    data:
{        msg1:’Hello,TalkingCoder’,        msg2:’你好,TalkingCoder’},    methods:
{        sendData:function(){this.$refs.child1.$emit(‘set-data’,
{});this.$refs.child2.$emit(‘set-data’, {});        }    }})

通过$refs就可以给指定的零件触发事件了,事实上,通过$refs是可以获获得子组件的全套实例的。

子组件派发事件,而父组件仍旧选择了三个相同子组件,怎么着区分是哪些组件派发的吗?照旧地点的demo,比如大家的child组件$dispatch了一个自定义事件,可以这么来不一样:

newVue({    data:
{        msg1:’Hello,TalkingCoder’,        msg2:’你好,TalkingCoder’},    methods:
{        sendData:function(){this.$refs.child1.$emit(‘set-data’,
{});this.$refs.child2.$emit(‘set-data’,
{});        },        handler1:function(){//
…},        handler2:function(){// …}    }})

像绑定DOM2事件一样,使用@xxx或v-bind:xxx来绑定自定义事件,来执行不一的措施。

内容分发slot

偶然大家编辑一个可复用的零件时,比如下边的一个confirm确认框:

题目、关闭按钮是统一的,不过中间正文的情节(包蕴样式)是想自定义的,那时候就会用到Vue组件的slot来散发内容。比如子组件的template的内容为:

提示

确定打消

父组件这样调用子组件:

欢迎来到TalkingCoder

终极渲染完的始末为:

提示

迎接来到TalkingCoder

确定打消

编写可复用组件

此间引用一段出自vue.js文档的内容:

在编写组件时,记住是不是要复用组件有益处。一回性组件跟别的组件紧密耦合没关系,不过可复用组件应当定义一个清晰的公然接口。

Vue.js 组件 API 来自三局地——prop,事件和 slot:

prop允许外部环境传递数据给组件;

事件同意组件触发外部环境的 action;

slot同意外部环境插入内容到零部件的视图结构内。

运用v-bind和v-on的简写语法,模板的缩进清楚且精简:

Hello!

路由、组件和组件化

上文说了那么多,现在总算到根本了。在上一篇文章中,大家大约的关联了组件化,那也是将Vue使用到极致的必经之路。大家先看一下src/main.js文件。

Vue有点像Express的用法,也有中间件的概念,比如大家用到的vue-router,还有vuex,它们都是vue的中间件,当然大家团结也可以付出基于vue的中间件。

importVuefrom’vue’;importVueRouterfrom’vue-router’;importAppfrom’components/app.vue’;importEnvfrom’./config/env’;Vue.use(VueRouter);//
开启debug格局Vue.config.debug =true;// 路由安顿varrouter
=newVueRouter({    history: Env !=’production’});router.map({‘/index’:
{        name:’index’,       
component:function(resolve){require([‘./routers/index.vue’],
resolve);        }   
}});router.beforeEach(function(){window.scrollTo(0,0);});router.afterEach(function(transition){});router.redirect({‘*’:”/index”});router.start(App,’#app’);

如上代码就是main.js的情节,那也是我们项目跑起来后首先个实施的js文件。在导入了Vue和VueRouter模块后,使用Vue.use(VueRouter)安装路由模块。路由可以做一些大局配置,具体可以翻开文档,那里只说一个就是history,上文已经介绍了关于HTML5的History,它用history.pushState()和history.replaceState()来管理历史记录,服务器需求正确的计划,否则恐怕会404。开启后地址栏会像一般网站那样采取“/”来划分,比“#”要优雅很多,能够看看大家通过环境模块env.js默许给支付环境开启了History格局路由,生产条件并未开启,为的是可以让大家来体验到那两者的差别性,使用者可以自己来修改配置。

导入的app.vue模块就是大家的输入组件了,上篇小说已经介绍过,大家透过webpack生成的index.html里,body内唯有一个挂载节点

,当大家经过实践router.start(App,
‘#app’)后,app.vue组件就会挂载到#app内了,所以app.vue组件也是我们工程起来后,第二个被调用的机件,可以在它里面落成部分全局性的操作,比如获取登录音信啊,计算日活啊之类。

在app.vue内,有一个的自定义组件,它就是成套网站的路由挂载节点了,切换路由时,它的内容会动态的切换,其实是在动态的切换不相同的组件,得益于webpack,路由间的切换可以是异步按需加载。

router.map()就是设置路由卓绝规则,比如访问127.0.0.1:8080/index,就会协作到”/index”,然后经过component,在回调里应用require()异步加载组件,这一个历程是可以改为共同的,可是相应没有人会这样做。vue-router协助匹配带参数的路由,比如’/user/:id’可以合营到’/user/123’,或者’/user/*any/bar’可以包容到’/user/a/b/bar’,:id是参数,*any是全匹配,然而vue-router协理的路由规则依然相比弱的,一般后端框架,比如Python的Tornado或者Node.js的Express是永葆正则的。

vue的路由只是动态的调用组件,根本上依然MVVM,而Angular的路由是MVC的,在ng的controller里,可以使用templateURL来利用一个html片段,而vue的零件是不接济那种形式的,必须把html字符串写(或编译)在template里,因为在Vue的布署里,一个零件(.vue文件)是应该把它的样式、html和js紧耦合的,那多亏组件化的魅力所在。

嵌套路由。vue-router是支撑嵌套路由的,在app.vue里的是大家的根路由挂载,若是急需,可以在某个具体的路由组件里面再利用一个来散发二级路由。具体运用格局可查看文档。

途径跳转。vue-router使用v-link指令来跳转,它会隐式的在DOM上绑定点击事件:

首页首页

只若是在js里跳转,可以如此:

module.exports = {    data:function(){return{        }    },    methods:
{       
go:function(){console.log(this.$route);console.log(this.$router);this.$router.go(‘/index’); 
      }    }}

拔取vue内置的$router方法也足以跳转,假使感兴趣,能够尝试上边$route和$router打印出什么内容,通过$route是足以得到当前路由的有的景色音信的,比如路径和参数。

vue-router还有一些钩子函数,通俗讲就是在暴发四遍路由时某个状态的部分回调。大家的项目main.js中使用了:

router.beforeEach(function(){window.scrollTo(0,0);});router.afterEach(function(transition){console.log(transition);});

beforeEach()是在路由切换先河时调用,那里我们将页面重返了上面。

afterEach()是在路由成功切换来激活状态时调用,可以打印出transition看看里面都有哪些。一般在此处可以做像自动导航、自动面包屑的局地大局工作。

router.redirect()很简短,就是重定向了,找不到路由时方可跳转到指定的路由。

小结

跟vue相关的组件化内容大概就是那样多了,说到底,vue的路由也是个零部件,与一般组件并没有别的差别化,只是概念的不比。vue还有一部分学问,比如自定义指令,自定义过滤器,这几个原理也很相近,使用也很简短,大家可以参照项目中的demo,结合文档来学学运用。在下一篇中,将介绍一些开发中沉淀的技艺或行使经验。

网站地图xml地图