设计模式的定义:
在面向对象软件设计过程中针对特定问题的简洁而优雅的解决方案。
通俗说就是在某种场合下对某个问题的一种解决方案
-出自《JavsSctipt设计模式与开发实践》
设计模式(Design pattern)代表了最佳的实践,通常被有经验的面向对象的软件开发人员所采用。设计模式是软件开发人员在软件开发过程中面临的一般问题的解决方案。这些解决方案是众多软件开发人员经过相当长的一段时间的试验和错误总结出来的
为一个对象找一个替代对象,以便对原对象进行访问
代理模式是一种非常有意义的模式,在生活中可以找到很多代理模式的场景。比如,明星都
有经纪人作为代理。如果想请明星来办一场商业演出,只能联系他的经纪人。经纪人会把商业演
出的细节和报酬都谈好之后,再把合同交给明星签。
代理模式的关键是,当应用端不方便直接访问一个对象或者不满足需要的时候,提供一个替身
对象来控制对这个对象的访问,应用端实际上访问的是替身对象。替身对象对请求做出一些处理之
后,再把请求转交给本体对象。
虚拟代理(将开销大的运算延迟到需要时执行)
缓存代理(为开销大的运算结果提供缓存)
保护代理(黑白双簧,代理充当黑脸,拦截非分要求)
防火墙代理(控制网络资源的访问)
远程代理(为一个对象在不同的地址控件提供局部代表)
智能引用代理(访问对象执行一些附加操作)
写时复制代理(延迟对象复制过程,对象需要真正修改时才进行)
代理模式的变体种类非常多,限于其在js中的适用性还有个人的理解,这里只简单介绍一下几个常用的代理
保护代理主要实现了访问主体的限制行为,代理B可以帮助A过滤掉一些请求。
代理对象可预先对请求进行处理,再决定是否转交给本体,代理和本体对外接口保持一致性
比如:
1 | // 主体,发送消息 |
1 | // 例子:代理接听电话,实现拦截黑名单 |
实例:
1 | var myImage = (function(){ |
缓存代理可以为一些开销大的运算结果提供暂时存储,在下次运算时,如果传递进来的参数和之前的一致,则可以直接返回前面存储的结果,而不是重新进行本体运算,减少本体调用次数。
例如,前后端分离,向后端请求分页的数据的时候,每次页码改变时都需要重新请求后端数据,我们可以将页面和对应的结果进行缓存,当请求同一页的时候,就不再请求后端的接口而是从缓存中去取数据。(这种场景也是有要求的,数据不会轻易变更的列表使用)
1 | // 斐波那契数列 |
但是在业务开发时应该注意使用场景,不需要在编写对象时就去预先猜测是否需要使用代理模式,只有当对象的功能变得复杂或者我们需要进行一定的访问限制时,再考虑使用代理。
js中常用的代理模式有虚拟代理和缓存代理两种
注意:面向对象设计的原则——单一职责原则
单一职责原则指的是,就一个类(通常也包括对象和函数等)而言,应该仅有一个引起它变化的原因。如果一个对象承担了多项职责,就意味着这个对象将变得巨大,引起它变化的原因可能会有多个。面向对象设计鼓励将行为分布到细粒度的对象之中,如果一个对象承担的职责过多,等于把这些职责耦合到了一起,这种耦合会导致脆弱和低内聚的设计。当变化发生时,设计可能会遭到意外的破坏。
就是对本体而言,功能要相对单一,便于拓展和代理的维护
定义:
发布 — 订阅模式又叫观察者模式,它定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都将得到通知。
之前通通曾经结合vue源码介绍过该设计模式的一些原理
所以在原理和结构方面不做详细的介绍,对该模式进行扩展的一个介绍
问大家一个问题,用发布订阅模式时,先发布还是先订阅?必须先订阅再发布吗?
我们所了解到的发布订阅模式,都是订阅者先订阅一个消息,随后才能接收到发布者发布的消息。如果把顺序反过来,发布者先发布一条信息,而在之前并没有对象来订阅它,这条消息无疑将会被当作垃圾回收掉。
在某些情况下,我们需要将这条信息保留下来,等到有对象来订阅它的时候,再重新把消息发布给订阅者。就如同QQ中的离线消息一样,离线信息被保存在服务器中,接收人下次登录上线之后,可以重新收到这条信息。
这种需求在实际项目中是存在的,比如在网站中,获取到用户信息之后才能渲染用户信息,而获取用户信息的操作是一个ajax异步请求。当aja请求成功返回之后会发布一个事件,在此之前订阅了此事件的用户导航模块可以接收到这些用户信息
但是这只是理想的状况,因为异步的原因,我们不能保证ajax请求返回的时间,有时候它返 回得比较快,而此时用户信息模块的代码还没有加载好(还没有订阅相应事件),特别是在用了 一些模块化惰性加载的技术后,这是很可能发生的事情。也许我们还需要一个方案,使得我们的 发布—订阅对象拥有先发布后订阅的能力。
为了满足这个需求,我们要建立一个存放离线事件的堆栈,当事件发布的时候,如果此时还
没有订阅者来订阅这个事件,我们暂时把发布事件的动作包裹在一个函数里,这些包装函数将被 存入堆栈中,等到终于有对象来订阅此事件的时候,我们将遍历堆栈并且依次执行这些包装函数, 也就是重新发布里面的事件。当然离线事件的生命周期只有一次,就像QQ的未读消息只会被重新阅读一次,所以刚才的操作我们只能进行一次。
1 |
|
离线功能的问题:
]]>本文首发于个人技术博客 https://liliuzhu.gitee.io/blog
这是很久之前的我们业务组内部的一个分享,一直没有更新发布了。乘此再复习一遍
首先我们需要知道vue-router是什么,它是干什么的?
这里的路由并不是指我们平时所说的硬件路由器,这里的路由就是SPA(单页应用)的路径管理器。 换句话说,vue-router就是WebApp的链接路径管理系统。
路由是根据不同的url地址展示不同的内容或者页面。前端路由就是把不同路由对应不同的内容或者页面的任务交给前端来做,之前是通过服务端根据url的不同返回不同的页面实现的。
vue-router是Vue.js官方的路由插件,它和vue.js是深度集成的,适合用于构建单页面应用。
那与传统的页面跳转有什么区别呢?
在vue-router单页面应用中,则是路径之间的切换,也就是组件的切换。路由模块的本质 就是建立起url和页面之间的映射关系。
随着 ajax 的流行,异步数据请求交互运行在不刷新浏览器的情况下进行。而异步交互体验的更高级版本就是 SPA —— 单页应用。单页应用不仅仅是在页面交互是无刷新的,连页面跳转都是无刷新的,为了实现单页应用,所以就有了前端路由。
至于我们为啥不能用a标签,这是因为用Vue做的都是单页面应用(当你的项目准备打包时,运行 npm run build时,就会生成dist文件夹,这里面只有静态资源和一个index.html页面,在没有后端服务的支持下,浏览器无法找到对应的url路径的),所以你写的标签是不起作用的,你必须使用vue-router来进行管理。
Vue Router 包含的功能有:
不做讲解,都用过无数遍了。看vue-router文档 https://router.vuejs.org/zh/
SPA(single page application):单一页面应用程序,只有一个完整的页面;它在加载页面时,不会加载整个页面,而是只更新某个指定的容器中内容。
vue-router 使用 path-to-regexp 作为路径匹配引擎,用来匹配path和params
单页面应用(SPA)的核心之一是:
vue-router 默认 hash 模式 —— 使用 URL 的 hash 来模拟一个完整的 URL,于是当 URL 改变时,页面不会重新加载。hash(#)是URL 的锚点,代表的是网页中的一个位置,单单改变#后的部分,浏览器只会滚动到相应位置,不会重新加载网页,也就是说hash 出现在 URL 中,但不会被包含在 http 请求中,对后端完全没有影响,因此改变 hash 不会重新加载页面;同时每一次改变#后的部分,都会在浏览器的访问历史中增加一个记录,使用”后退”按钮,就可以回到上一个位置;所以说Hash模式通过锚点值的改变,根据不同的值,渲染指定DOM位置的不同数据。hash 模式的原理是 onhashchange 事件(监测hash值变化),可以在 window 对象上监听这个事件。
在 2014 年之前,大家是通过 hash 来实现路由,url hash 就是类似于:
1 | http://www.renrenche.com/ |
后来,因HTML5的发布,又出现了一个onpopstate事件,其可以代替onhashchange使用
1 | window.addEventListener( |
由于hash模式会在url中自带#,如果不想要很丑的hash,我们可以用vue-router的 history 模式。
14年后,因为HTML5标准发布。html5 history interface 中新增的了 pushState() 和 replaceState()方法这两个方法应用于浏览器记录栈,在当前已有的 back、forward、go基础之上,它们提供了对历史记录修改的功能。只是当它们执行修改时,虽然改变了当前的URL,但浏览器不会立即向后端发送请求。同时还有popstate事件。通过这些就能用另一种方式来实现前端路由了,但原理都是跟hash实现相同的。
当你使用 history 模式时,URL就像正常的url,单页路由的url就不会多出一个#,例如 http://shanyishanmei.com/user/id 变得更加美观!但因为没有#号,所以当用户刷新页面之类的操作时,浏览器还是会给服务器发送请求。为了避免出现这种情况,所以这个实现需要服务器的支持,需要把所有路由都重定向到根页面。因为我们的应用是个单页客户端应用,如果后台没有正确的配置,当用户在浏览器直接访问http://shanyishanmei.com/user/id2就会返回404,这就不对了。所以呢,你要在服务端增加一个覆盖所有情况的候选资源:如果 URL 匹配不到任何静态资源,则应该返回同一个index.html页面,这个页面就是你 app 依赖的页面。
1 | window.addEventListener('popstate', e => { |
通过一个数组和一个数字变量来模拟浏览器的history的。支持所有 JavaScript 运行环境,如 Node.js 服务器端。如果发现没有浏览器的 API,路由会自动强制进入这个模式
1 | constructor (router: Router, base: ?string) { |
当活动历史记录条目更改时,将触发popstate事件。如果被激活的历史记录条目是通过对history.pushState()的调用创建的,或者受到对history.replaceState()的调用的影响,popstate事件的state属性包含历史条目的状态对象的副本。
需要注意的是调用history.pushState()或history.replaceState()不会触发popstate事件。只有在做出浏览器动作时,才会触发该事件,如用户点击浏览器的回退按钮(或者在Javascript代码中调用history.back())
不同的浏览器在加载页面时处理popstate事件的形式存在差异。页面加载时Chrome和Safari通常会触发(emit )popstate事件,但Firefox则不会
根据popstate介绍以及从vue-router源码,当我们手动改变url的hash的时候或者window.location.hash = ‘xxx’,history.go(-1), history.back(),history.forward() 的时候才会触发onpopstate或者onhashchange事件,进而运行回调transitionTo方法。而window.history.replaceState和window.history.pushState,仅会改变历史记录条目,无法触发onpopstate,所以目前hash和history模式下,$router的push,replace方法都是直接调用transitionTo方法来更新视图而后再用history.replaceState和history.pushState改变;历史记录和url
1 | Vue.mixin({ |
1 | Object.defineProperty(Vue.prototype, '$router', { |
相比
1 | push,replace,go,back,forward, addRoutes等 |
全局路由守卫
1 | beforeEach,beforeResolve,afterEach |
1 | let mode = options.mode || 'hash' |
1 | 1.导航被触发。 |
1 | // confirmTransition 的成功回调 |
总体流程图
优点:
缺点:
confirmTransition 这个高阶函数一层套一层,绕不过来具体看源码’src/history/base.js’
异步组件的加载原理
]]>本文首发于个人技术博客 https://liliuzhu.gitee.io/blog
Babel是一个广泛使用的转码器,可以将ES6代码转为ES5代码,从而可以在现有环境执行,所以我们可以用ES6编写,而不用考虑环境支持的问题。
Babel 默认只转换新的 JavaScript 句法(syntax),而不转换新的 API ,比如 Iterator、Generator、Set、Maps、Proxy、Reflect、Symbol、Promise 等全局对象,以及一些定义在全局对象上的方法(比如 Object.assign)都不会转码。Babel 默认不转码的 API 非常多,详细清单可以查看babel-plugin-transform-runtime模块的definitions.js文件。
有些浏览器版本的发布早于ES6的定稿和发布,因此如果在编程中使用了ES6的新特性,而浏览器没有更新版本,或者新版本中没有对ES6的特性进行兼容,那么浏览器就会无法识别ES6代码,例如IE9根本看不懂代码写的let和const是什么东西?只能选择报错,这就是浏览器对ES6的兼容性问题;
为了完整使用 ES6 的 API ,我们可以使用 babel-polyfill 这个插件:
1 | $ npm install -save-dev babel-polyfill |
或
1 | npm install --save @babel/polyfill |
然后,在需要使用的文件的顶部引入
1 | import "babel-polyfill" |
或
1 | import "@babel/polyfill"; |
node.js 中:
1 | require('babel-polyfill'); |
或
1 | require("@babel/polyfill"); |
webpack.config.js 中:
1 | module.exports = { |
或
1 | module.exports = { |
]]>本文首发于个人技术博客 https://liliuzhu.gitee.io/blog
在正式介绍WebSocket之前先跟大家科普一下以及讨论一下过去是如何实现Web双向通信的
HTTP 协议有一个缺陷:通信只能由客户端发起。举例来说,我们想了解今天的天气,只能是客户端向服务器发出请求,服务器返回查询结果。HTTP 协议做不到服务器主动向客户端推送信息。这种单向请求的特点,注定了如果服务器有连续的状态变化,客户端要获知就非常麻烦。 在WebSocket协议之前,有三种实现双向通信的方式:轮询(polling)、长轮询(long-polling)和iframe流(streaming)。
轮询是客户端和服务器之间会一直进行连接,每隔一段时间就询问一次。其缺点也很明显:连接数会很多,一个接受,一个发送。而且 每次发送请求都会有Http的Header,会很耗流量,也会消耗CPU的利用率 。
实例
1.index.html
1 | <!--index.html--> |
2.server.js
1 | // server.js |
3.效果图
长轮询是对轮询的改进版,客户端发送HTTP给服务器之后,看有没有新消息,如果没有新消息,就一直等待。当有新消息的时候,才会返回给客户端。在某种程度上减小了网络带宽和CPU利用率等问题。由于http数据包的头部数据量往往很大(通常有400多个字节),但是真正被服务器需要的数据却很少(有时只有10个字节左右),这样的数据包在网络上周期性的传输,难免 对网络带宽是一种浪费 。
实例
1.index.html
1 | <!--index.html--> |
2.server.js
1 | // server.js |
3.效果图
iframe流方式是在页面中插入一个隐藏的iframe,利用其src属性在服务器和客户端之间创建一条长连接,服务器向iframe传输数据(通常是HTML,内有负责插入信息的javascript),来实时更新页面。
实例
1.index.html
1 | <!--index.html--> |
2.server.js
1 | // server.js |
3.效果图
EventSource的官方名称应该是Server-sent events (SSE)服务端派发事件,EventSource 基于http协议只是简单的单项通信,实现了服务端推的过程客户端无法通过EventSource向服务端发送数据。虽然不能实现双向通信但是在功能设计上他也有一些优点比如可以自动重连接,event-IDs,以及发送随机事件的能力(WebSocket要借助第三方库比如socket.io可以实现重连。)
实例
1.index.html
1 | <!--index.html--> |
2.server.js
1 | // server.js |
3.效果图
有什么用:
因为受单项通信的限制EventSource非常适应于后端数据更新频繁且对实时性要求较高而又不需要客户端向服务端通信的场景下。比如来实现像股票报价、新闻推送、实时天气这些只需要服务器发送消息给客户端场景中。EventSource的使用更加便捷这也是他的优点。
EventSource的应用,webpack-hot-middleware原理
EventSource实例的readyState属性,表明连接的当前状态。该属性只读,可以取以下值。
注意:
在页面中内嵌入一个使用了Socket类的Flash程序JavaScript通过调用此Flash程序提供的Socket接口与服务器端的Socket接口进行通信,JavaScript在收到服务器端传送的信息后控制页面的显示。
==Flash 不懂也不说太多了,再多说都是瞎编了==
以上demo源码地址:https://github.com/liliuzhu/personalShareDemo/tree/master/WebSocket/polling
WebSocket是HTML5开始提供的一种在单个TCP连接上进行全双工通讯的协议。
WebSocket使得客户端和服务器之间的数据交换变得更加简单,允许服务端主动向客户端推送数据。在WebSocket API中,浏览器和服务器只需要完成一次握手,两者之间就直接可以创建持久性的连接,并进行双向数据传输。
在WebSocket API中,浏览器和服务器只需要做一个握手的动作,然后,浏览器和服务器之间就形成了一条快速通道。两者之间就直接可以数据互相传送。
HTML5 定义的 WebSocket协议,能更好的节省服务器资源和带宽,并且能够更实时地进行通讯;解决了轮询以及其他长连接的很多缺点。
1 | // WebSocket的客户端原生api |
Socket.readyState 表示连接状态,可以是以下值
注意:
Websocket 使用ws或wss的统一资源标志符,类似于HTTPS,其中wss表示在TLS之上的Websocket
Websocket 使用和HTTP相同的TCP端口,可以绕过大多数防火墙的限制。默认情况下,Websocket 协议使用 80 端口;运行在 TLS 之上时,默认使用 443 端口。
虽然 WebSocketServer 可以使用别的端口,但是统一端口还是更优的选择
1 | // 服务器数据可能是文本,也可能是二进制数据(blob对象或Arraybuffer对象)。 |
EventSource和WebSocket一样都是HTML5中的新技术,不过两者在定位上有很大的差别。
WebSocket 协议本质上是一个基于 TCP 的协议。
为了建立一个 WebSocket连接,客户端浏览器首先要向服务器发起一个HTTP请求,这个请求和通常的HTTP请求不同,包含了一些附加头信息,其中附加头信息”Upgrade:WebSocket”表明这是一个申请协议升级的 HTTP 请求,服务器端解析这些附加的头信息然后产生应答信息返回给客户端,客户端和服务器端的 WebSocket 连接就建立起来了,双方就可以通过这个连接通道自由的传递信息,并且这个连接会持续存在直到客户端或者服务器端的某一方主动的关闭连接。
Websocket 其实是一个新协议,跟HTTP协议基本没有关系,只是为了兼容现有浏览器的握手规范而已,也就是说它是 HTTP 协议上的一种补充。
废话不说上案例
以上demo源码地址: https://github.com/liliuzhu/personalShareDemo/tree/master/WebSocket/webSocket
方式 | 类型 | 技术实现 | 优点 | 缺点 | 适用场景 | |
---|---|---|---|---|---|---|
轮询Polling | client⇌server | 客户端循环请求 | 1、实现简单 2、 支持跨域 | 1、浪费带宽和服务器资源 2、 一次请求信息大半是无用(完整http头信息) 3、有延迟 4、大部分无效请求 | 适于小型应用 | |
长轮询Long-Polling | client⇌server | 服务器hold住连接,一直到有数据或者超时才返回,减少重复请求次数 | 1、实现简单 2、不会频繁发请求 3、节省流量 4、延迟低 | 1、服务器hold住连接,会消耗资源 2、一次请求信息大半是无用 | WebQQ、Hi网页版、Facebook IM | |
长连接iframe | server⇌client | 在页面里嵌入一个隐蔵iframe,将这个 iframe 的 src 属性设为对一个长连接的请求,服务器端就能源源不断地往客户端输入数据。 | 1、数据实时送达 2、不发无用请求,一次链接,多次“推送” | 1、服务器增加开销 2、无法准确知道连接状态 3、IE、chrome等一直会处于loading状态 | Gmail聊天 | |
EventSource | server→client | new EventSource() | 1、基于现有http协议,实现简单2、断开后自动重联,并可设置重联超时3、派发任意事件4、跨域并有相应的安全过滤 | 1、只能单向通信,服务器端向客户端推送事件2、事件流协议只能传输UTF-8数据,不支持二进制流。4、兼容性不高,IE 和 Edge下目前所有不支持EventSource服务器端需要保持 HTTP 连接,消耗一定的资源 | 股票报价、新闻推送、实时天气 | |
WebSocket | server⇌client | new WebSocket() | 1、支持双向通信,实时性更强 2、可发送二进制文件3、减少通信量 | 1、浏览器支持程度不一致 2、不支持断开重连 | 网络游戏、银行交互和支付 |
综上所述:Websocket协议不仅解决了HTTP协议中服务端的被动性,即通信只能由客户端发起,也解决了数据同步有延迟的问题,同时还带来了明显的性能优势,所以websocket是Web 实时推送技术的比较理想的方案,但如果要兼容低版本浏览器,可以考虑用轮询来实现。
npm上有很多包对websocket做了实现比如 socket.io、WebSocket-Node、ws、nodejs-websocket还有很多
Socket.io:
Socket.io是一个WebSocket库,包括了客户端的js和服务器端的nodejs,它会自动根据浏览器从WebSocket、AJAX长轮询、Iframe流等等各种方式中选择最佳的方式来实现网络实时应用(不支持WebSocket的情况会降级到AJAX轮询),非常方便和人性化,兼容性非常好,支持的浏览器最低达IE5.5。屏蔽了细节差异和兼容性问题,实现了跨浏览器/跨设备进行双向数据通信。
ws:
不像 socket.io 模块,ws是一个单纯的websocket模块,不提供向上兼容,不需要在客户端挂额外的js文件。在客户端不需要使用二次封装的api使用浏览器的原生Websocket API即可通信。
]]>本文首发于个人技术博客 https://liliuzhu.gitee.io/blog
先看一下各个算法的时间复杂度和空间复杂度
说明:
时间复杂度:指的是一个算法执行所耗费的时间
空间复杂度指:运行完一个程序所需内存的大小
稳定指:如果a=b,a在b的前面,排序后a仍然在b的前面
不稳定指:如果a=b,a在b的前面,排序后可能会交换位置
下面主要通过文字和动图介绍冒泡排序、选择排序、快速排序和插入排序这些经典的排序算法,并用js代码实现
冒泡排序可谓是最经典的排序算法了,它是基于比较的排序算法,其优点是实现简单,排序数量较小时性能较好。
它重复地走访过要排序的数列,一次比较两个元素,如果它们的顺序错误就把它们交换过来。走访数列的工作是重复地进行直到没有再需要交换,也就是说该数列已经排序完成。这个算法的名字由来是因为越小的元素会经由交换慢慢“浮”到数列的顶端。
相邻的数据进行两两比较,小数放在前面,大数放在后面,如果前面的数据比后面的数据大,就交换这两个数的位置。也可以实现大数放在前面,小数放在后面,如果前面的数据比后面的小,就交换两个的位置。要实现上述规则需要用到两层for循环。
1 | function bubbleSort(arr) { |
冒泡排序算法优化
1 | function bubbleSort(arr) { |
表现最稳定的排序算法之一,因为无论什么数据进去都是O(n²)的时间复杂度。。。所以用到它的时候,数据规模越小越好。唯一的好处可能就是不占用额外的内存空间了吧。
先在未排序序列中找到最小(大)元素,存放到排序序列的起始位置,然后,再从剩余未排序元素中继续寻找最小(大)元素,然后放到已排序序列的末尾。以此类推,直到所有元素均排序完毕。
n个记录的直接选择排序可经过n-1趟直接选择排序得到有序结果。具体算法描述如下:
1 | function selectionSort(arr) { |
插入排序(Insertion-Sort)的算法描述是一种简单直观的排序算法。
它的工作原理是通过构建有序序列,对于未排序数据,在已排序序列中从后向前扫描,找到相应位置并插入。插入排序在实现上,通常采用in-place排序(即只需用到O(1)的额外空间的排序),因而在从后向前扫描过程中,需要反复把已排序元素逐步向后挪位,为最新元素提供插入空间。
一般来说,插入排序都采用in-place在数组上实现。具体算法描述如下:
1 | function insertSort(arr) { |
快速排序是由东尼·霍尔所发展的一种排序算法。在平均状况下,排序 n 个项目要 Ο(nlogn) 次比较。在最坏状况下则需要 Ο(n2) 次比较,但这种状况并不常见。事实上,快速排序通常明显比其他 Ο(nlogn) 算法更快,因为它的内部循环(inner loop)可以在大部分的架构上很有效率地被实现出来。
快速排序又是一种分而治之思想在排序算法上的典型应用。本质上来看,快速排序应该算是在冒泡排序基础上的递归分治法。
1 | function quickSort(arr){ |
]]>本文首发于个人技术博客 https://liliuzhu.gitee.io/blog
- 原文作者:cherry
- 原文地址:【基础】利用 hexo + Gitpage 开发自己的博客
进入程序员这个坑之后就开始自己在网上扒资料,然而资料太多,情况太复杂,主要是看见别人的博客,感觉好高大上,并且感觉在茫茫的互联网有自己的小天地感觉也是极好的。不是为了给别人看,而是为了 记录自己的成长,记录自己的每一个脚印。
想要实现拥有一个独立的私有博客,我们需要两个东西,一个是可供浏览器访问的静态网页存储空间,这个我们选择gitPage,一个是一个静态网页生成工具,Octopress也好,Hexo也罢,这里我选择的是Hexo。
到Node.js官网下载相应平台的最新版本,一路安装即可。我用的是node-v0.10.22-x86.msi
安装git,或安装github客户端,自我感觉github客户端很好用,界面很友好,同样操作起来也比git好用的多!我用的是window10系统,在官网下载数次都未安装成功,最后在知乎上终于找到安装包,链接: http://pan.baidu.com/s/1eS2mHxS 密码: yatq ,有需要的同学可以点击下载。
使用git shell,依次输入以下代码命令:
1 | cd / |
命令解释:
cd和/之间要有空格,这条指令的作用是返回根目录,也可以在cd /后加入一个文件名,例如下文要用到的cd /Hexo 就可以指向这个文件夹,再输入代码行就默认在在此文件下执行。
1 | cd / |
命令解释:
cd /这里返回的根目录取决于你在github客户端的设置,我设置的是F盘,所以返回得也是F盘,所以下面创建的Hexo文件夹也在F盘。
Hexo这个文件名可以随便命名,存放的是构建博客所要用到的所有文件。
指向Hexo目录
安装依赖文件
编译
开启本地服务(第5、6步的操作可以合并成hexo s -g)
此时打开浏览器,在地址栏输入http://localhost:4000/
即可查看博客的原型,是不是看到了胜利的曙光;但是如果“显示无法访问此网站”也不要沮丧,我这步是直接看到页面的,你无法访问的原因可能你没有翻墙,因为页面中默认使用了ajax.google.com 下的js包。
那么如何翻墙呢? 下面提供我所知道的两种方法:
这种方法比较简单,下载安装运行Lantern,可以官网下载的吧!这里提供一下安装包吧,链接: http://pan.baidu.com/s/1c2x7eRu
密码: z3kw
这种方法需要修改hosts文件,我的 hosts 文件路径:C:\Windows\System32\drivers\etc ,详细攻略:http://blog.my-eclipse.cn/host-google.html
如果你不想翻墙,可以采用这种方法:
进入你刚新建好的 blog根目录
1 | themes/landscape/layout/_partial |
1,找到 after-footer.ejs把
1 | <script src="http://cdn.bootcss.com/jquery/2.1.1/jquery.min.js“ > </script> |
替换成
<script src="http://cdn.bootcss.com/jquery/2.1.1/jquery.min.js“ > </script>
2,找到 header.ejs
注释掉或者删掉 下面这句css引用<link href="//fonts.googleapis.com/css?family=Source+Code+Pro" rel=”stylesheet” type=”text/css”>
hexo server 之后。访问 http://localhost:4000 就会看到blog主页了。
如果你成功在http://localhost:4000/
下看到了博客原型,那么再进行一些简单的操作之后就可以马上拥有自己的博客了,是不是很激动!
行百里者半九十
不到成功的那一刻,一切欣喜若狂都是不值得的!如果你已经迫不及待,我们继续:
也就是把博客部署到github page提供的服务器上。
步骤
deploy: type: github repo: https://github.com/yourname/blog.git
继续回到git shell输入命令:
1 | hexo clean |
命令解释:
千辛万苦建立了博客,那么我们来学习一下如何发表博文。
继续回到git shell输入:
hexo new “新博文的名字”
即可在 Hexo\source_posts 目录中找到”新博文的名字.md”这个文件。你就可以使用maekdown编辑器打开进行编写博客内容了。
Markdown编辑器
推荐两款我所使用的markdown编辑器:
MIU,据说是仿mac版的mou,界面相当友好,非常喜欢,官网都下载不了,挺小众,可能我就是典型的少说派,我也是偶然间得到,在此提供下载地址:
链接: http://pan.baidu.com/s/1slMPeTR
密码: 2pnk
正在使用的Atom:更为先进的文本代码编辑器 ,由 Github 打造的下一代编程开发神器,其中支持markdown。
可能会遇到的问题
hexo new [layout] “postName” #新建文章
其中layout是可选参数,默认值为post。有哪些layout呢,请到scaffolds目录下查看,这些文件名称就是layout名称。当然你可以添加自己的layout,方法就是添加一个文件即可,同时你也可以编辑现有的layout,比如post的layout默认是hexo\scaffolds\post.md
1 | title: { { title } } |
大括号与大括号之间我多加了个空格,否则会被转义,不能正常显示。
我想添加categories,以免每次手工输入,只需要修改这个文件添加一行
1 | title: { { title } } |
postName是md文件的名字,同时也出现在你文章的URL中,postName如果包含空格,必须用”将其包围,postName可以为中文。
注意,所有文件:后面都必须有个空格,不然会报错。
看一下刚才生成的文件hexo\source_posts\postName.md
1 | title: postName #文章页面上的显示名称,可以任意修改,不会出现在URL中 |
始使用markdown格式输入你的正文。,你就可以用喜爱的编辑器尽情书写你的文章。关于markdown语法,可以参考我的文章Markdown简明语法。
fancybox
可能有人对这个Reading页面中图片的fancybox效果感兴趣,这个是怎么做的呢。
很简单,只需要在你的文章*.md文件的头上添加photos项即可,然后一行行添加你要展示的照片:
1 | layout: photo |
经过测试,文件头上的layout: photo可以省略。
不想每次都手动添加怎么办?同样的,打开您的hexo\scaffolds\photo.md
1 | layout: { { layout } } |
然后每次可以执行带layout的new命令生成照片文章:
1 | hexo new photo "photoPostName" |
description
markdown文件头中也可以添加description,以覆盖全局配置文件中的description内容,请参考下文_config.yml的介绍。
1 | title: hexo你的博客 |
hexo默认会处理全部markdown和html文件,如果不想让hexo处理你的文件,可以在文件头中加入layout: false。
文章摘要
在需要显示摘要的地方添加如下代码即可:
1 | 以上是摘要 |
more以上内容即是文章摘要,在主页显示,more以下内容点击『> Read More』链接打开全文才显示。
hexo中所有文件的编码格式均是UTF-8。
看到很多博客上说使用七牛,但是这种方法可能是用着最爽的,我们来看一下如何使用:
首先确认 _config.yml 中更改 post_asset_folder:true 。
回到git shell,输入
npm install https://github.com/CodeFalling/hexo-asset-image –save
继续执行
1 | hexo clean |
重新创建一个博客名字,然后发现Hexo\source_posts下多了一个与博客名字相同的空文件夹
然后就可以把我们博客中要用到的图片存放在这个文件夹下,需要时直接引用即可,是不是特别方便?
提醒:
写一篇博文时尽量只使用一种markdown编辑器,如果同时使用两个编辑器,我感觉不同编辑器对markdown语法的编译还是有一些差别的,用这个编辑器写好的格式用另一个编辑器打开却乱了!
继续重复以下命令即可实现预览和发表,恭喜你已经在自己建设的博客网站上发表了第一篇博文!
1 | 1. hexo clean |
更高大上的发表博文的方法
使用Travis CI自动部署你的Hexo博客到Github,请参考手把手教你使用Travis CI自动部署你的Hexo博客到Github上
使用could9在线更新博客,这样的话即使更换了电脑,也能优雅的更新博客了。详细请参考:用c9.io实现在线更新博客
如果你跟我一样觉得原始的博客主题很low,想更换一个高逼格的,那我们继续往下进行:
选择主题
你可以在Themes·Hexo上选择你喜欢的主题,我使用的Next主题
参考Next官方文档,内容十分详尽!
安装主题的方法就是一句git命令:
1 | git clone https://github.com/heroicyang/hexo-theme-modernist.git themes/modernist |
目录是否是modernist无所谓,只要与_config.yml文件一致即可。
安装完成后,打开hexo_config.yml,修改主题为modernist
1 | theme: modernist |
打开hexo\themes\modernist目录,编辑主题配置文件_config.yml:
1 | menu: #配置页头显示哪些菜单 |
更新主题
1 | cd themes/modernist |
静态博客要使用第三方评论系统,hexo默认集成的是Disqus,因为你懂的,所以国内的话还是建议用多说
直接用你的微博/豆瓣/人人/百度/开心网帐号登录多说,做一下基本设置。如果使用modernist主题,在modernist_config.yml中配置duoshuo_shortname为多说的基本设置->域名中的shortname即可。你也可以在多说后台自定义一下多说评论框的格式,比如评论框的位置,对于css设置,可以参考这里,我是在HeroicYang的基础上修改的。
如果你是有的其他第三方评论系统,将通用代码粘贴到hexo\themes\modernist\layout_partial\comment.ejs里面,如下:
1 | <% if (config.disqus_shortname && page.comments){ %> |
那些小图标都是一个新页面,需要手动创建,那么如何创建?
回到git shell,
hexo new page “页面名称”
比如你要创建一个about页面,就输入hexo new page “about”
正确显示各页面内容
发表博文后发现点击上面建立的页面后发现是空白页,比如,打开标签页面,发现是空白,或者提示找不到!
解决方法:以标签页为例,打开Hexo\source\tags下index.md文件,修改如下:
comments: false即关闭此页面的评论功能
type: “tags”这里的值根据你想更改的页面决定
更改过后,在重新部署到github上,你就可以点击各个页面查看,发现一切都是那么美好!
hexo支持的插件:Plugins | Hexo
想安装什么插件,按照相关README.md中介绍操作即可。
安装多说评论、不蒜子(或LeanCloud)和分享插件,参考:第三方服务集成,介绍非常全面!好好用来装饰你的博客吧!
安装sitemap和feed插件时,如果遇到问题,可以参考:博客搬迁记 - 从WordPress到Hexo,安装sitemap后要到百度站长提交你的网站,首先要添加站点,然后在链接提交你的sitemap.xml,详细操作参考:为Hexo博客生成sitemap
安装swiftype插件,如果遇到问题,可以参考利用swiftype为hexo添加站内搜索
考虑到博客的速度,同时也为了便于博客的迁移,图床是必须的。我墙裂推荐七牛,访问速度极快,支持日志、防盗链和水印。
免费用户有每月10GB流量+总空间10GB+PUT/DELETE 10万次请求+GET 100万次请求,这对个人博客来说足够,有一点要说明的是,七牛没有目录的概念,但是文件名可以包含/,比如2013/11/27/reading/photos-0.jpg,参考这里关于key-value存储系统。
七牛除了作为图床还可以作为其他静态文件存储空间,比如我的个人站点首页有个字库文件和JS文件下载较慢,有时间会把它弄到七牛上去,以提高首页打开速度。请看这篇Linux中国采用七牛云存储支撑图片访问。
如果非要说不足的话,就是文件管理界面不是很友好,不支持CNAME到分配的永久链接,也不能绑定未备案的自有域名,必须备案才可以。
如果你对七牛web版的文件管理界面不满意,可以用官方的七牛云存储工具。
您还可以使用如下图床服务 FarBox,Dropbox,又拍云
Next主题很美观,个人也非常喜欢,但是一点令我们烦恼的就是主题加载的特别缓慢,那怎么优化呢?请参考一下两篇博文,作者已经总结的非常详细了,有需要的可以拜读一下,受益匪浅!
购买域名,我是在万网购买的,可以申请到国际域名,免去了备案的繁杂过程,我居然申请了两个,由于自学前端,所以就构建了一个网站来展示自己写的一些demo,【至于如何快速的构建一个网站,从购买域名,云空间到上传文件,你可以试一下这个网站,但是现在可以用github page做服务器,也可以构建多个项目主页来展现demo,是我马上要研究的方向,自己上传云服务器感觉步骤好繁琐,看一下在github建立项目主页能否得到改善!】还一个正好闲置着,所以就拿来解析到github page上,以后就可以通过自己的域名访问自己的博客了!
如何操作:在 Hexo\source 文件夹里新建一个名为 CNAME 的文件,用文本编辑器打开,添加内容 yourwebsite.com (你的个人域名 )。保存后,部署你的博客即可。如果这步遇到问题,也可手动在万网上解析,github page提供的IP:
192.30.252.153
192.30.252.154
favicon.ico一般用于作为缩略图的网站标志,在线制作网站
关于是否绑定域名
经过这几天的试用,关于是否绑定域名,发表一下自己的看法,如果你仅仅是使用个人主页来托管个人博客。绑定与否看你自己的想法,如果你还想使用github的项目主页来展示平时写的一些小练习demo,那我劝你不要绑定个人域名了,关于如何使用github的项目主页,请参考单个GitHub帐号下添加多个GitHub Pages的相关问题,这样你就可以直接在需要展示的项目下添加gh-pages分支,然后通过访问“用户名。github.io/项目名/*.html”来查看页面展示效果了。这多方便,不用自己在上传云空间了,省去了一堆麻烦事!
#至此,基本操作介绍完毕,以下内容普通用户无需了解。
默认目录结构:
1 | . |
接下来是重头戏_config.yml,做个简单说明:
1 | # Hexo Configuration |
页面展现的全部逻辑都在每个主题中控制,源代码在hexo\themes\你使用的主题\中,以modernist主题为例:
1 | . |
如果你需要修改头部,直接修改hexo\themes\modernist\layout_partial\header.ejs,比如头上加个搜索框:
1 | <div> |
将如上代码加入即可,您需要修改css以便这个搜索框比较美观。
再如,你要修改页脚版权信息,直接编辑hexo\themes\modernist\layout_partial\footer.ejs。同理,你需要修改css,直接去修改对应位置的styl文件。
页面上显示访问次数可以使用 不蒜子,两行代码即可搞定。
因Google Analytics偶尔被墙,故用百度统计,以modernist主题为例,介绍如何添加。
编辑文件hexo\themes\modernist_config.yml,增加配置选项:
1 | baidu_tongji: true |
新建文件hexo\themes\modernist\layout_partial\baidu_tongji.ejs,内容如下:
1 | <% if (theme.baidu_tongji){ %> |
注册并登录百度统计获取你的统计代码。
编辑文件hexo\themes\modernist\layout_partial\head.ejs,在『/head』之前增加:
1 | <('baidu_tongji') > - partial |
重新生成并部署你的站点。
不出意外的话,在你的站点的每个页面的左上角都会看到一个恶心的百度LOGO。你只能在『百度统计首页->网站列表->获取代码->系统管理设置->统计图标设置->显示图标』,把那个勾去掉。百度真是恶心,我准备还是用Google Analytics。
我没有添加分享,觉得这个不是很必要,导致页面看起来啰嗦。以加网为例介绍如何添加:
网站图标
看一下hexo\themes\modernist\layout_partial\head.ejs,找到这句:
1 | <link rel="icon" type="image/x-icon" href="<%- config.root %>favicon.ico"> |
你懂的,将你的favicon.ico放到工程根目录下即可,也就是hexo\source目录。可以在Faviconer制作你的ico图标,国内有比特虫。
除了默认已提供的挂件外,你还可以自定义自己的小挂件,在hexo\themes\modernist\layout_widget\下,新建自己的ejs文件,如myWidget.ejs,然后在配置文件hexo\themes\modernist_config.yml中配置。
1 | widgets: |
用上述方法可以添加新浪微博小挂件。
安装插件:
1 | npm install <plugin-name> --save |
启用插件:在*hexo_config.yml文件添加:
1 | plugins: |
升级插件:
1 | npm update |
卸载插件:
1 | npm uninstall <plugin-name> |
RSS插件
将上述命令中的『plugin-name』,替换为hexo-generator-feed。一旦安装完成,你可以在配置显示你站点的RSS,文件路径\atom.xml。
你可以用rss作为迁移工具,用如下命令读取其他位置的rss:
1 | hexo migrate rss <source> |
『source』是本地或网络文件路径。
Sitemap插件
将上述命令中的『plugin-name』,替换为hexo-generator-sitemap。你可以将你站点地图提交给搜索引擎,文件路径\sitemap.xml。
更多插件的安装方法,请参考官方Wiki。
如果你按照上述步骤做,但插件不起作用,没有生成atom.xml和sitemap.xml,也没有报错,那么你应该cd到你的hexo初始化目录,在该目录下重新安装插件,重试。
hexo支持从其他类型站点迁移,如通用RSS,Jekyll,Octopress,WordPress等,这一部分我没试过。请参考官方文档Hexo Migration。
你可以到屈站长提交你的站点给搜索引擎。其他内容如添加站点或页面的description,提交Sitemap,添加百度统计,Google Analytics等等,参考本文其他章节的内容,不再一一阐述。
更新hexo:
1 | npm update -g hexo |
更新主题:
1 | cd themes/你的主题 |
更新插件:
1 | npm update |
干掉IE
Kill IE6 提示的javascript代码,请自行搜索。
你要保留好自己的博客源码。换机器写博客,就只能使用各种网盘的同步功能,或者你把你的站点源文件提交到某代码托管服务器。另外,貌似这篇很牛逼,Hexo 服务器端布署及 Dropbox 同步。
我的办法是这样的,先在一个目录下做好Node+Git+Hexo的绿色环境,写个hexos.bat可以一键启动hexo工作台,把整个目录用Dropbox同步,这样随便在办公室或家的任何笔记本台式机都可以写博客,也不用处理什么文件拷贝备份的事情,非常爽。
为hexo博客添加访问次数统计功能
其它
网站加速
Webluker-FAQ索引
网站监控
]]>本文首发于个人技术博客 https://liliuzhu.gitee.io/blog
这是本人,第一次写博客,文采不好,技术也菜鸟,请不要见怪。
前一段时间裸辞了,于是开始广投简历。可是现实是非常的残酷,年底了面试的通知很少。想着是不是自己的简历上干货太少了,不如把自己之前做的项目连接放在简历上。
可是可是。。。,现实又很残酷。我们做的项目大多是企业内部系统,只能通过内网来访问。更为严重的是我们的主管是不会告诉我们客户的正式服务器的。出来面试,连作品连接都没有,都不好意思说自己是做web前端的[尴尬]。
那怎么办呢?没有作品链接,简历被淘汰的概率也会大好多,后来想起来可以用自己的电脑搭建一台服务器,说干就干。
后来找到了一些免费的第三方工具并且都一一实验了一下,有些成功了,有些也失败了。
但是可能是我的网络环境的问题,实际用的时候却是这样的
结果第一个内网映射工具,使用失败。
附上官网地址http://www.ittun.com/
也是网上找的,是基于Node.js的一个模块,说是可以将内网服务器暴露至公网。基于node.js,倒很适合我的胃口。结果也试几次还是失败。也可能是我用的方法还不对,继续寻找。
终于这个是可以用的了,试了几次除了速度慢一些,还都好用,不过需要这个工具需要在官网上申请免费的key,而且一个帐号只能申请一个免费的key,可以指定二级域名。不过后来测试的时候还是发现了一个问题,就是在客户端上传文件的JNat会出现错误,而且文件上传失败.希望以后能够得到解决。
在此附上JNat官网地址http://www.j2eeall.com
这个工具也是比较好用的,不过也需要去官网注册,而且还要实名认证,还是比较麻烦的。一个注册用户可免费拥有2条不同协议的隧道。
客户端上传文件时也没有问题。不过这个工具也有不好的地方,就是免费版不能自定义二级域名。过一段时间不用,再去重新开启映射就会随机更新一个二级域名,这点比较坑,要是在app中应用岂不也是每次更新了二级域名,都要重新打包不可。
不过,这已经不错了,毕竟人家是免费的[呲牙]!附上官方网址https://natapp.cn
这是最近才发现的一个内网穿透工具,好像还挺好用,官网讨论群也比较多。官网上介绍的也比较详细。官网上说其具有以下几方面优点:
然而对于我来收说比较的可悲,和ittun一样都存在着一样的问题—无法连接
应该和ittun想同的原因,也不知道该怎么破,还在的等待技术群的回复。附上官网链接https://www.ngrok.cc/
]]>本文首发于个人技术博客 https://liliuzhu.gitee.io/blog
Welcome to Hexo! This is your very first post. Check documentation for more info. If you get any problems when using Hexo, you can find the answer in troubleshooting or you can ask me on GitHub.
1 | $ hexo new "My New Post" |
More info: Writing
1 | $ hexo server |
More info: Server
1 | $ hexo generate |
More info: Generating
1 | $ hexo deploy |
More info: Deployment
]]>