-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathatom.xml
180 lines (120 loc) · 89.7 KB
/
atom.xml
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
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
<title>GrowthCoder</title>
<subtitle>听小听的博客</subtitle>
<link href="/atom.xml" rel="self"/>
<link href="growthcoder.me/"/>
<updated>2018-02-08T08:09:42.661Z</updated>
<id>growthcoder.me/</id>
<author>
<name>听小听</name>
</author>
<generator uri="http://hexo.io/">Hexo</generator>
<entry>
<title>深入浅出React和Redux笔记之Redux</title>
<link href="growthcoder.me/2018/02/08/%E6%B7%B1%E5%85%A5%E6%B5%85%E5%87%BAReact%E5%92%8CRedux%E7%AC%94%E8%AE%B0%E4%B9%8BRedux/"/>
<id>growthcoder.me/2018/02/08/深入浅出React和Redux笔记之Redux/</id>
<published>2018-02-08T07:58:22.000Z</published>
<updated>2018-02-08T08:09:42.661Z</updated>
<content type="html"><![CDATA[<h4 id="三个基本原则"><a href="#三个基本原则" class="headerlink" title="三个基本原则"></a>三个基本原则</h4><ul><li><p>唯一数据源</p> <figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div></pre></td><td class="code"><pre><div class="line">应用的状态数据应该只存储在唯一的一个 Store 上。这个唯一 Store 上的状态,</div><div class="line">是一个树形的对象,每个组件往往只是用树形对象上一部</div><div class="line">分的数据,而如何设计 Store 上状态的结构,就是 Redux 应用的核心问题</div></pre></td></tr></table></figure></li><li><p>保持状态只读</p> <figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div></pre></td><td class="code"><pre><div class="line">保持状态只读,就是说不能去直接修改状态,要修改 Store 的状态,必须要通过派发</div><div class="line">一个 action 对象完成。</div><div class="line"> 要驱动用户界面渲染,就要改变应用的状态,但是改变状态的方法不是去修</div><div class="line">改状态上值,而是创建一个新的状态对象返回给 Redux ,由 Redux 完成新的状态的组装</div></pre></td></tr></table></figure></li></ul><a id="more"></a><ul><li><p>数据改变只能通过纯函数完成</p> <figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div></pre></td><td class="code"><pre><div class="line">纯函数就是 Reducer</div><div class="line"></div><div class="line">reducer(state , action )</div><div class="line"></div><div class="line">第一个参数 state 是当前的状态,</div><div class="line">第二个参数 action 是接收到的 action 对象,</div><div class="line">而 reducer函数要做的事情,就是根据 state 和 action 的值产生一个新的对象返回,</div><div class="line">注意 reducer 必须是纯函数,</div><div class="line">也就是说函数的返回结果必须完全由参数 state 和 action 决定,</div><div class="line">而且不产生任何副作用,也不能修改参数 state 和 action 对象。</div></pre></td></tr></table></figure> <figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div></pre></td><td class="code"><pre><div class="line">// Redux的 reducer 只负责计算状态,却并不负责存储状态</div><div class="line"></div><div class="line">function reducer(state , action) => {</div><div class="line"> const {counterCaption} = action;</div><div class="line"></div><div class="line"> switch (action.type) {</div><div class="line"> case ActionTypes.INCREMENT :</div><div class="line"> return { ...state , [ counterCaption] : state [ counterCaption ] + 1};</div><div class="line"> case ActionTypes . DECREMENT:</div><div class="line"> return { ...state, [counterCaption] : state [ counterCaption) - 1};</div><div class="line"> default :</div><div class="line"> return state</div><div class="line"> }</div><div class="line">}</div></pre></td></tr></table></figure></li></ul><h4 id="Redux-Context"><a href="#Redux-Context" class="headerlink" title="Redux Context"></a>Redux Context</h4><ul><li><code><Provider store={store}></code> react-redux库提供provider</li><li><strong>connect</strong> 接受两个参数</li></ul><h3 id="模块化Redux和React应用"><a href="#模块化Redux和React应用" class="headerlink" title="模块化Redux和React应用"></a>模块化Redux和React应用</h3><p>构建应用的基础</p><ul><li>代码文件的组织结构(按角色划分)</li><li>确定模块的边界</li><li>Store的状态树设计<ul><li>一个模块控制一个状态节点<ul><li>只能修改自己相关的那一部分数据,修改权是互斥的</li></ul></li><li>避免冗余数据</li><li>树形结构扁平</li></ul></li></ul><h3 id="参考资料"><a href="#参考资料" class="headerlink" title="参考资料"></a>参考资料</h3><p><a href="http://www.ruanyifeng.com/blog/2016/09/redux_tutorial_part_one_basic_usages.html" target="_blank" rel="external">阮一峰 Redux 入门教程(一):基本用法</a></p>]]></content>
<summary type="html">
<h4 id="三个基本原则"><a href="#三个基本原则" class="headerlink" title="三个基本原则"></a>三个基本原则</h4><ul>
<li><p>唯一数据源</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div></pre></td><td class="code"><pre><div class="line">应用的状态数据应该只存储在唯一的一个 Store 上。这个唯一 Store 上的状态,</div><div class="line">是一个树形的对象,每个组件往往只是用树形对象上一部</div><div class="line">分的数据,而如何设计 Store 上状态的结构,就是 Redux 应用的核心问题</div></pre></td></tr></table></figure>
</li>
<li><p>保持状态只读</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div></pre></td><td class="code"><pre><div class="line">保持状态只读,就是说不能去直接修改状态,要修改 Store 的状态,必须要通过派发</div><div class="line">一个 action 对象完成。</div><div class="line"> 要驱动用户界面渲染,就要改变应用的状态,但是改变状态的方法不是去修</div><div class="line">改状态上值,而是创建一个新的状态对象返回给 Redux ,由 Redux 完成新的状态的组装</div></pre></td></tr></table></figure>
</li>
</ul>
</summary>
</entry>
<entry>
<title>深入浅出React和Redux笔记之React</title>
<link href="growthcoder.me/2018/02/08/%E6%B7%B1%E5%85%A5%E6%B5%85%E5%87%BAReact%E5%92%8CRedux%E7%AC%94%E8%AE%B0%E4%B9%8BReact/"/>
<id>growthcoder.me/2018/02/08/深入浅出React和Redux笔记之React/</id>
<published>2018-02-08T07:57:06.000Z</published>
<updated>2018-02-08T08:03:44.761Z</updated>
<content type="html"><![CDATA[<h3 id="第一章-React新的前端思维"><a href="#第一章-React新的前端思维" class="headerlink" title="第一章 React新的前端思维"></a>第一章 React新的前端思维</h3><ul><li><strong>响应式编程</strong> Reactive Programming</li><li><code>Virutal DOM</code>不会触及浏览器的部分,只是存在于 JavaScript 空间的树形结构,每次自上而下渲<br>染 React 组件时,会对比这一次产生的 <code>Virutal DOM</code> 和上一次渲染的 <code>VirutalDOM</code>,对比<br>就会发现差别,然后修改真正的<code>DOM</code>树时就只需要触及差别中的部分就行。</li><li><code>React</code>等于强制所有组件都按照这种由<code>数据驱动渲染的模式</code>来工作,无论应用的规模多大,都能让程序处于可控范围内。<a id="more"></a><h3 id="第二章-构建高质量React组件"><a href="#第二章-构建高质量React组件" class="headerlink" title="第二章 构建高质量React组件"></a>第二章 构建高质量React组件</h3></li><li>组件的划分要满足<strong>高内聚、低耦合</strong>的原则</li></ul><h4 id="React-的-prop"><a href="#React-的-prop" class="headerlink" title="React 的 prop"></a>React 的 prop</h4><ul><li><p>在 <code>ControlPanel</code>的<code>render</code>函数中将这三个子组件实例用<code>div</code>包起来,因为<code>React</code>要求<code>render</code>函数只能返回一个元素</p></li><li><p>如果一个组件需要定义自己的<strong>构造函数</strong>,一定要记得在构造函数的第一行通过 <code>super</code>调用父类也就是<code>React.Component</code>的构造函数。<strong>如果在构造函数中没有调用 <code>super(props)</code>,那么组件实例被构造之后,类实例的所有成员函数就无法通过<code>this.props</code>访问到父组件传递过来的<code>props</code>值</strong>。很明显,给<code>this.props</code>赋值是 <code>React.Component</code>构造函数的工作之一</p></li></ul><figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div></pre></td><td class="code"><pre><div class="line">constructor(props) {</div><div class="line"> console.log('enter constructor:' + props.caption);</div><div class="line"></div><div class="line"> /*</div><div class="line"> * 若未调用父组件的构造函数</div><div class="line"> * 类实例的所有成员函数就无法通过 this.props 访问到父组件传递过来的 props 值</div><div class="line"> */</div><div class="line"> super(props);</div><div class="line"></div><div class="line"> // ES6方法创造的 React 组件类并不自动给我们绑定 this 到当前实例对象</div><div class="line"> this.onClickIncrementButton = this.onClickIncrementButton.bind(this);</div><div class="line"> this.onClickDecrementButton = this.onClickDecrementButton.bind(this);</div><div class="line"></div><div class="line"> this.state = {</div><div class="line"> count: props.initValue || 0</div><div class="line"> }</div><div class="line">}</div></pre></td></tr></table></figure><ul><li>ES6方法创造的 React 组件类并不自动给我们绑定 this 到当前实例对象</li></ul><h3 id="组件的生命周期"><a href="#组件的生命周期" class="headerlink" title="组件的生命周期"></a>组件的生命周期</h3><ul><li>装载过程(Mount ),也就是把组件第一次在 DOM 树中渲染的过程;</li><li>更新过程(Update ),当组件被重新渲染的过程;</li><li>卸载过程(Unmount),组件从 DOM 中删除的过程。<h4 id="装载过程"><a href="#装载过程" class="headerlink" title="装载过程"></a>装载过程</h4><h5 id="constructor-NaN"><a href="#constructor-NaN" class="headerlink" title="constructor"></a>constructor</h5></li><li>无状态的 React 组件往往就不需要定义构造函数</li><li>以下场景需要构造函数:<strong>初始化 state、绑定成员函数的 this 环境</strong></li></ul><figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div></pre></td><td class="code"><pre><div class="line">在 ES6 语法下,类的每个成员函数在执行时的 this 并不是和类实例自动绑定的。</div><div class="line">而在构造函数中, this就是当前组件实例,</div><div class="line">所以,为了方便将来的调用,往往在构造函数中将这个实例的特定函数绑定 this 为当前实例</div></pre></td></tr></table></figure><figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div></pre></td><td class="code"><pre><div class="line">用 ES6 的话,在构造函数中通过给 this.state 赋值完成状态的初始化,通过给类属性</div><div class="line">(注意是类属性,而不是类的实例对象属性) defaultProps 赋值指定 props 初始值,达到的</div><div class="line">效果是完全一样的</div></pre></td></tr></table></figure><figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div></pre></td><td class="code"><pre><div class="line">class Sample extends React.Component {</div><div class="line"> constructor(props) {</div><div class="line"> super(props);</div><div class="line"> this.state = {foo:'bar'};</div><div class="line"> }</div><div class="line">}</div><div class="line">Sample.defaultProps = {</div><div class="line"> return {sampleProp: 0)</div><div class="line">}</div></pre></td></tr></table></figure><h5 id="render"><a href="#render" class="headerlink" title="render"></a>render</h5><ul><li>==<strong>所有 React 组件的父类 React. Component<br>类对除 render 之外的生命周期函数都有默认实现</strong>==</li><li>通常一个组件要发挥作用,总是要渲染一些东西, render 函数并不做实际的渲染动作,它只是返回一个 JSX 描述的结构,最终由 React 来操作渲染过程。</li><li>render 函数本身并不往 DOM 树上渲染或者装载内容,它只是返回一个 <code>JSX</code> 表示的对象,然后由 React 库来根据返回对象决定如何渲染</li></ul><h4 id="componentDidMount"><a href="#componentDidMount" class="headerlink" title="componentDidMount"></a>componentDidMount</h4><ul><li>所有组件的render函数调用之后,连在一起执行</li><li>此时DOM已装载完成</li></ul><h4 id="更新过程"><a href="#更新过程" class="headerlink" title="更新过程"></a>更新过程</h4><ul><li>当props或者state被修改时,会引发组件的更新过程</li><li>更新过程会依次调用以下生命周期函数</li></ul><figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div></pre></td><td class="code"><pre><div class="line">componentWillReceiveProps</div><div class="line">shouldComponentUpdate</div><div class="line">componentWillUpdate</div><div class="line">render</div><div class="line">componentDidUpdate</div></pre></td></tr></table></figure><h5 id="componentWillReceiveProps-nextProps"><a href="#componentWillReceiveProps-nextProps" class="headerlink" title="componentWillReceiveProps(nextProps)"></a>componentWillReceiveProps(nextProps)</h5><figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div></pre></td><td class="code"><pre><div class="line">只要是父组件的 render 函数被调用,在 render 函数里面被渲染的子组件就会经历更新过</div><div class="line">程,不管父组件传给子组件的 props 有没有改变,都会触发子组件的 componentWillReceiveProps 函数。</div><div class="line"></div><div class="line">通过 this.setState 方法触发的更新过程不会调用这个函数,这是因为这个函数</div><div class="line">适合根据新的 props 值(也就是参数 nextProps )来计算出是不是要更新内部状态 state</div></pre></td></tr></table></figure><h5 id="shouldComponentUpdate-nextProps-nextState"><a href="#shouldComponentUpdate-nextProps-nextState" class="headerlink" title="shouldComponentUpdate(nextProps, nextState)"></a>shouldComponentUpdate(nextProps, nextState)</h5><ul><li>决定了一个组件什么时候不需要渲染</li><li>要求有返回结果 返回布尔值:<strong>告诉 React 库这个组件在这次更新过程中是否要继续</strong>。</li><li><p>在更新过程中, <strong>React 库首先调用 shouldComponentUpdate函数</strong>,如果这个函数返回<br><strong>true ,那就会继续更新过程</strong>,接下来调用 render 函数;反之,如果得到一个 <strong>false</strong> ,那就<br>立刻<strong>停止更新</strong>过程,也就不会引发后续的渲染了</p></li><li><p>使用恰当,可以提高性能</p></li></ul><h4 id="卸载过程"><a href="#卸载过程" class="headerlink" title="卸载过程"></a>卸载过程</h4><h5 id="componentWillUnmount"><a href="#componentWillUnmount" class="headerlink" title="componentWillUnmount"></a>componentWillUnmount</h5><figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div></pre></td><td class="code"><pre><div class="line">React 组件的卸载过程只涉及一个函数 componentWillUnmount , 当 React 组件要从</div><div class="line">DOM 树上删除掉之前,对应的 componentWillUnmount 函数会被调用,所以这个函数适</div><div class="line">合做一些清理性的工作。</div></pre></td></tr></table></figure><h3 id="组件向外传递数据"><a href="#组件向外传递数据" class="headerlink" title="组件向外传递数据"></a>组件向外传递数据</h3><ul><li>子组件某些情况下也需要==把数据传递给父组件==</li></ul><h3 id="Provider"><a href="#Provider" class="headerlink" title="Provider"></a>Provider</h3><h3 id="注意事项"><a href="#注意事项" class="headerlink" title="注意事项"></a>注意事项</h3><ul><li><code>React.createClass 、 React.PropTypes</code>等模块被移出了<code>react</code>包,现在你必须从单独的包里引入。<br>==PropTypes is not defined==<figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">import PropTypes from 'prop-types';</div></pre></td></tr></table></figure></li></ul>]]></content>
<summary type="html">
<h3 id="第一章-React新的前端思维"><a href="#第一章-React新的前端思维" class="headerlink" title="第一章 React新的前端思维"></a>第一章 React新的前端思维</h3><ul>
<li><strong>响应式编程</strong> Reactive Programming</li>
<li><code>Virutal DOM</code>不会触及浏览器的部分,只是存在于 JavaScript 空间的树形结构,每次自上而下渲<br>染 React 组件时,会对比这一次产生的 <code>Virutal DOM</code> 和上一次渲染的 <code>Virutal
DOM</code>,对比<br>就会发现差别,然后修改真正的<code>DOM</code>树时就只需要触及差别中的部分就行。</li>
<li><code>React</code>等于强制所有组件都按照这种由<code>数据驱动渲染的模式</code>来工作,无论应用的规模多大,都能让程序处于可控范围内。
</summary>
</entry>
<entry>
<title>JavaScript设计模式【读书笔记】</title>
<link href="growthcoder.me/2018/02/08/JavaScript%E8%AE%BE%E8%AE%A1%E6%A8%A1%E5%BC%8F%E3%80%90%E8%AF%BB%E4%B9%A6%E7%AC%94%E8%AE%B0%E3%80%91/"/>
<id>growthcoder.me/2018/02/08/JavaScript设计模式【读书笔记】/</id>
<published>2018-02-08T07:46:10.000Z</published>
<updated>2018-02-08T07:54:37.436Z</updated>
<content type="html"><![CDATA[<h3 id="单例模式"><a href="#单例模式" class="headerlink" title="单例模式"></a>单例模式</h3><p>定义:<strong>保证一个类仅有一个实例</strong>,并提供全局访问。</p><p>有一些对象我们往往只需要一个,比如线程池、全局缓存、window对象<br><a id="more"></a><br><strong>实现单例模式</strong></p><figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div><div class="line">18</div><div class="line">19</div><div class="line">20</div><div class="line">21</div><div class="line">22</div><div class="line">23</div><div class="line">24</div><div class="line">25</div><div class="line">26</div><div class="line">27</div></pre></td><td class="code"><pre><div class="line"># 问题:此单例模式不透明、创建实例不按套路出牌</div><div class="line"># 构造函数不纯粹、且使用了匿名函数和闭包</div><div class="line"></div><div class="line">var Singleton = function(name) {</div><div class="line"> this.name = name;</div><div class="line">};</div><div class="line"></div><div class="line">Singleton.prototype.getName = function() {</div><div class="line"> console.log(this.name);</div><div class="line">};</div><div class="line"></div><div class="line">Singleton.getInstance = (function() {</div><div class="line"> var instance = null;</div><div class="line"></div><div class="line"> return function (name) {</div><div class="line"> if(!instance) {</div><div class="line"> instance = new Singleton(name);</div><div class="line"> }</div><div class="line"></div><div class="line"> return instance;</div><div class="line"> };</div><div class="line">})(); //立即执行函数</div><div class="line"></div><div class="line">var a = Singleton.getInstance('gao');</div><div class="line">var b = Singleton.getInstance('ting');</div><div class="line"></div><div class="line">console.log(a == b);</div></pre></td></tr></table></figure><p><strong>用代理实现单例模式</strong></p><figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div><div class="line">18</div><div class="line">19</div><div class="line">20</div><div class="line">21</div><div class="line">22</div></pre></td><td class="code"><pre><div class="line">var Singleton = function ( name ){</div><div class="line"> this.name = name;</div><div class="line">};</div><div class="line"></div><div class="line">var ProxySingleton = (function() {</div><div class="line"> var instance;</div><div class="line"></div><div class="line"> return function(name) {</div><div class="line"> if(!instance) {</div><div class="line"> instance = new Singleton(name);</div><div class="line"> }</div><div class="line"></div><div class="line"> return instance;</div><div class="line"> };</div><div class="line">})();</div><div class="line"></div><div class="line">var a = new ProxySingleton('gaot');</div><div class="line">var b = new ProxySingleton('ting');</div><div class="line"></div><div class="line">console.log(a == b); //true</div><div class="line">console.log(a); //Singleton { name: 'gaot' }</div><div class="line">console.log(b); //Singleton { name: 'gaot' }</div></pre></td></tr></table></figure><p>引入代理类,实现单例模式编写,将负责管理单例的逻辑移到了代理类ProxySington,与普通类组合,达到了单例模式的效果</p><p><strong>JavaScript中的单例模式</strong></p><p>全局变量可以当成单例模式来使用</p><p>降低全局变量带来的命名污染</p><ul><li>使用命名空间</li></ul><figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div><div class="line">18</div><div class="line">19</div></pre></td><td class="code"><pre><div class="line">var MyApp = {};</div><div class="line"></div><div class="line">MyApp.namespace = function(name) {</div><div class="line"> var parts = name.split('.');</div><div class="line"></div><div class="line"> var current = MyApp;</div><div class="line"></div><div class="line"> for(var i in parts) {</div><div class="line"> if(!current[parts[i]]) {</div><div class="line"> current[parts[i]] = {};</div><div class="line"> }</div><div class="line"></div><div class="line"> current = current[parts[i]];</div><div class="line"> console.log(current[parts[i]]);</div><div class="line"> }</div><div class="line">};</div><div class="line"></div><div class="line">MyApp.namespace('gao.ting');</div><div class="line">console.log(MyApp);</div></pre></td></tr></table></figure><ul><li>使用闭包封装私有变量</li></ul><figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div></pre></td><td class="code"><pre><div class="line">var user = (function(){</div><div class="line"> var __name = 'gaot',</div><div class="line"> __age = 25;</div><div class="line"></div><div class="line"> return function(){</div><div class="line"> return __name + ' ' + __age;</div><div class="line"> };</div><div class="line">})();</div><div class="line"></div><div class="line">console.log(user)</div></pre></td></tr></table></figure><p><strong>惰性单例模式</strong></p><p>需要的时候才去创建对象实例</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div></pre></td><td class="code"><pre><div class="line"># 管理单例模式逻辑</div><div class="line">var getSingle = function (fn) {</div><div class="line"> var result;</div><div class="line"></div><div class="line"> return function() {</div><div class="line"> return result || (result = fn.apply(this, arguments));</div><div class="line"> };</div><div class="line">};</div></pre></td></tr></table></figure>]]></content>
<summary type="html">
<h3 id="单例模式"><a href="#单例模式" class="headerlink" title="单例模式"></a>单例模式</h3><p>定义:<strong>保证一个类仅有一个实例</strong>,并提供全局访问。</p>
<p>有一些对象我们往往只需要一个,比如线程池、全局缓存、window对象<br>
</summary>
<category term="前端" scheme="growthcoder.me/tags/%E5%89%8D%E7%AB%AF/"/>
</entry>
<entry>
<title>Yeoman量身定制前端脚手架</title>
<link href="growthcoder.me/2018/01/28/Yeoman%E9%87%8F%E8%BA%AB%E5%AE%9A%E5%88%B6%E5%89%8D%E7%AB%AF%E8%84%9A%E6%89%8B%E6%9E%B6-md/"/>
<id>growthcoder.me/2018/01/28/Yeoman量身定制前端脚手架-md/</id>
<published>2018-01-28T05:18:51.000Z</published>
<updated>2018-02-08T07:47:02.939Z</updated>
<content type="html"><![CDATA[<h2 id="Yeoman是什么?"><a href="#Yeoman是什么?" class="headerlink" title="Yeoman是什么?"></a>Yeoman是什么?</h2><h3 id="Yeoman为何方神圣,说他有三头六臂一点都不夸张"><a href="#Yeoman为何方神圣,说他有三头六臂一点都不夸张" class="headerlink" title="Yeoman为何方神圣,说他有三头六臂一点都不夸张"></a>Yeoman为何方神圣,说他有三头六臂一点都不夸张</h3><p><img src="http://upload-images.jianshu.io/upload_images/2658726-d9f706a2c367f6f0.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240" alt="d5978593e4269f636f250dcdd8503590.png"></p><p>因为他<strong>由三部分组成</strong>:yo(脚手架工具)、grunt(等构建工具)、npm(等包管理器)。<br><a id="more"></a><br>官方文档中给他的定位为<strong>scaffolding tool</strong>,其实就是脚手架工具,可以帮助前端开发人员量身定制化自己的脚手架,省去copy环节。</p><p>使用 <strong>yeoman generator</strong>可以帮助我们<em>构建项目结构、安装依赖等</em>重复性操作,然而已有的generator有时并不能满足需求,所以可以使用yeoman的<a href="http://yeoman.io/generator/" target="_blank" rel="external">API</a>来构建自己的生成器。</p><p>通过定制好自己的generator之后,只需要几个命令,就可以使用自己的脚手架,并且自动化生成项目文件结构、配置文件、依赖包等。</p><p>接下来开始敲黑板、划重点了!!!</p><h3 id="配置开发环境"><a href="#配置开发环境" class="headerlink" title="配置开发环境"></a>配置开发环境</h3><p>需要安装node.js</p><p>安装Yeoman的<strong>命令行工具</strong>和开发<strong>Yeoman生成器</strong>的工具 generator-generator</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div></pre></td><td class="code"><pre><div class="line">npm install -g yo</div><div class="line">npm install -g generator-generator</div></pre></td></tr></table></figure><h3 id="初始化项目"><a href="#初始化项目" class="headerlink" title="初始化项目"></a>初始化项目</h3><figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">yo generator</div></pre></td></tr></table></figure><p>执行上述命令,执行前,不需要新建文件夹,yo generator会帮我们建好文件夹。Yeoman会在终端提出几个问题,这是一个交互式的配置过程。项目名自己设置,必须以generator-开头,协议选择MIT,协议完成后,Yeoman会自动安装项目依赖。当然可以终止掉自动安装,自己使用cnpm或者yarn进行安装,用了都说好。</p><p><img src="http://upload-images.jianshu.io/upload_images/2658726-29ecd6e8b6b3750f.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240" alt="yeoman.png"></p><p>最后生成的项目目录:<br><figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div></pre></td><td class="code"><pre><div class="line">generator-vue-test</div><div class="line">├ generators</div><div class="line"> ├ app</div><div class="line"> ├ index.js</div><div class="line"> ├ templates</div><div class="line"> ├ dummyfile.txt</div><div class="line">├ __tests__</div><div class="line"> ├ app.js</div><div class="line">├ LICENSE</div><div class="line">├ README.md</div><div class="line">├ package.json</div></pre></td></tr></table></figure></p><h3 id="配置"><a href="#配置" class="headerlink" title="配置"></a>配置</h3><p>/generators/app/index.js 是Yeoman的配置文件,生成器入口文件,在这里进行我们自己脚手架的配置</p><p>generators/app/templates/是默认存放文件的目录,所有模板文件都放在这个目录下,最后生成的脚手架也只有这个文件夹下的内容。</p><h4 id="prompting-接受用户输入阶段"><a href="#prompting-接受用户输入阶段" class="headerlink" title="prompting 接受用户输入阶段"></a>prompting 接受用户输入阶段</h4><figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div><div class="line">18</div></pre></td><td class="code"><pre><div class="line">module.exports = class extends Generator {</div><div class="line"> prompting() {</div><div class="line"> // Have Yeoman greet the user.</div><div class="line"> this.log(yosay(</div><div class="line"> 'Welcome to the awe-inspiring ' + chalk.red('generator-downloads') + ' generator!'</div><div class="line"> ));</div><div class="line"> const prompts = [{</div><div class="line"> type: 'confirm',</div><div class="line"> name: 'someAnswer',</div><div class="line"> message: 'Would you like to enable this option?',</div><div class="line"> default: true</div><div class="line"> }];</div><div class="line"> return this.prompt(prompts).then(props => {</div><div class="line"> // To access props later use this.props.someAnswer;</div><div class="line"> this.props = props;</div><div class="line"> });</div><div class="line"> }</div><div class="line">};</div></pre></td></tr></table></figure><p>封装了 inquirer,在终端提供一个交互式的配置过程。可以根据提供的<a href="http://yeoman.io/generator/" target="_blank" rel="external">API</a>,进行适当的修改,实现通用的脚手架。</p><ul><li>this.appname: 获取当前文件夹名称</li><li>this.user.git.name(): 获取全局git用户名</li><li>this.user.git.email(): 获取全局git邮箱</li><li>this.github.username(): 获取github用户名</li></ul><figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div><div class="line">18</div><div class="line">19</div><div class="line">20</div><div class="line">21</div><div class="line">22</div><div class="line">23</div><div class="line">24</div><div class="line">25</div></pre></td><td class="code"><pre><div class="line">const prompts = [{</div><div class="line"> type: 'confirm',</div><div class="line"> name: 'someAnswer',</div><div class="line"> message: 'Would you like to enable this option?',</div><div class="line"> default: true</div><div class="line">},{</div><div class="line"> type: 'input',</div><div class="line"> name: 'name',</div><div class="line"> message: 'Your project name',</div><div class="line"> default: this.appname</div><div class="line">},{</div><div class="line"> type: 'input',</div><div class="line"> name: 'description',</div><div class="line"> message: 'description',</div><div class="line">},{</div><div class="line"> type: 'input',</div><div class="line"> name: 'author',</div><div class="line"> message: 'author',</div><div class="line"> default: this.user.git.name()</div><div class="line">},{</div><div class="line"> type: 'input',</div><div class="line"> name: 'email',</div><div class="line"> message: 'email',</div><div class="line"> default: this.user.git.email()</div><div class="line">}];</div></pre></td></tr></table></figure><p>这里实现了让用户输入作者、项目名、email。</p><h4 id="writing-生成项目目录结构阶段"><a href="#writing-生成项目目录结构阶段" class="headerlink" title="writing 生成项目目录结构阶段"></a>writing 生成项目目录结构阶段</h4><p>通过this.fs,可以使用所有文件的方法,只用使用<a href="https://github.com/sboudrias/mem-fs-editor" target="_blank" rel="external">mem-fs editor </a>模块的接口</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div><div class="line">18</div><div class="line">19</div><div class="line">20</div><div class="line">21</div><div class="line">22</div><div class="line">23</div><div class="line">24</div><div class="line">25</div><div class="line">26</div><div class="line">27</div><div class="line">28</div><div class="line">29</div><div class="line">30</div><div class="line">31</div><div class="line">32</div><div class="line">33</div><div class="line">34</div><div class="line">35</div><div class="line">36</div><div class="line">37</div><div class="line">38</div><div class="line">39</div><div class="line">40</div><div class="line">41</div><div class="line">42</div><div class="line">43</div><div class="line">44</div><div class="line">45</div><div class="line">46</div><div class="line">47</div><div class="line">48</div><div class="line">49</div><div class="line">50</div><div class="line">51</div><div class="line">52</div><div class="line">53</div><div class="line">54</div><div class="line">55</div><div class="line">56</div><div class="line">57</div><div class="line">58</div><div class="line">59</div><div class="line">60</div><div class="line">61</div><div class="line">62</div></pre></td><td class="code"><pre><div class="line">writing() {</div><div class="line"> this.fs.copy(</div><div class="line"> this.templatePath('build/'),</div><div class="line"> this.destinationPath('build/')</div><div class="line"> );</div><div class="line"></div><div class="line"> this.fs.copy(</div><div class="line"> this.templatePath('config/'),</div><div class="line"> this.destinationPath('config/')</div><div class="line"> );</div><div class="line"></div><div class="line"> this.fs.copy(</div><div class="line"> this.templatePath('src/'),</div><div class="line"> this.destinationPath('src/')</div><div class="line"> );</div><div class="line"></div><div class="line"> this.fs.copy(</div><div class="line"> this.templatePath('mock/'),</div><div class="line"> this.destinationPath('mock/')</div><div class="line"> );</div><div class="line"></div><div class="line"> this.fs.copy(</div><div class="line"> this.templatePath('static/.gitkeep'),</div><div class="line"> this.destinationPath('static/.gitkeep')</div><div class="line"> );</div><div class="line"></div><div class="line"> this.fs.copy(</div><div class="line"> this.templatePath('.babelrc'),</div><div class="line"> this.destinationPath('.babelrc')</div><div class="line"> );</div><div class="line"></div><div class="line"> this.fs.copy(</div><div class="line"> this.templatePath('.eslintrc.js'),</div><div class="line"> this.destinationPath('.eslintrc.js')</div><div class="line"> );</div><div class="line"></div><div class="line"> this.fs.copyTpl(</div><div class="line"> this.templatePath('package.json'),</div><div class="line"> this.destinationPath('package.json'), {</div><div class="line"> title: this.props.name,</div><div class="line"> description: this.props.description,</div><div class="line"> author: this.props.author,</div><div class="line"> email: this.props.email</div><div class="line"> }</div><div class="line"> );</div><div class="line"></div><div class="line"> this.fs.copy(</div><div class="line"> this.templatePath('README.md'),</div><div class="line"> this.destinationPath('README.md')</div><div class="line"> );</div><div class="line"></div><div class="line"> this.fs.copy(</div><div class="line"> this.templatePath('.gitignore'),</div><div class="line"> this.destinationPath('.gitignore')</div><div class="line"> );</div><div class="line"></div><div class="line"> this.fs.copyTpl(</div><div class="line"> this.templatePath('index.html'),</div><div class="line"> this.destinationPath('index.html'),</div><div class="line"> { title: this.props.name }</div><div class="line"> );</div><div class="line"> }</div></pre></td></tr></table></figure><h4 id="copy-vs-copyTpl"><a href="#copy-vs-copyTpl" class="headerlink" title="copy() vs copyTpl()"></a>copy() vs copyTpl()</h4><p>他们的第一个参数都是模板文件路径,第二个参数是生成文件路径,不同之处在于copyTpl的第三个参数是一个对象,用于向模板中填充数据。copyTpl使用的是ejs模板引擎。</p><p>例如:./templates/index.html的文件内容是:</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div></pre></td><td class="code"><pre><div class="line"><!DOCTYPE html></div><div class="line"><html></div><div class="line"> <head></div><div class="line"> <meta charset="utf-8"></div><div class="line"> <title><%= title %></title></div><div class="line"> </head></div><div class="line"> <body></div><div class="line"> <div id="app"></div></div><div class="line"> <!-- built files will be auto injected --></div><div class="line"> </body></div><div class="line"></html></div></pre></td></tr></table></figure><figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div></pre></td><td class="code"><pre><div class="line">this.fs.copyTpl(</div><div class="line"> this.templatePath('index.html'),</div><div class="line"> this.destinationPath('index.html'),</div><div class="line"> {title: 'Templating with Yeoman'}</div><div class="line">);</div></pre></td></tr></table></figure><p>一但generator运行成功,index.html将会编译为:</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div></pre></td><td class="code"><pre><div class="line"><!DOCTYPE html></div><div class="line"><html></div><div class="line"> <head></div><div class="line"> <meta charset="utf-8"></div><div class="line"> <title>Templating with Yeoman</title></div><div class="line"> </head></div><div class="line"> <body></div><div class="line"> <div id="app"></div></div><div class="line"> <!-- built files will be auto injected --></div><div class="line"> </body></div><div class="line"></html></div></pre></td></tr></table></figure><p>json也同样适用上面的语法,配置package.json文件可以适应不同的项目。</p><h4 id="install-安装依赖"><a href="#install-安装依赖" class="headerlink" title="install 安装依赖"></a>install 安装依赖</h4><figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div></pre></td><td class="code"><pre><div class="line">// 3. 安装依赖</div><div class="line">install: function (){</div><div class="line"> this.npmInstall();</div><div class="line">}</div></pre></td></tr></table></figure><h3 id="安装测试"><a href="#安装测试" class="headerlink" title="安装测试"></a>安装测试</h3><p>如果你想观察自己配置的结果,可以使用<strong>npm link</strong> 命令,相当于全局安装了此脚手架,然后通过新建文件夹,且进入文件夹,<strong>运行yo</strong>,选择刚刚的脚手架,便可以测试。<br>例如:</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">mkdir vue-test && cd vue-test</div></pre></td></tr></table></figure><h3 id="发布generator"><a href="#发布generator" class="headerlink" title="发布generator"></a>发布generator</h3><p>可以将你创建的生成器发布到npm社区,便于自己和其他开发者使用。</p><p>generator-test/package.json中的name要在<a href="https://www.npmjs.com/没被创建过,才可以发布。" target="_blank" rel="external">https://www.npmjs.com/没被创建过,才可以发布。</a></p><p>如果没有npm的账号,可以通过npm adduser创建;<br>如果已有账号,通过 npm login 登陆。</p><p>登陆成功之后,在项目的根目录下,运行npm publish就可以发布了。如果更新后重新发布,需要修改package.json文件的版本号。</p><p>使用下述命令可以撤销发布,只有在发布包24小时内允许撤销发布的包。<br><figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">npm unpublish 包名</div></pre></td></tr></table></figure></p><h3 id="参考资料"><a href="#参考资料" class="headerlink" title="参考资料"></a>参考资料</h3><p>Yeoman官网:<a href="http://yeoman.io/" target="_blank" rel="external">http://yeoman.io/</a></p><p><img src="http://upload-images.jianshu.io/upload_images/2658726-6c440e5aa821e544.jpg?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240" alt="微信图片_20170817160210.jpg"></p>]]></content>
<summary type="html">
<h2 id="Yeoman是什么?"><a href="#Yeoman是什么?" class="headerlink" title="Yeoman是什么?"></a>Yeoman是什么?</h2><h3 id="Yeoman为何方神圣,说他有三头六臂一点都不夸张"><a href="#Yeoman为何方神圣,说他有三头六臂一点都不夸张" class="headerlink" title="Yeoman为何方神圣,说他有三头六臂一点都不夸张"></a>Yeoman为何方神圣,说他有三头六臂一点都不夸张</h3><p><img src="http://upload-images.jianshu.io/upload_images/2658726-d9f706a2c367f6f0.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240" alt="d5978593e4269f636f250dcdd8503590.png"></p>
<p>因为他<strong>由三部分组成</strong>:yo(脚手架工具)、grunt(等构建工具)、npm(等包管理器)。<br>
</summary>
<category term="前端" scheme="growthcoder.me/tags/%E5%89%8D%E7%AB%AF/"/>
</entry>
<entry>
<title>ubuntu下安装mysql</title>
<link href="growthcoder.me/2017/12/20/ubuntu%E4%B8%8B%E5%AE%89%E8%A3%85mysql/"/>
<id>growthcoder.me/2017/12/20/ubuntu下安装mysql/</id>
<published>2017-12-20T09:22:50.000Z</published>
<updated>2017-12-29T07:00:01.546Z</updated>
<content type="html"><![CDATA[<h4 id="安装mysql前配置"><a href="#安装mysql前配置" class="headerlink" title="安装mysql前配置"></a>安装mysql前配置</h4><ul><li><p>新买的服务器,端口都没有对外开放,需要对服务器安全组进行配置。</p></li><li><p>可以添加安全组规则,允许或者禁止安全组内的ECS实例对公网、内网的访问</p></li><li>VPC 网络:只需要设置出方向和入方向的规则,不区分私网和公网。</li><li>最后安全组如下:<br><img src="http://upload-images.jianshu.io/upload_images/2658726-83313bde30090e76.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240" alt="image.png"><ul><li>22 用于SSH远程连接到Linux实例</li><li>3306 实例作为 MySQL 服务器</li><li>80 实例作为网站或 Web 应用的服务器<a id="more"></a><h4 id="mysql安装"><a href="#mysql安装" class="headerlink" title="mysql安装"></a>mysql安装</h4></li></ul></li></ul><figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">sudo apt-get install mysql-server</div></pre></td></tr></table></figure><p>安装过程会弹出提示框,输入root用户的密码,我在这里设置密码为root</p><p>安装完成后,MySQL服务器会自动启动,我们检查MySQL服务器程序。</p><h4 id="mysql检查"><a href="#mysql检查" class="headerlink" title="mysql检查"></a>mysql检查</h4><figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div></pre></td><td class="code"><pre><div class="line"># 检查MySQL服务器系统进程</div><div class="line">-aux|grep mysql</div><div class="line">mysql 3205 2.0 0.5 549896 44092 ? Ssl 20:10 0:00 /usr/sbin/mysqld</div><div class="line">conan 3360 0.0 0.0 11064 928 pts/0 S+ 20:10 0:00 grep --color=auto mysql</div><div class="line"></div><div class="line"># 检查MySQL服务器占用端口</div><div class="line">netstat -nlt|grep 3306</div><div class="line">tcp 0 0 127.0.0.1:3306 0.0.0.0:* LISTEN</div><div class="line"></div><div class="line"># 通过启动命令检查MySQL服务器状态</div><div class="line">sudo /etc/init.d/mysql status</div><div class="line"># 通过系统服务命令检查MySQL服务器状态</div><div class="line">service mysql status</div></pre></td></tr></table></figure><h4 id="通过命令行客户端访问MySQL"><a href="#通过命令行客户端访问MySQL" class="headerlink" title="通过命令行客户端访问MySQL"></a>通过命令行客户端访问MySQL</h4><figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">mysql -uroot -p //password: root</div></pre></td></tr></table></figure><h4 id="修改MySQL服务器的配置"><a href="#修改MySQL服务器的配置" class="headerlink" title="修改MySQL服务器的配置"></a>修改MySQL服务器的配置</h4><h5 id="将字符编码设置为UTF-8"><a href="#将字符编码设置为UTF-8" class="headerlink" title="将字符编码设置为UTF-8"></a>将字符编码设置为UTF-8</h5><p>默认情况下,MySQL的字符集是latin1,因此在存储中文的时候,会出现乱码的情况,所以我们需要把字符集统一改成UTF-8。</p><p>用vi打开MySQL服务器的配置文件my.cnf</p><h5 id="让MySQL服务器被远程访问"><a href="#让MySQL服务器被远程访问" class="headerlink" title="让MySQL服务器被远程访问"></a>让MySQL服务器被远程访问</h5><p>默认情况下,MySQL服务器不允许远程访问,只允许本机访问,所以我们需要设置打开远程访问的功能。</p><p>用vi打开MySQL服务器的配置文件my.cnf</p><p>当我们修改完mysql权限相关的操作后一定要刷新权限表,使配置生效,执行<br><code>flush privileges;</code></p><p>第一种:是直接将原来的 <code>user='root' and host='localhost'</code> 记录的host修改成%或指定的ip<br>1) 将host设置为%表示任何ip都能连接mysql<br><code>update user set host='%' where user='root' and host='localhost';</code><br>2) 当然也可以将host指定为某个ip<br><code>update user set host='106.39.178.131' where user='root' and host='localhost';</code><br>3) 执行完以上语句,接着执行以下语句 ,刷新权限表,使配置生效<br><code>flush privileges</code></p><h4 id="参考文章"><a href="#参考文章" class="headerlink" title="参考文章"></a>参考文章</h4><p><a href="http://www.jb51.net/article/121173.htm" target="_blank" rel="external">mysql配置客户端访问</a></p><p><a href="http://blog.fens.me/linux-mysql-install/" target="_blank" rel="external">mysql安装</a></p>]]></content>
<summary type="html">
<h4 id="安装mysql前配置"><a href="#安装mysql前配置" class="headerlink" title="安装mysql前配置"></a>安装mysql前配置</h4><ul>
<li><p>新买的服务器,端口都没有对外开放,需要对服务器安全组进行配置。</p>
</li>
<li><p>可以添加安全组规则,允许或者禁止安全组内的ECS实例对公网、内网的访问</p>
</li>
<li>VPC 网络:只需要设置出方向和入方向的规则,不区分私网和公网。</li>
<li>最后安全组如下:<br><img src="http://upload-images.jianshu.io/upload_images/2658726-83313bde30090e76.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240" alt="image.png"><ul>
<li>22 用于SSH远程连接到Linux实例</li>
<li>3306 实例作为 MySQL 服务器</li>
<li>80 实例作为网站或 Web 应用的服务器
</summary>
<category term="Linux" scheme="growthcoder.me/tags/Linux/"/>
</entry>
<entry>
<title>JS实现排序算法</title>
<link href="growthcoder.me/2017/07/05/JS%E5%AE%9E%E7%8E%B0%E6%8E%92%E5%BA%8F%E7%AE%97%E6%B3%95/"/>
<id>growthcoder.me/2017/07/05/JS实现排序算法/</id>
<published>2017-07-05T09:02:40.000Z</published>
<updated>2017-07-05T09:08:48.926Z</updated>
<content type="html"><![CDATA[<p>总结下用js实现排序的几种普遍方法:</p><h4 id="1-冒泡排序"><a href="#1-冒泡排序" class="headerlink" title="1. 冒泡排序"></a>1. 冒泡排序</h4><h6 id="原理:"><a href="#原理:" class="headerlink" title="原理:"></a>原理:</h6><p>依次比较相邻的两个元素,如果后一个小于前一个,则交换,这样从头到尾一次,就将最大的放到了末尾。</p><h6 id="平均时间复杂度:O-n-2-。"><a href="#平均时间复杂度:O-n-2-。" class="headerlink" title="平均时间复杂度:O(n^2)。"></a>平均时间复杂度:O(n^2)。</h6><figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div><div class="line">18</div><div class="line">19</div></pre></td><td class="code"><pre><div class="line">function bubbleSort(arr) {</div><div class="line"> var temp;</div><div class="line"> if(arr.length == 0 || arr == null) {</div><div class="line"> return arr;</div><div class="line"> }</div><div class="line">// [1, 545, 55, 33, 23, 21, 3]</div><div class="line"> for(var i = 0; i < arr.length - 1; i++ ) {</div><div class="line"> for(j = 0; j < arr.length - i - 1; j++) {</div><div class="line"> if(arr[j] > arr[j+1]) {</div><div class="line"> temp = arr[j];</div><div class="line"> arr[j] = arr[j+1];</div><div class="line"> arr[j+1] = temp;</div><div class="line"> }</div><div class="line"> }</div><div class="line"> }</div><div class="line"> return arr;</div><div class="line">}</div><div class="line">//bubbleSort([1,34,23,34543,12,544,2])</div><div class="line">//[1, 2, 12, 23, 34, 544, 34543]</div></pre></td></tr></table></figure><a id="more"></a><h5 id="2-选择排序"><a href="#2-选择排序" class="headerlink" title="2. 选择排序"></a>2. 选择排序</h5><h6 id="原理:-1"><a href="#原理:-1" class="headerlink" title="原理:"></a>原理:</h6><p>每次找一个最大或者最小的数排在最开始,让其他数与之比较,进而选择是否交换位置。</p><h6 id="平均时间复杂度:O-n-2-。-1"><a href="#平均时间复杂度:O-n-2-。-1" class="headerlink" title="平均时间复杂度:O(n^2)。"></a>平均时间复杂度:O(n^2)。</h6><figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div><div class="line">18</div><div class="line">19</div><div class="line">20</div><div class="line">21</div><div class="line">22</div><div class="line">23</div><div class="line">24</div><div class="line">25</div><div class="line">26</div></pre></td><td class="code"><pre><div class="line">function selectSort (arr) {</div><div class="line"> var length = arr.length,</div><div class="line"> i,</div><div class="line"> j,</div><div class="line"> k,</div><div class="line"> temp;</div><div class="line"></div><div class="line"> if( length === 0 || arr === null ) {</div><div class="line"> return arr;</div><div class="line"> }</div><div class="line"></div><div class="line"> for(i = 0; i < length - 1; i++) {</div><div class="line"> k = i; //标记最小数</div><div class="line"> for(j = i + 1; j < length; j++) {</div><div class="line"> if(arr[k] > arr[j]) {</div><div class="line"> k = j;</div><div class="line"> }</div><div class="line"> temp = arr[k];</div><div class="line"> arr[k] = arr[i];</div><div class="line"> arr[i] = temp;</div><div class="line"> }</div><div class="line"> }</div><div class="line"> return arr;</div><div class="line">}</div><div class="line">//selectSort([1,43,2,324,23,534,2])</div><div class="line">//[1, 2, 2, 23, 43, 324, 534]</div></pre></td></tr></table></figure><h5 id="3-插入排序"><a href="#3-插入排序" class="headerlink" title="3. 插入排序"></a>3. 插入排序</h5><h6 id="原理:-2"><a href="#原理:-2" class="headerlink" title="原理:"></a>原理:</h6><p>将元素插入到有序序列中,一般将第一个元素视为有序序列,插入元素视为待排序列,与第一个元素进行比较插入。</p><h6 id="平均时间复杂度:O-n-2-。-2"><a href="#平均时间复杂度:O-n-2-。-2" class="headerlink" title="平均时间复杂度:O(n^2)。"></a>平均时间复杂度:O(n^2)。</h6><figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div><div class="line">18</div><div class="line">19</div><div class="line">20</div><div class="line">21</div><div class="line">22</div><div class="line">23</div><div class="line">24</div><div class="line">25</div></pre></td><td class="code"><pre><div class="line">function insertionSort (arr) {</div><div class="line"> var length = arr.length,</div><div class="line"> i,</div><div class="line"> j,</div><div class="line"> k,</div><div class="line"> preIndex, //当前元素的前一个元素的下标</div><div class="line"> current; //当前待排元素</div><div class="line"></div><div class="line"> if( length === 0 || arr === null ) {</div><div class="line"> return;</div><div class="line"> }</div><div class="line"></div><div class="line"> for(i = 1; i < length; i++) {</div><div class="line"> preIndex = i - 1;</div><div class="line"> current = arr[i];</div><div class="line"> while(preIndex >= 0 && current < arr[preIndex]) {</div><div class="line"> arr[preIndex+1] = arr[preIndex]; // 比current大的元素后移</div><div class="line"> preIndex--;</div><div class="line"> }</div><div class="line"> arr[preIndex+1] = current;//将current插入到数组中</div><div class="line"> }</div><div class="line"> return arr;</div><div class="line">}</div><div class="line">//insertionSort([23,34,2,43,3423,23,1123,3])</div><div class="line">//[2, 3, 23, 23, 34, 43, 1123, 3423]</div></pre></td></tr></table></figure><h5 id="4-快速排序"><a href="#4-快速排序" class="headerlink" title="4. 快速排序"></a>4. 快速排序</h5><h6 id="原理:-3"><a href="#原理:-3" class="headerlink" title="原理:"></a>原理:</h6><p>选择一个基准,将比基准小的,放在基准左边,将比基准大的,放在基准右边;一般选择中间的作为基准,之后两边再用递归的方法不断重复上述过程。</p><h6 id="平均时间复杂度:O-nlog-n-。"><a href="#平均时间复杂度:O-nlog-n-。" class="headerlink" title="平均时间复杂度:O(nlog(n))。"></a>平均时间复杂度:O(nlog(n))。</h6><figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div><div class="line">18</div><div class="line">19</div><div class="line">20</div><div class="line">21</div><div class="line">22</div><div class="line">23</div><div class="line">24</div><div class="line">25</div><div class="line">26</div><div class="line">27</div><div class="line">28</div></pre></td><td class="code"><pre><div class="line"></div><div class="line">function quickSort (arr) {</div><div class="line"> if( arr.length <= 1 ) {</div><div class="line"> return arr;</div><div class="line"> }</div><div class="line"></div><div class="line"> var left = [],</div><div class="line"> right = [],</div><div class="line"> i,</div><div class="line"> j,</div><div class="line"> k,</div><div class="line"> pivotIndex, // 参考点下标</div><div class="line"> pivot; //参考点</div><div class="line"></div><div class="line"> pivotIndex = Math.floor(arr.length / 2);</div><div class="line"> pivot = arr.splice(pivotIndex, 1)[0];//截取参考点</div><div class="line"></div><div class="line"> for(i = 0; i < arr.length; i++) {</div><div class="line"> if(arr[i] < pivot) {</div><div class="line"> left.push(arr[i]);</div><div class="line"> }else {</div><div class="line"> right.push(arr[i]);</div><div class="line"> }</div><div class="line"> }</div><div class="line"> return quickSort(left).concat([pivot], quickSort(right)); //递归进行上述规则排序 最后返回数组</div><div class="line">}</div><div class="line">//quickSort([12,3,2,434,21,32,23,11])</div><div class="line">//[2, 3, 11, 12, 21, 23, 32, 434]</div></pre></td></tr></table></figure><p><em>未完待续</em></p>]]></content>
<summary type="html">
<p>总结下用js实现排序的几种普遍方法:</p>
<h4 id="1-冒泡排序"><a href="#1-冒泡排序" class="headerlink" title="1. 冒泡排序"></a>1. 冒泡排序</h4><h6 id="原理:"><a href="#原理:" class="headerlink" title="原理:"></a>原理:</h6><p>依次比较相邻的两个元素,如果后一个小于前一个,则交换,这样从头到尾一次,就将最大的放到了末尾。</p>
<h6 id="平均时间复杂度:O-n-2-。"><a href="#平均时间复杂度:O-n-2-。" class="headerlink" title="平均时间复杂度:O(n^2)。"></a>平均时间复杂度:O(n^2)。</h6><figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div><div class="line">18</div><div class="line">19</div></pre></td><td class="code"><pre><div class="line">function bubbleSort(arr) &#123;</div><div class="line"> var temp;</div><div class="line"> if(arr.length == 0 || arr == null) &#123;</div><div class="line"> return arr;</div><div class="line"> &#125;</div><div class="line">// [1, 545, 55, 33, 23, 21, 3]</div><div class="line"> for(var i = 0; i &lt; arr.length - 1; i++ ) &#123;</div><div class="line"> for(j = 0; j &lt; arr.length - i - 1; j++) &#123;</div><div class="line"> if(arr[j] &gt; arr[j+1]) &#123;</div><div class="line"> temp = arr[j];</div><div class="line"> arr[j] = arr[j+1];</div><div class="line"> arr[j+1] = temp;</div><div class="line"> &#125;</div><div class="line"> &#125;</div><div class="line"> &#125;</div><div class="line"> return arr;</div><div class="line">&#125;</div><div class="line">//bubbleSort([1,34,23,34543,12,544,2])</div><div class="line">//[1, 2, 12, 23, 34, 544, 34543]</div></pre></td></tr></table></figure>
</summary>
<category term="前端" scheme="growthcoder.me/tags/%E5%89%8D%E7%AB%AF/"/>
</entry>
<entry>
<title>打开APP、扫码下载、唤醒本地APP方案总结</title>
<link href="growthcoder.me/2017/07/05/%E6%B4%BB%E5%8A%A8%E9%A1%B5%E4%B8%AD%E6%89%93%E5%BC%80APP%E3%80%81%E6%89%AB%E7%A0%81%E4%B8%8B%E8%BD%BDAPP%E6%96%B9%E6%A1%88%E6%80%BB%E7%BB%93/"/>
<id>growthcoder.me/2017/07/05/活动页中打开APP、扫码下载APP方案总结/</id>
<published>2017-07-05T09:00:07.000Z</published>
<updated>2018-01-26T01:41:53.404Z</updated>
<content type="html"><![CDATA[<p>最近做活动,需要用到在H5中打开/下载APP,PC端扫码下载APP相关业务,看似很小的一个功能,却蕴藏很大玄机。主要的难点在于在<strong>微信中唤醒APP</strong>,参考了很多产品的实现方式,对唱吧、今日头条等这几个平台颇为满意。最终我们团队,也实现了想要的功能。</p><h5 id="功能描述"><a href="#功能描述" class="headerlink" title="功能描述"></a>功能描述</h5><p>①Android端 微信中,依托应用宝实现打开、下载逻辑;<br> 浏览器中,本地没有APP,跳到指定下载页,有APP可以唤醒APP并打开指定活动页。<br>②IOS端 微信中,本地没有APP,依托应用宝进行下载,本地有APP,则可以在微信中唤醒APP,并且在APP中打开该活动页。<br>浏览器中,本地没有APP,跳iTunes下载,有APP,唤醒。<br><img src="http://upload-images.jianshu.io/upload_images/2658726-0ce0454a64231bf9.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240" alt=""><br><a id="more"></a></p><h3 id="一、方案流程"><a href="#一、方案流程" class="headerlink" title="一、方案流程"></a>一、方案流程</h3><p><img src="http://upload-images.jianshu.io/upload_images/2658726-28e51cf93152a907.jpg?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240" alt=""></p><table><thead><tr><th style="text-align:center">端</th><th style="text-align:center">难度</th><th style="text-align:center">使用技术</th><th style="text-align:center">能否跳转到指定页面</th></tr></thead><tbody><tr><td style="text-align:center">Android/微信</td><td style="text-align:center">简单</td><td style="text-align:center">应用宝链接</td><td style="text-align:center">否</td></tr><tr><td style="text-align:center">Android/浏览器</td><td style="text-align:center">简单</td><td style="text-align:center">Schema</td><td style="text-align:center">是</td></tr><tr><td style="text-align:center">Ios/微信</td><td style="text-align:center">复杂</td><td style="text-align:center">Universal Links</td><td style="text-align:center">是</td></tr><tr><td style="text-align:center">Ios/浏览器</td><td style="text-align:center">复杂</td><td style="text-align:center">Universal Links</td><td style="text-align:center">是</td></tr></tbody></table><h3 id="二、针对以上方案ios端的配置工作:"><a href="#二、针对以上方案ios端的配置工作:" class="headerlink" title="二、针对以上方案ios端的配置工作:"></a>二、针对以上方案ios端的配置工作:</h3><p>1、需要一台https服务器,且在微信端进行过安全认证,否则在安卓微信端容易导致页面跳转失败!!!目前使用的shui5的服务器在微信端没经过认证,所以实现逻辑不太一样</p><p>①apple-app-site-association文件<br>注意这个文件必须没有后缀名,文件名必须为apple-app-site-association!!!,请放置在https服务器的根目录,eg:(<a href="https://171edu.com/apple-app-site-association" target="_blank" rel="external">https://171edu.com/apple-app-site-association</a>);<br>②将download.html页面也放在之前的https服务器下 eg:(<a href="https://171edu.com/download.html" target="_blank" rel="external">https://171edu.com/download.html</a>)<br><figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div></pre></td><td class="code"><pre><div class="line">{</div><div class="line"> "applinks": {</div><div class="line"> "apps": [],</div><div class="line"> "details": [</div><div class="line"> {</div><div class="line"> "appID": "add your id",</div><div class="line"> "paths": [ "*" ]</div><div class="line"> },</div><div class="line"> {</div><div class="line"> "appID": "add your id",</div><div class="line"> "paths": [ "*" ]</div><div class="line"> }</div><div class="line"> ]</div><div class="line"> }</div><div class="line">}</div></pre></td></tr></table></figure></p><p>③之前的服务器(<a href="https://171edu.com" target="_blank" rel="external">https://171edu.com</a>) 要在ios的app中进行备案,<strong>当app拦截到这个domain时,会查看本地是否有app,如果有打开,并根据url后面的传参,打开相应的活动页面</strong>,如果本地没有app,则跳转至download页面,进行逻辑判断。</p><p>2、打开app在ios端的实现逻辑<br>iOS/微信<br>界面流程: 1. 扫描打开H5页面->点击打开应用按钮->打开一张不同域的网页,如存在则打开App/如不存在则打开App Store<br>实现流程: 1. 点击按钮 - >判断为微信/ios ->重定向到不同域的网页</p><p>iOS/浏览器<br>界面流程: 1. 打开H5页面->点击打开应用按钮->打开一张不同域的网页,如存在则打开App/如不存在则打开App Store<br>实现流程: 1. 点击按钮 - >判断为微信/ios ->重定向到不同域的网页</p><p>Itunes下载地址:<a href="https://itunes.apple.com/cn/app/id1127148565" target="_blank" rel="external">https://itunes.apple.com/cn/app/id1127148565</a></p><h3 id="三、Android实现"><a href="#三、Android实现" class="headerlink" title="三、Android实现"></a>三、Android实现</h3><p>Android/微信<br>界面流程:1.打开H5页面->点击打开应用按钮->载入应用宝链接(移动团队提供)->逻辑交由应用宝管理<br>实现流程: 1.点击按钮->判断是微信端/android->重定向当前页面至应用宝页面(移动团队提供)</p><p>Android/浏览器<br>界面流程: 1. 打开浏览器输入地址(或微信浏览器中以外部浏览器打开)->点击打开应用按钮->如已存在则打开程序/未存在开始下载<br>实现流程: 1. 点击按钮 ->判断是否浏览器端/android ->重定向android规定Schema字符串->同时定时器重定向到android下载路径</p><ol><li>应用宝地址:<br><a href="http://a.app.qq.com/o/simple.jsp?pkgname=com.winwin.tax" target="_blank" rel="external">http://a.app.qq.com/o/simple.jsp?pkgname=com.winwin.tax</a></li><li>Schema规则:<br>winwin://?type=activity&url=<br><a href="http://promotion.171edu.com/swpx/index.html" target="_blank" rel="external">http://promotion.171edu.com/swpx/index.html</a></li></ol><h3 id="四、相关页面代码"><a href="#四、相关页面代码" class="headerlink" title="四、相关页面代码"></a>四、相关页面代码</h3><p><em>//①download.html</em><br><figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div><div class="line">18</div><div class="line">19</div><div class="line">20</div><div class="line">21</div><div class="line">22</div><div class="line">23</div><div class="line">24</div><div class="line">25</div><div class="line">26</div><div class="line">27</div><div class="line">28</div><div class="line">29</div><div class="line">30</div><div class="line">31</div><div class="line">32</div><div class="line">33</div><div class="line">34</div><div class="line">35</div><div class="line">36</div><div class="line">37</div><div class="line">38</div><div class="line">39</div><div class="line">40</div><div class="line">41</div><div class="line">42</div><div class="line">43</div><div class="line">44</div></pre></td><td class="code"><pre><div class="line"><script></div><div class="line">window.onload = function() {</div><div class="line"> var env = {</div><div class="line"> agent: window.navigator.userAgent.toLowerCase(),</div><div class="line"> downURL: 'http://appdownload.17win.com/',</div><div class="line"> activityURL: 'winwin://?type=activity&url=http://promotion.171edu.com/swpx/index.html?edu',</div><div class="line"> yybaoURL: 'http://a.app.qq.com/o/simple.jsp?pkgname=com.winwin.tax',</div><div class="line"> iosURL: 'https://itunes.apple.com/cn/app/id1127148565',</div><div class="line"> eduURL: 'https://shui5.servyou.com.cn/download.html?utm_campaign=xueyuan&utm_medium=app&utm_source=ewm',(app的新版本此处链接改为https://171edu.com/...)</div><div class="line"></div><div class="line"> isWechat: function () {</div><div class="line"> return this.agent.match(/MicroMessenger/i) == 'micromessenger';</div><div class="line"> },</div><div class="line"> isAndroid: function () {</div><div class="line"> return this.agent.match(/android/i) == 'android';</div><div class="line"> },</div><div class="line"> isIphone: function () {</div><div class="line"> return this.agent.match(/iphone/i) == 'iphone';</div><div class="line"> },</div><div class="line"> init: function () {</div><div class="line"> if (env.isWechat()) {</div><div class="line"> //微信端都跳转到应用宝</div><div class="line"> window.location.href = env.yybaoURL;</div><div class="line"> } else {</div><div class="line"> if (env.isAndroid()) {</div><div class="line"> // 非微信安卓端实现思路</div><div class="line"> //首先唤醒本地app,如果本地有app,打开app,清除定时器,</div><div class="line"> //如果不存在app,则跳转到apk下载页面,下载app</div><div class="line"> timer = setTimeout(function () {</div><div class="line"> window.location.href = env.downURL;</div><div class="line"> }, 800);</div><div class="line"> window.location.href = env.activityURL;</div><div class="line"> window.onpagehide = function () {</div><div class="line"> clearTimeout(timer);</div><div class="line"> }</div><div class="line"> } else {</div><div class="line"> window.location.href = env.iosURL;</div><div class="line"> }</div><div class="line"> }</div><div class="line"> }</div><div class="line"> };</div><div class="line"> env.init();</div><div class="line">}</div><div class="line"></script></div></pre></td></tr></table></figure></p><p><em>//②app.html</em><br><figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div><div class="line">18</div><div class="line">19</div><div class="line">20</div><div class="line">21</div><div class="line">22</div><div class="line">23</div><div class="line">24</div><div class="line">25</div><div class="line">26</div><div class="line">27</div><div class="line">28</div><div class="line">29</div><div class="line">30</div></pre></td><td class="code"><pre><div class="line"><script></div><div class="line"> var env = {</div><div class="line"> agent: window.navigator.userAgent.toLowerCase(),</div><div class="line"> downURL: 'http://appdownload.17win.com/',</div><div class="line"> activityURL: 'winwin://?type=activity&url=http://promotion.171edu.com/swpx/index.html?edu',</div><div class="line"> yybaoURL: 'http://a.app.qq.com/o/simple.jsp?pkgname=com.winwin.tax',</div><div class="line"> // eduURL: 'https://171edu.com/download.html',</div><div class="line"> eduURL: 'https://shui5.servyou.com.cn/download.html?type=activity&url=http://promotion.171edu.com/swpx/index.html&utm_campaign=xueyuan&utm_medium=app&utm_source=ewm',</div><div class="line"> iosActivityURL: 'https://shui5.servyou.com.cn/download.html?type=activity&url=http://promotion.171edu.com/swpx/index.html',</div><div class="line"></div><div class="line"> isWechat: function(){</div><div class="line"> return this.agent.match(/MicroMessenger/i) == 'micromessenger';</div><div class="line"> },</div><div class="line"> isAndroid: function(){</div><div class="line"> return this.agent.match(/android/i) == 'android';</div><div class="line"> },</div><div class="line"> isIphone: function(){</div><div class="line"> return this.agent.match(/iphone/i) == 'iphone';</div><div class="line"> }</div><div class="line"> };</div><div class="line"> window.onload = function() {</div><div class="line"> var btn = document.getElementById('btn');</div><div class="line"> btn.click();</div><div class="line"> };</div><div class="line"></div><div class="line"> function goto () {</div><div class="line"> window.location.href = 'https://shui5.servyou.com.cn/download.html?utm_campaign=xueyuan&utm_medium=app&utm_source=ewm';</div><div class="line"> }</div><div class="line"></script></div><div class="line"><button style="opacity: 0;" id="btn" onclick=goto()></button></div></pre></td></tr></table></figure></p><p><em>//③活动页面中打开app相关js</em><br><em>////env.js</em><br><figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div><div class="line">18</div><div class="line">19</div><div class="line">20</div><div class="line">21</div><div class="line">22</div><div class="line">23</div><div class="line">24</div><div class="line">25</div><div class="line">26</div><div class="line">27</div><div class="line">28</div><div class="line">29</div><div class="line">30</div><div class="line">31</div></pre></td><td class="code"><pre><div class="line">var env = {</div><div class="line"> agent: window.navigator.userAgent.toLowerCase(),</div><div class="line"> downURL: 'http://appdownload.17win.com/',</div><div class="line"> activityURL: 'winwin://?type=activity&url=http://promotion.171edu.com/swpx/index.html?edu',</div><div class="line"> yybaoURL: 'http://a.app.qq.com/o/simple.jsp?pkgname=com.winwin.tax',</div><div class="line"> eduURL: 'https://171edu.com/download.html?type=activity&url=http://promotion.171edu.com/swpx/index.html&utm_campaign=xueyuan&utm_medium=app&utm_source=ewm',</div><div class="line"> shui5URL: 'https://shui5.servyou.com.cn/download.html?type=activity&url=http://promotion.171edu.com/swpx/index.html&utm_campaign=xueyuan&utm_medium=app&utm_source=ewm',</div><div class="line"> iosActivityURL: 'https://shui5.servyou.com.cn/download.html?type=activity&url=http://promotion.171edu.com/swpx/index.html',</div><div class="line"></div><div class="line"> isWechat: function(){</div><div class="line"> return this.agent.match(/MicroMessenger/i) == 'micromessenger';</div><div class="line"> },</div><div class="line"> isAndroid: function(){</div><div class="line"> return this.agent.match(/android/i) == 'android';</div><div class="line"> },</div><div class="line"> isIphone: function(){</div><div class="line"> return this.agent.match(/iphone/i) == 'iphone';</div><div class="line"> }</div><div class="line">};</div><div class="line">;$(function() {</div><div class="line"> $('.btn-app').bind('click', function() {</div><div class="line">//现在实现逻辑</div><div class="line"> if(env.isWechat() && env.isAndroid()){</div><div class="line"> window.location.href = env.yybaoURL;</div><div class="line"> }else {</div><div class="line"> window.location.href = env.shui5URL;</div><div class="line"> }</div><div class="line"> });</div><div class="line">//以后用171edu服务器,直接用下面的</div><div class="line">//window.location.href = env.eduURL;</div><div class="line">});</div></pre></td></tr></table></figure></p><h3 id="五、扫码下载实现逻辑"><a href="#五、扫码下载实现逻辑" class="headerlink" title="五、扫码下载实现逻辑"></a>五、扫码下载实现逻辑</h3><p>二维码为app.html,该页面主要是模拟触发点击按钮事件,进行跳转到download.html,之后进行下载业务处理</p><h6 id="本人的第一篇博客,感谢您阅读到了最后,文中如果有不足之处,还请批评指正。"><a href="#本人的第一篇博客,感谢您阅读到了最后,文中如果有不足之处,还请批评指正。" class="headerlink" title="本人的第一篇博客,感谢您阅读到了最后,文中如果有不足之处,还请批评指正。"></a>本人的第一篇博客,感谢您阅读到了最后,文中如果有不足之处,还请批评指正。</h6>]]></content>
<summary type="html">
<p>最近做活动,需要用到在H5中打开/下载APP,PC端扫码下载APP相关业务,看似很小的一个功能,却蕴藏很大玄机。主要的难点在于在<strong>微信中唤醒APP</strong>,参考了很多产品的实现方式,对唱吧、今日头条等这几个平台颇为满意。最终我们团队,也实现了想要的功能。</p>
<h5 id="功能描述"><a href="#功能描述" class="headerlink" title="功能描述"></a>功能描述</h5><p>①Android端 微信中,依托应用宝实现打开、下载逻辑;<br> 浏览器中,本地没有APP,跳到指定下载页,有APP可以唤醒APP并打开指定活动页。<br>②IOS端 微信中,本地没有APP,依托应用宝进行下载,本地有APP,则可以在微信中唤醒APP,并且在APP中打开该活动页。<br>浏览器中,本地没有APP,跳iTunes下载,有APP,唤醒。<br><img src="http://upload-images.jianshu.io/upload_images/2658726-0ce0454a64231bf9.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240" alt=""><br>
</summary>
<category term="前端" scheme="growthcoder.me/tags/%E5%89%8D%E7%AB%AF/"/>
</entry>
</feed>