-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathatom.xml
More file actions
99 lines (63 loc) · 37.5 KB
/
atom.xml
File metadata and controls
99 lines (63 loc) · 37.5 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
<title>Live long and prosper</title>
<link href="/atom.xml" rel="self"/>
<link href="http://yoursite.com/"/>
<updated>2019-05-27T10:46:03.284Z</updated>
<id>http://yoursite.com/</id>
<author>
<name>Lance</name>
</author>
<generator uri="http://hexo.io/">Hexo</generator>
<entry>
<title>正则学习笔记一</title>
<link href="http://yoursite.com/2019/05/27/%E6%AD%A3%E5%88%99%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0%E4%B8%80/"/>
<id>http://yoursite.com/2019/05/27/正则学习笔记一/</id>
<published>2019-05-27T10:39:52.000Z</published>
<updated>2019-05-27T10:46:03.284Z</updated>
<content type="html"><![CDATA[<h1 id="chapter1"><a href="#chapter1" class="headerlink" title="chapter1"></a>chapter1</h1><p>前两章强调了一个核心理念: <strong>正则表达式是匹配模式,要么匹配字符,要么匹配位置</strong>;<br>首先来看匹配字符</p><a id="more"></a><h2 id="两种模糊匹配"><a href="#两种模糊匹配" class="headerlink" title="两种模糊匹配"></a>两种模糊匹配</h2><ol><li><p>横向模糊匹配,相同的字符出现多次</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">var regex = /ab{2,5}c/g;</span><br><span class="line">var string = "abc abbc abbbc abbbbc abbbbbc abbbbbbc";</span><br><span class="line">console.log( string.match(regex) );</span><br><span class="line">// => ["abbc", "abbbc", "abbbbc", "abbbbbc"]</span><br><span class="line">// 没有g只返回第一个</span><br></pre></td></tr></table></figure></li><li><p>纵向模糊匹配一个字符多个不同的选择</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">var regex = /a[123]b/g;</span><br><span class="line">var string = "a0b a1b a2b a3b a4b";</span><br><span class="line">console.log( string.match(regex) );</span><br><span class="line">// => ["a1b", "a2b", "a3b"]</span><br></pre></td></tr></table></figure></li></ol><h2 id="分组"><a href="#分组" class="headerlink" title="分组"></a>分组</h2><ol><li><p>范围表示法</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">[123456abcdefGHIJKLM] [1-6a-fG-M]</span><br></pre></td></tr></table></figure></li><li><p>转义</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">匹配'a''-''z' 任意一个字符 => [a\-z]</span><br></pre></td></tr></table></figure></li><li><p>取反: /[^abc]/i:除去abc之外的小写字母</p></li></ol><h2 id="常见的简写形式"><a href="#常见的简写形式" class="headerlink" title="常见的简写形式"></a>常见的简写形式</h2><table><thead><tr><th>字符组</th><th>具体含义</th></tr></thead><tbody><tr><td>\d</td><td>[0-9],所有数字digit </td></tr><tr><td>\D</td><td>[^0-9],除数字之外的其他字符</td></tr><tr><td>\w</td><td>[0-9a-zA-Z_] 数字字母下划线(便捷记忆:word)</td></tr><tr><td>\W</td><td>word 取反</td></tr><tr><td>\s</td><td>[ \t\v\n\r\f]</td></tr><tr><td>\S</td><td>\s 取反</td></tr><tr><td>.</td><td>通配符</td></tr></tbody></table><h2 id="量词"><a href="#量词" class="headerlink" title="量词"></a>量词</h2><table><thead><tr><th>量词</th><th>含义</th></tr></thead><tbody><tr><td>{m,n}</td><td>出现m到n次</td></tr><tr><td>{m}</td><td>出现m次</td></tr><tr><td>{m,}</td><td>至少出现m次</td></tr><tr><td>?</td><td>{0,1}</td></tr><tr><td>+</td><td>{1,}</td></tr><tr><td>*</td><td>{0,}</td></tr></tbody></table><h3 id="贪婪匹配和惰性匹配"><a href="#贪婪匹配和惰性匹配" class="headerlink" title="贪婪匹配和惰性匹配"></a>贪婪匹配和惰性匹配</h3><p>什么是贪婪模式?什么是惰性模式?看完以下两点之后我们举例说明</p><ol><li>默认为贪婪模式,尽可能多的匹配</li><li>贪婪模式转惰性模式: 在量词之后加’?’;<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">ex:</span><br></pre></td></tr></table></figure></li></ol><h2 id="多选分支"><a href="#多选分支" class="headerlink" title="多选分支"></a>多选分支</h2><p>多个子模式任选其一</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">var regex = /good|nice/g;</span><br><span class="line">var string = "good idea, nice try.";</span><br><span class="line">console.log( string.match(regex) );</span><br><span class="line">// ['good','nice']</span><br></pre></td></tr></table></figure><p>分支匹配也是惰性的,举例如下:<br><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">var regex = /good|goodbye/g;</span><br><span class="line">var string = "goodbye";</span><br><span class="line">console.log( string.match(regex) );</span><br><span class="line">// ['good']</span><br></pre></td></tr></table></figure></p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">var regex = /goodbye|good/g;</span><br><span class="line">var string = "goodbye";</span><br><span class="line">console.log( string.match(regex) );</span><br><span class="line">// ['goodbye']</span><br></pre></td></tr></table></figure><p>他的惰性体现在: 当前面的匹配上了,后面的就不再尝试了!</p><h2 id="阶段实战"><a href="#阶段实战" class="headerlink" title="阶段实战"></a>阶段实战</h2><ol><li>匹配16进制的颜色<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">reg = /#([\da-fA-F]{6}|[\da-fA-F]{3})/</span><br></pre></td></tr></table></figure></li></ol><p>需要关注的点: 6和3的位置互换之后,遇到#123456会只返回#123;<br>换一个写法: </p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">reg = /#([\da-f]{3}){1,2}/gi</span><br></pre></td></tr></table></figure><ol start="2"><li>匹配24小时制时间,例如: 01:59,21:00;分析:<br>首位可以是[0-2],首位是2的时候第二位只能是[0-3];第三位[0-5];第四位[0-9]:</li></ol><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">let reg = /^([2][0-3]|(0|1)\d):[0-5]\d$/g</span><br><span class="line">console.log( reg.test("02:07") );</span><br></pre></td></tr></table></figure><ol start="3"><li><p>匹配日期: 2019-09-01(不考虑大小月,2.29,2.30等问题)</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">var reg = /[0-9]{4}-(0\d|1[0-2])-[0-3][1-9]/</span><br></pre></td></tr></table></figure></li><li><p>匹配 html 标签中的id;<br><code><div id="container" class="main"></div></code></p></li></ol><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">var reg = /id="\w+"/</span><br><span class="line">// reg = /id=".*"/</span><br></pre></td></tr></table></figure><ul><li>保留问题如何直接提取出id的值呢?<h3 id="小结"><a href="#小结" class="headerlink" title="小结"></a>小结</h3>掌握字符组和量词就能解决大部分常见的情形,也就是说,当你会了这二者,JavaScript 正则算是入门了。</li></ul>]]></content>
<summary type="html">
<h1 id="chapter1"><a href="#chapter1" class="headerlink" title="chapter1"></a>chapter1</h1><p>前两章强调了一个核心理念: <strong>正则表达式是匹配模式,要么匹配字符,要么匹配位置</strong>;<br>首先来看匹配字符</p>
</summary>
<category term="web" scheme="http://yoursite.com/categories/web/"/>
<category term="正则" scheme="http://yoursite.com/tags/%E6%AD%A3%E5%88%99/"/>
</entry>
<entry>
<title>结合Vue源码谈谈发布-订阅模式</title>
<link href="http://yoursite.com/2019/05/21/pub-sub/"/>
<id>http://yoursite.com/2019/05/21/pub-sub/</id>
<published>2019-05-21T09:28:40.000Z</published>
<updated>2019-05-21T15:00:18.514Z</updated>
<content type="html"><![CDATA[<p>最近的工作学习中接触到了发布-订阅模式。该思想编程中的应用也是很广泛的, 例如在 <code>Vue</code>中也大量使用了该设计模式,所以会结合Vue的源码和大家谈谈自己粗浅的理解.</p><h2 id="发布订阅模式主要包含哪些内容呢"><a href="#发布订阅模式主要包含哪些内容呢" class="headerlink" title="发布订阅模式主要包含哪些内容呢?"></a>发布订阅模式主要包含哪些内容呢?</h2><ol><li>发布函数,发布的时候执行相应的回调</li><li>订阅函数,添加订阅者,传入发布时要执行的函数,可能会携额外参数</li><li>一个缓存订阅者以及订阅者的回调函数的列表</li><li>取消订阅(需要分情况讨论)</li></ol><p>这么看下来,其实就像 <code>JavaScript</code> 中的事件模型,我们在DOM节点上绑定事件函数,触发的时候执行就是应用了发布-订阅模式.<br><a id="more"></a></p><h2 id="我们先按照上面的内容自己实现一个-Observer-对象如下"><a href="#我们先按照上面的内容自己实现一个-Observer-对象如下" class="headerlink" title="我们先按照上面的内容自己实现一个 Observer 对象如下:"></a>我们先按照上面的内容自己实现一个 <code>Observer</code> 对象如下:</h2><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br></pre></td><td class="code"><pre><span class="line">//用于存储订阅的事件名称以及回调函数列表的键值对</span><br><span class="line">function Observer() {</span><br><span class="line"> this.cache = {} </span><br><span class="line">}</span><br><span class="line"></span><br><span class="line">//key:订阅消息的类型的标识(名称),fn收到消息之后执行的回调函数</span><br><span class="line">Observer.prototype.on = function (key,fn) {</span><br><span class="line"> if(!this.cache[key]){</span><br><span class="line"> this.cache[key]=[]</span><br><span class="line"> }</span><br><span class="line"> this.cache[key].push(fn)</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">//arguments 是发布消息时候携带的参数数组</span><br><span class="line">Observer.prototype.emit = function (key) {</span><br><span class="line"> if(this.cache[key]&&this.cache[key].length>0){</span><br><span class="line"> var fns = this.cache[key]</span><br><span class="line"> }</span><br><span class="line"> for(let i=0;i<fns.length;i++){</span><br><span class="line"> Array.prototype.shift.call(arguments)</span><br><span class="line"> fns[i].apply(this,arguments)</span><br><span class="line"> }</span><br><span class="line">}</span><br><span class="line">// remove 的时候需要注意,如果你直接传入一个匿名函数fn,那么你在remove的时候是无法找到这个函数并且把它移除的,变通方式是传入一个</span><br><span class="line">//指向该函数的指针,而 订阅的时候存入的也是这个指针</span><br><span class="line">Observer.prototype.remove = function (key,fn) {</span><br><span class="line"> let fns = this.cache[key]</span><br><span class="line"> if(!fns||fns.length===0){</span><br><span class="line"> return</span><br><span class="line"> }</span><br><span class="line"> //如果没有传入fn,那么就是取消所有该事件的订阅</span><br><span class="line"> if(!fn){</span><br><span class="line"> fns=[]</span><br><span class="line"> }else {</span><br><span class="line"> fns.forEach((item,index)=>{</span><br><span class="line"> if(item===fn){</span><br><span class="line"> fns.splice(index,1)</span><br><span class="line"> }</span><br><span class="line"> })</span><br><span class="line"> }</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">//example</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">var obj = new Observer()</span><br><span class="line">obj.on('hello',function (a,b) {</span><br><span class="line"> console.log(a,b)</span><br><span class="line">})</span><br><span class="line">obj.emit('hello',1,2)</span><br><span class="line">//取消订阅事件的回调必须是具名函数</span><br><span class="line">obj.on('test',fn1 =function () {</span><br><span class="line"> console.log('fn1')</span><br><span class="line">})</span><br><span class="line">obj.on('test',fn2 = function () {</span><br><span class="line"> console.log('fn2')</span><br><span class="line">})</span><br><span class="line">obj.remove('test',fn1)</span><br><span class="line">obj.emit('test')</span><br></pre></td></tr></table></figure><p>为什么会使用发布订阅模式呢? 它的优点在于:</p><ol><li>实现<strong>时间上的解耦</strong>(组件,模块之间的异步通讯)</li><li><strong>对象之间的解耦</strong>,交由发布订阅的对象管理对象之间的耦合关系.</li></ol><h2 id="发布-订阅模式在-Vue中的应用"><a href="#发布-订阅模式在-Vue中的应用" class="headerlink" title="发布-订阅模式在 Vue中的应用"></a>发布-订阅模式在 <code>Vue</code>中的应用</h2><ol><li><code>Vue</code>的实例方法中的应用:(当前版本:2.5.16)<ul><li><a href="https://cn.vuejs.org/v2/api/#vm-on" target="_blank" rel="noopener">文档传送门</a></li><li><a href="https://github.com/vuejs/vue/blob/c24f3e4208cd045832002ee9916559f6fe0dc2b5/src/core/instance/events.js" target="_blank" rel="noopener">源码传送门</a></li></ul></li></ol><ul><li>源码节选 :(引入了flow.js用于静态类型检查)</li></ul><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br></pre></td><td class="code"><pre><span class="line">// vm.$on</span><br><span class="line">export function eventsMixin (Vue: Class<Component>) {</span><br><span class="line"> const hookRE = /^hook:/</span><br><span class="line"> //参数类型为字符串或者字符串组成的数组</span><br><span class="line"> Vue.prototype.$on = function (event: string | Array<string>, fn: Function): Component {</span><br><span class="line"> const vm: Component = this</span><br><span class="line"> // 传入类型为数组</span><br><span class="line"> if (Array.isArray(event)) {</span><br><span class="line"> for (let i = 0, l = event.length; i < l; i++) {</span><br><span class="line"> this.$on(event[i], fn)</span><br><span class="line"> //递归并传入相应的回调</span><br><span class="line"> }</span><br><span class="line"> } else {</span><br><span class="line"> //</span><br><span class="line"> (vm._events[event] || (vm._events[event] = [])).push(fn)</span><br><span class="line"> // optimize hook:event cost by using a boolean flag marked at registration</span><br><span class="line"> // instead of a hash lookup</span><br><span class="line"> if (hookRE.test(event)) {</span><br><span class="line"> vm._hasHookEvent = true</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line"> return vm</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">// vm.$emit</span><br><span class="line"></span><br><span class="line"> Vue.prototype.$emit = function (event: string): Component {</span><br><span class="line"> const vm: Component = this</span><br><span class="line"> if (process.env.NODE_ENV !== 'production') {</span><br><span class="line"> const lowerCaseEvent = event.toLowerCase()</span><br><span class="line"> if (lowerCaseEvent !== event && vm._events[lowerCaseEvent]) {</span><br><span class="line"> tip(</span><br><span class="line"> `Event "${lowerCaseEvent}" is emitted in component ` +</span><br><span class="line"> `${formatComponentName(vm)} but the handler is registered for "${event}". ` +</span><br><span class="line"> `Note that HTML attributes are case-insensitive and you cannot use ` +</span><br><span class="line"> `v-on to listen to camelCase events when using in-DOM templates. ` +</span><br><span class="line"> `You should probably use "${hyphenate(event)}" instead of "${event}".`</span><br><span class="line"> )</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line"> let cbs = vm._events[event]</span><br><span class="line"> if (cbs) {</span><br><span class="line"> cbs = cbs.length > 1 ? toArray(cbs) : cbs</span><br><span class="line"> const args = toArray(arguments, 1)</span><br><span class="line"> for (let i = 0, l = cbs.length; i < l; i++) {</span><br><span class="line"> try {</span><br><span class="line"> cbs[i].apply(vm, args)// 执行之前传入的回调</span><br><span class="line"> } catch (e) {</span><br><span class="line"> handleError(e, vm, `event handler for "${event}"`)</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line"> return vm</span><br><span class="line"> }</span><br></pre></td></tr></table></figure><p><code>Vue</code>中还实现了<code>vm.$once</code> (监听一次);以及<code>vm.$off</code> (取消订阅) ,大家可以在同一文件中看一下是如何实现的.</p><ol start="2"><li><code>Vue</code>数据更新机制中的应用</li></ol><ul><li>observer每个对象的属性,添加到订阅者容器Dependency(Dep)中,当数据发生变化的时候发出notice通知。</li><li>Watcher:某个属性数据的监听者/订阅者,一旦数据有变化,它会通知指令(directive)重新编译模板并渲染UI</li><li>部分源码如下: <a href="https://github.com/vuejs/vue/blob/dev/src/core/observer/index.js" target="_blank" rel="noopener">源码传送门-observer</a></li></ul><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br></pre></td><td class="code"><pre><span class="line">export class Observer {</span><br><span class="line"> value: any;</span><br><span class="line"> dep: Dep;</span><br><span class="line"> vmCount: number; // number of vms that has this object as root $data</span><br><span class="line"></span><br><span class="line"> constructor (value: any) {</span><br><span class="line"> this.value = value</span><br><span class="line"> this.dep = new Dep()</span><br><span class="line"> this.vmCount = 0</span><br><span class="line"> def(value, '__ob__', this)</span><br><span class="line"> if (Array.isArray(value)) {</span><br><span class="line"> const augment = hasProto</span><br><span class="line"> ? protoAugment</span><br><span class="line"> : copyAugment</span><br><span class="line"> augment(value, arrayMethods, arrayKeys)</span><br><span class="line"> this.observeArray(value)</span><br><span class="line"> } else {</span><br><span class="line"> this.walk(value)</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> /**</span><br><span class="line"> * Walk through each property and convert them into</span><br><span class="line"> * getter/setters. This method should only be called when</span><br><span class="line"> * value type is Object.</span><br><span class="line"> */</span><br><span class="line"> // 属性为对象的时候,observe 对象的属性</span><br><span class="line"> walk (obj: Object) {</span><br><span class="line"> const keys = Object.keys(obj)</span><br><span class="line"> for (let i = 0; i < keys.length; i++) {</span><br><span class="line"> defineReactive(obj, keys[i])</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> /**</span><br><span class="line"> * Observe a list of Array items.</span><br><span class="line"> */</span><br><span class="line"> observeArray (items: Array<any>) {</span><br><span class="line"> for (let i = 0, l = items.length; i < l; i++) {</span><br><span class="line"> observe(items[i])</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line">}</span><br></pre></td></tr></table></figure><ul><li>Dep对象: 订阅者容器,负责维护watcher<a href="https://github.com/vuejs/vue/blob/dev/src/core/observer/dep.js" target="_blank" rel="noopener">源码传送门</a></li></ul><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br></pre></td><td class="code"><pre><span class="line">export default class Dep {</span><br><span class="line"> static target: ?Watcher;</span><br><span class="line"> id: number;</span><br><span class="line"> subs: Array<Watcher>;</span><br><span class="line"></span><br><span class="line"> constructor () {</span><br><span class="line"> this.id = uid++</span><br><span class="line"> this.subs = [] //存储订阅者 </span><br><span class="line"> }</span><br><span class="line"> // 添加watcher</span><br><span class="line"> addSub (sub: Watcher) {</span><br><span class="line"> this.subs.push(sub)</span><br><span class="line"> }</span><br><span class="line"> // 移除</span><br><span class="line"> removeSub (sub: Watcher) {</span><br><span class="line"> remove(this.subs, sub)</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> depend () {</span><br><span class="line"> if (Dep.target) {</span><br><span class="line"> Dep.target.addDep(this)</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line"> // 变更通知</span><br><span class="line"> notify () {</span><br><span class="line"> // stabilize the subscriber list first</span><br><span class="line"> const subs = this.subs.slice()</span><br><span class="line"> for (let i = 0, l = subs.length; i < l; i++) {</span><br><span class="line"> subs[i].update()</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line">}</span><br></pre></td></tr></table></figure><h2 id="工作中小应用举例"><a href="#工作中小应用举例" class="headerlink" title="工作中小应用举例"></a>工作中小应用举例</h2><ol><li>场景: 基于wepy的小程序. 由于项目本身不是足够的复杂到要使用提供的 <code>redux</code>进行状态管理.但是在不同的组件(不限于父子组件)之间,存在相关联的异步操作.所以在wepy对象上挂载了一个本文最开始实现的Observer对象.作为部分组件之间通信的总线机制:</li></ol><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">wepy.$bus = new Observer()</span><br><span class="line">// 然后就可以在不同的模块和组件中订阅和发布消息了</span><br></pre></td></tr></table></figure><h2 id="要注意的点"><a href="#要注意的点" class="headerlink" title="要注意的点"></a>要注意的点</h2><p>当然,发布-订阅模式也是有缺点的. </p><ol><li>创建订阅者本身会消耗内存,订阅消息后,也许,永远也不会有发布,而订阅者始终存在内存中.</li><li>对象之间解耦的同时,他们的关系也会被深埋在代码背后,这会造成一定的维护成本.</li></ol><p>当然设计模式的存在是帮助我们解决特定场景的问题的,学会在正确的场景中使用才是最重要的.</p>]]></content>
<summary type="html">
<p>最近的工作学习中接触到了发布-订阅模式。该思想编程中的应用也是很广泛的, 例如在 <code>Vue</code>中也大量使用了该设计模式,所以会结合Vue的源码和大家谈谈自己粗浅的理解.</p>
<h2 id="发布订阅模式主要包含哪些内容呢"><a href="#发布订阅模式主要包含哪些内容呢" class="headerlink" title="发布订阅模式主要包含哪些内容呢?"></a>发布订阅模式主要包含哪些内容呢?</h2><ol>
<li>发布函数,发布的时候执行相应的回调</li>
<li>订阅函数,添加订阅者,传入发布时要执行的函数,可能会携额外参数</li>
<li>一个缓存订阅者以及订阅者的回调函数的列表</li>
<li>取消订阅(需要分情况讨论)</li>
</ol>
<p>这么看下来,其实就像 <code>JavaScript</code> 中的事件模型,我们在DOM节点上绑定事件函数,触发的时候执行就是应用了发布-订阅模式.<br>
</summary>
<category term="web" scheme="http://yoursite.com/categories/web/"/>
<category term="设计模式" scheme="http://yoursite.com/tags/%E8%AE%BE%E8%AE%A1%E6%A8%A1%E5%BC%8F/"/>
<category term="源码" scheme="http://yoursite.com/tags/%E6%BA%90%E7%A0%81/"/>
</entry>
<entry>
<title>hexo+githubPages 建站记录</title>
<link href="http://yoursite.com/2019/03/20/test-article/"/>
<id>http://yoursite.com/2019/03/20/test-article/</id>
<published>2019-03-20T06:45:20.000Z</published>
<updated>2019-05-23T02:07:45.954Z</updated>
<content type="html"><![CDATA[<h2 id="使用githubPages"><a href="#使用githubPages" class="headerlink" title="使用githubPages"></a>使用githubPages</h2><ol><li>新建仓库,仓库名 <code>你的用户名+github.io</code>;例如我的仓库名是 <code>lance10030.github.io</code>. 要求源自于 <a href="https://help.github.com/en/categories/github-pages-basics" target="_blank" rel="noopener">Github Pages</a>.</li><li>确保本地配置好了<code>github</code>的<code>ssh</code>, <a href="https://juejin.im/post/5ac0a382f265da238533012d" target="_blank" rel="noopener">配置教程</a>.</li><li>项目中配置<code>_config.yml</code>,示例如下<a id="more"></a></li></ol><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">deploy:</span><br><span class="line"> type: git</span><br><span class="line"> repository: git@github.com:lance10030/lance10030.github.io.git</span><br><span class="line"> branch: master</span><br></pre></td></tr></table></figure><ol start="4"><li>按照<a href="https://hexo.io/zh-cn/docs/" target="_blank" rel="noopener">hexo文档</a>;做配置,创建测试文章,然后<br><code>hexo g</code>;然后运行<code>hexo d</code>,打开 <code>用户名.github.io</code>看看初步的效果;<h2 id="主题"><a href="#主题" class="headerlink" title="主题"></a>主题</h2>我是用的主题是:<a href="https://github.com/litten/hexo-theme-yilia" target="_blank" rel="noopener">yilia</a>,具体用法如下:</li></ol><ul><li>进入你的项目文件夹;</li><li><code>git clone https://github.com/litten/hexo-theme-yilia.git themes/yilia</code></li><li>修改配置文件<code>_config.yml</code></li></ul><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">theme: yilia</span><br></pre></td></tr></table></figure><ul><li>主题的详细是用查看<a href="https://github.com/litten/hexo-theme-yilia" target="_blank" rel="noopener">hexo-theme-yilia</a>的<code>README</code>文件.</li><li><a href="https://www.zhihu.com/question/24422335" target="_blank" rel="noopener">其他主题推荐</a></li></ul><h3 id="使用-yilia-遇到的问题"><a href="#使用-yilia-遇到的问题" class="headerlink" title="使用 yilia 遇到的问题"></a>使用 yilia 遇到的问题</h3><ol><li>主页文章没有折叠的问题<br>该问题的解决方法是在文章中(.md文件)需要折叠的内容之后加上:<br><code><!--more--></code><br>目前没找到自动换行的方法</li><li>搜索部分报模块缺失:<br>主要是跟目录下_config.yml 文件中按照yilia的说明添加的 <code>jsonContent:</code> 的空格问题.yml对空格的要求比较严格;</li></ol>]]></content>
<summary type="html">
<h2 id="使用githubPages"><a href="#使用githubPages" class="headerlink" title="使用githubPages"></a>使用githubPages</h2><ol>
<li>新建仓库,仓库名 <code>你的用户名+github.io</code>;例如我的仓库名是 <code>lance10030.github.io</code>. 要求源自于 <a href="https://help.github.com/en/categories/github-pages-basics" target="_blank" rel="noopener">Github Pages</a>.</li>
<li>确保本地配置好了<code>github</code>的<code>ssh</code>, <a href="https://juejin.im/post/5ac0a382f265da238533012d" target="_blank" rel="noopener">配置教程</a>.</li>
<li>项目中配置<code>_config.yml</code>,示例如下
</summary>
<category term="Diary" scheme="http://yoursite.com/categories/Diary/"/>
<category term="建站" scheme="http://yoursite.com/tags/%E5%BB%BA%E7%AB%99/"/>
<category term="hexo + gihubPage" scheme="http://yoursite.com/tags/hexo-gihubPage/"/>
</entry>
</feed>