-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathatom.xml
More file actions
324 lines (170 loc) · 172 KB
/
atom.xml
File metadata and controls
324 lines (170 loc) · 172 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
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
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
<title>Hexo</title>
<link href="/atom.xml" rel="self"/>
<link href="http://jetbn.github.io/"/>
<updated>2021-07-05T05:42:44.537Z</updated>
<id>http://jetbn.github.io/</id>
<author>
<name>jetBn</name>
</author>
<generator uri="https://hexo.io/">Hexo</generator>
<entry>
<title>深拷贝与浅拷贝</title>
<link href="http://jetbn.github.io/2021/07/05/%E8%B4%9D%E4%B8%8E%E6%B5%85%E6%8B%B7%E8%B4%9D/"/>
<id>http://jetbn.github.io/2021/07/05/%E8%B4%9D%E4%B8%8E%E6%B5%85%E6%8B%B7%E8%B4%9D/</id>
<published>2021-07-05T05:40:40.000Z</published>
<updated>2021-07-05T05:42:44.537Z</updated>
<content type="html"><![CDATA[<h1 id="深拷贝与浅拷贝"><a href="#深拷贝与浅拷贝" class="headerlink" title="深拷贝与浅拷贝"></a>深拷贝与浅拷贝</h1><ol><li><p><strong>关于<code>JavaScript</code>中的数据类型</strong></p><p> <code>JavaScript</code>中的数据类型分为两种大类:</p><ul><li><p>基础类型: <code>undefined</code>、<code>null</code>、<code>String</code>, <code>Number</code>、<code>Boolean</code>以及<code>ES6</code>引入的<code>Symbol</code>、<code>ES10</code>中的<code>BigInt</code></p></li><li><p>引用类型:<code>Object</code></p><p>相关的<code>JavaScript</code>对变量都是存储在栈内存、堆内存中的,而基础类型存在栈内存中,引用类型存在堆内存中。相关在的读写数据的时候,对于基础类型的是直接读写栈内存中的数据,引用类型是将一个内存地址保存在栈内存中,读写都是修改栈内存指向堆内存的地址。<br><br>比如以下代码</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><code class="hljs plain">let obj = {<br> name: 'joy',<br> age: 20<br>}<br>let num = 200<br></code></pre></td></tr></table></figure><p>这里我们的<code>obj</code>就是存在栈内存中而指向一个堆内存中的地址,<code>num</code>就是直接存在栈内存中的。</p><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><code class="hljs plain">let obj1 = obj<br>console.log(obj1 === obj) //true<br></code></pre></td></tr></table></figure><p>重新声明一个变量等于<code>obj</code>我们发现两个是相等的 <br><br>这里我们就是可以发现内存中只是新增一个栈内存指向堆内存中的地址而已,新的这个栈内存还是指向之前的堆内存地址,这种就是浅拷贝。当我们改变<code>obj</code>中的<code>name</code>发现<code>obj1</code>中的<code>name</code>也被改变了,所以我们其实就是改变堆内存的变量而已,又因为两个<code>obj</code>与<code>obj1</code>都是指向这个堆内存地址,所以就是我要改变一个另一个不会发生变化,深度的复制一个堆内存地址和不单单引用地址这种才叫深拷贝。</p></li></ul></li><li><p><strong>浅拷贝</strong></p><p> 由上述可知,浅拷贝只是复制了堆内存的引用地址,通常我们在业务中出现的浅拷贝是指复制引用对象的第一层,也就是基本类型复制新值,引用类型复制引用地址。我们使用的方案有循环赋值、扩展运算符、<code>Object.assign()</code><br></p> <img src="https://raw.githubusercontent.com/jetBn/blog/master/assets/md_images/ndeep.png"> <img src="https://raw.githubusercontent.com/jetBn/blog/master/assets/md_images/ndeep1.png"> 由上图代码示意结构我们发现我们分别使用`Object.assign()`和扩展运算符,浅拷贝了一份`obj`,分别为`obj1`和`obj2`当我们改变`obj`的第一层`name`的时候发现剩下的两个对象的`name`不会随这变化,当我们改变`obj`的第二层属性`child`的`name`的时候发现这三个对象都改变了,这就验证了上述所说的,浅拷贝就是单单复制了引用对象的第一层,而更深层次就没复制。</li></ol><ol start="3"><li><p><strong>深拷贝</strong></p><p> 同过上述的浅拷贝,我们应该能了解到深拷贝的含义,就是拷贝对象以及更深层次的子对象,并且拷贝后两个对象互不影响。基本类型复制新值,引用类型开辟新的堆内存,可使用<code>JSON.parse(JSON.stringify(obj))</code>、循环赋值。</p><ol><li><p>使用<code>JSON.parse(JSON.stringify(obj))</code></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><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></pre></td><td class="code"><pre><code class="hljs plain">let obj = {<br> name: 'joy',<br> friends: ['tom', 'lili'],<br> sex: Symbol('male'),<br> age: undefined,<br> child: {<br> num: 100<br> },<br> date: new Date(),<br> reg: /\.*/g<br>}<br><br>let obj1 = JSON.parse(JSON.stringify(obj))<br><br>console.log(obj === obj1) // false<br><br>obj.child.num = 200<br><br>console.log(obj.child.num, obj1.child.num) // 200, 100<br></code></pre></td></tr></table></figure><p> 这里我们分别打印<code>child</code>中的<code>num</code>值发现互不影响, 这说明了我们的拷贝成功了。最后我们看下分别打印<code>obj</code>和<code>obj1</code></p><pre><code><img src ="https://raw.githubusercontent.com/jetBn/blog/master/assets/md_images/ndeep2.png"/></code></pre><p> 发现了拷贝忽略我们的<code>undefined</code>、<code>symbol</code>、正则表达式,日期类型、方法。所以这也是这个方法拷贝不足的地方。</p></li><li><p><strong> 手写一个<code>deepClone</code></strong></p><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><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></pre></td><td class="code"><pre><code class="hljs plain">function deepClone(obj) {<br> if(obj === null || !obj) return obj<br> if(typeof obj !== 'object') return obj<br> if(obj instanceof RegExp) return new RegExp(obj)<br> if(obj instanceof Date) return new Date(obj)<br> let result = Array.isArray(obj)?[]:{};<br><br> for(let key in obj){<br> if(obj.hasOwnProperty(key)){<br> if(obj[key] && typeof obj[key] === "object"){<br> result[key] = deepClone(obj[key]);<br> }else{<br> result[key] = obj[key];<br> }<br> }<br> }<br> return result;<br>}<br></code></pre></td></tr></table></figure><p> 然后测试一下手写的代码,如图</p> <img src="https://raw.githubusercontent.com/jetBn/blog/master/assets/md_images/ndeep3.png"> <img src="https://raw.githubusercontent.com/jetBn/blog/master/assets/md_images/ndeep4.png"><p> 发现已经解决了 上面<code>JSON.stringify()</code>方法的不足, 就是<code>undefined</code>、<code>symbol</code>的无法拷贝。自己实现的深拷贝在一些复杂的对象中可能会出现一些问题,慢慢完善吧。但是基本的数据类型还都是可以实现拷贝的。</p></li></ol></li></ol>]]></content>
<summary type="html">
<h1 id="深拷贝与浅拷贝"><a href="#深拷贝与浅拷贝" class="headerlink" title="深拷贝与浅拷贝"></a>深拷贝与浅拷贝</h1><ol>
<li><p><strong>关于<code>JavaScript</code>中的数据类型</
</summary>
</entry>
<entry>
<title>Event Loop</title>
<link href="http://jetbn.github.io/2021/07/05/Event-Loop/"/>
<id>http://jetbn.github.io/2021/07/05/Event-Loop/</id>
<published>2021-07-05T03:54:44.000Z</published>
<updated>2021-07-05T04:01:00.853Z</updated>
<content type="html"><![CDATA[<h1 id="Event-Loop"><a href="#Event-Loop" class="headerlink" title="Event Loop"></a>Event Loop</h1><ol><li><p>关于javascirpt</p><p> javascript是一门单线程的语言, 虽然HTML5提出了web-work这样多线程解决方案,但是依旧没有改变javascript是单线程的本质。</p> <br> > 关于HMLT5的web-work 它其实就是将一些大量的计算代码交给web work去处理运行而不冻结用户界面,就是阻塞UI的渲染,但是子线程是完全受主线程的控制的,而且不能和页面进行交互,如获取元素, alert等,但是线程之间是可以进行传递数据的。</li><li><p>javascript的事件循环 </p><p> 由于js是单线程的,就是同一个时间只能做同一个事情,那么就引出问题了,我们访问一个页面的时候,比如有很多的图片、视频等等资源,加载的时候我们肯定不是在那等的,所以就引入两种任务 同步任务与异步任务。</p><p> <img src="https://raw.githubusercontent.com/jetBn/blog/master/assets/md_images/event_loop1.png" alt="Image text"></p><ol><li><p>同步和异步任务分别进入不同的场所分支。执行同步的任务都在主线程上执行,形成一个执行栈,而异步任务进入Event Table中注册并且返回回调函数</p></li><li><p>当这个异步任务有了运行的结果,Event Table会将这个回调函数移入Event Queue中进入等待的一种状态。</p></li><li><p>当主线程同步的任务执行完毕, 会去Event Queue中读取对应的函数,并且结束它的等待状态,让它进入主线程 行执行。</p></li><li><p>主线程不断重复着上面的3个步骤,也就是常说的Event loop事件循环。</p><blockquote><p>那怎么知道主线程执行栈为空的?<br> 其实js引擎在monitoring process 监控进程,不会不断的检查主线程执行栈是否为空,一旦为空,就会去Event Queue那里检查是否有等待被调用的函数。</p></blockquote></li></ol></li><li><p>任务队列解释</p> <br> >1. "任务队列"是一个事件的队列(也可以理解成消息队列), IO设备完成一项任务,就在"任务队列"中添加一个事件,表示相关的异步任务可以进入"执行栈"了。主线程读取"任务队列",就是读取里面有哪些事件 。 >2. "任务队列"中的事件,除了IO设备的事件以为,还包括一些用户产生的事件(比如鼠标点击,页面滚动等等)。只要指定过回调函数,这些事件发生时就会进入"任务队列",等待主线程的读取。 >3. 所谓"回调函数"(callback), 就是那些会被主线程挂起来的代码。异步任务必须指定回调函数,当主线程开始执行异步任务,就是执行对应的回调函数。 > 4. "任务队列"是一个先进先出的数据结构,排在前面的事件,优先被主线程读取。主线程的读取过程基本上自动的, 只要执行栈一清空,"任务队列"上的第一位事件就自动进入主线程。但是,由于存在后文提到的"定时器"功能,主线程首先要检查一下执行时间,某些时间只有到了规定的时间,才能返回主线程。 > 5. 读取到一个异步任务,首先是将异步任务放进事件表格(Event table)中,当放进事件表格中的异步任务完成某种事情或者达成某些条件(如setTimeout事件到了,鼠标点击了, 数据文件获取到了)之后,才将这些异步任务推入事件队列(Event Queue)中,这时候的异步任务才是执行栈中空闲的时候才能读取到的异步任务。</li><li><p>宏任务和微任务</p><p> 宏任务(macro-task)包括:setTimeout, setInterval, setImmediate, I/O, UI交互事件,可以理解是每次执行栈执行的代码就是一个宏任务<br> 微任务(micro-task)包括: Promises, Object.observe, MutationObserver, process.nextTick, 且process.nextTick优先级大于promise.then。可以理解是在当前 task 执行结束后立即执行的任务;</p> <br></li><li><p>宏任务、微任务的执行顺序</p><p> 主要的来讲就是先执行同步代码,遇到异步宏任务则将异步宏任务放入宏任务队列中,遇到异步微任务则将异步微任务放入微任务的队列中,当所有的同步代码执行完毕后,再将异步微任务从队列中调出来进入主线程执行,微任务执行完毕后再将异步宏任务从队列中调取出来到主线程中执行,一直循环直至所有任务执行完毕。</p> <br><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><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></pre></td><td class="code"><pre><code class="hljs plain">console.log('1');<br>async function async1() {<br> console.log('2');<br> await async2();<br> console.log('3');<br>}<br>async function async2() {<br> console.log('4');<br>}<br><br>process.nextTick(function() {<br> console.log('5');<br>})<br><br>setTimeout(function() {<br> console.log('6');<br> process.nextTick(function() {<br> console.log('7');<br> })<br> new Promise(function(resolve) {<br> console.log('8');<br> resolve();<br> }).then(function() {<br> console.log('9')<br> })<br>})<br><br>async1();<br><br>new Promise(function(resolve) {<br> console.log('10');<br> resolve();<br>}).then(function() {<br> console.log('11');<br>});<br>console.log('12');<br></code></pre></td></tr></table></figure><p> 第一轮时间循环流程: </p><ul><li><p>整体script代码作为一个宏任务进入主线,遇到console.log,输出1</p></li><li><p>遇到async1、async2函数声明, 声明暂时不用管</p></li><li><p>遇到process.nextTick(),其回调函数被分发到微任务Event Queue中,我们记为process1</p></li><li><p>遇到setTimeout, 它的回调被分发到宏任务Event Queue中。我们暂记为setTimeout1</p></li><li><p>执行async1,遇到console.log,输出2</p><br><p>当使用async定义的函数,当它被调用时,它返回的是一个Promise对象<br>而当await后面的表达式是一个Promise时,它的返回值实际上是Promise的回调reslove的参数</p><br></li><li><p>遇到await async2()调用,发现async2也是一个定义async的函数,所以直接执行返回4,同时返回了一个Promise。(这里返回的Promise被分配到微任务Event Queue中, 我们记为await1。await会让出线程,接下来就会跳出async1函数继续往下执行)</p></li><li><p>遇到Promise, new Promise直接执行,输出10。then被分发到微任务Event Queue中。记为then1</p></li><li><p>遇到console.log 输出12</p><table><thead><tr><th>宏任务Event Queue</th><th>微任务Event Queue</th></tr></thead><tbody><tr><td>setTimeout1</td><td>process1</td></tr><tr><td> </td><td>await1</td></tr><tr><td> </td><td>then1</td></tr></tbody></table><p>这是第一轮事件循环结束时候各个Event Queue的情况,此时已经输出 1 2 4 10 12</p><br>这时候存在process1,await1,then1三个微任务,进行依次执行</li><li><p>执行process1输出5</p></li><li><p>取到await1, 就是async1放进去的Promise,执行Promise时候发现了遇到了他的reslove函数,(这里这个reslove函数又会被放入微任务Event Queue中,记为await2,然后再次跳出async1函数继续执行下一个微任务)</p></li><li><p>执行then1输出11</p><table><thead><tr><th>宏任务Event Queue</th><th>微任务Event Queue</th></tr></thead><tbody><tr><td>setTimeout1</td><td>await2</td></tr></tbody></table><p>到这里输出1 2 4 10 12 5 11,然后我们的第一次微任务执行完毕了 新加入了一个await2的微任务在微任务Event Queue中。</p><br>此时我们进行执行await2微任务,<strong>它是async1放进去Promise的reslove回调</strong>,执行它(因为async2并没有返回值, 所以这个reslove的参数是undefined),此时await定义的这个Promise已经执行完毕并且返回了结果, 所以可以继续往下执行async1函数后面的任务了,那就是console.log(3), 输出 3<br>现在到这里我们第一轮事件循环结束了,此时,输出为 1 2 4 10 12 5 11 3<br>现在微任务执行完毕,进行第二轮的事件循环从setTimeout1宏任务开始</li><li><p>遇到console.log,输出6</p></li><li><p>遇到process.nextTick(),被分发到微任务Event Queue中去,记为process2</p></li><li><p>遇到new Promise立即执行后输出8,然后then被分发到微任务Event Queue,记为then2</p><table><thead><tr><th>宏任务Event Queue</th><th>微任务Event Queue</th></tr></thead><tbody><tr><td> </td><td>process2</td></tr><tr><td> </td><td>then2</td></tr></tbody></table><p>上述表格为二轮事件循环结束各个Event Queue的情况,这时候的情况是存在两个微任务process2和then2</p></li><li><p>执行process2, 输出7</p></li><li><p>执行then2,输出9</p><p>第二轮事件循环结束,第二轮结果为 6 8 7 9</p><br>所以最后的输出结果为1 2 4 10 12 5 11 3 6 8 7 9<br></li></ul></li><li><p>最后</p><p> 通过题目与理论的结合更深刻的理解javascirpt中Event loop</p></li></ol>]]></content>
<summary type="html">
<h1 id="Event-Loop"><a href="#Event-Loop" class="headerlink" title="Event Loop"></a>Event Loop</h1><ol>
<li><p>关于javascirpt</p>
<p> javascri
</summary>
</entry>
<entry>
<title>defineProperty与Proxy</title>
<link href="http://jetbn.github.io/2021/07/05/efineProperty%E4%B8%8EProxy/"/>
<id>http://jetbn.github.io/2021/07/05/efineProperty%E4%B8%8EProxy/</id>
<published>2021-07-05T03:54:31.000Z</published>
<updated>2021-07-05T03:56:31.594Z</updated>
<content type="html"><![CDATA[<h1 id="defineProperty与Proxy"><a href="#defineProperty与Proxy" class="headerlink" title="defineProperty与Proxy"></a>defineProperty与Proxy</h1><hr><h2 id="简述介绍"><a href="#简述介绍" class="headerlink" title="简述介绍"></a>简述介绍</h2><p> <code>defineProperty</code>是<code>ES5</code>对象<code>Object</code>的<code>api</code>,而<code>Proxy</code>则是<code>ES6</code>实现的的<code>api</code>都是可以实现数据监听与劫持,<code>Proxy</code>的表面意思上更像是一种代理的意思,它比<code>ES5</code>的 <code>defineProperty</code>更友好的监听对象中的属性,它代理的是整个对象,实现的监听,而<code>defineProperty</code>是遍历对象的每个属性,而且还不能监听数组的变化。<code>Vue</code>2.x的数据绑定就是用<code>defineProperty()</code>实现的,现在<code>Vue</code>3.x版本也是改用了<code>Proxy</code>来实现,所以就更深层次理解下这两个<code>api</code>。</p><h2 id="Object-defineProperty"><a href="#Object-defineProperty" class="headerlink" title="Object.defineProperty()"></a><code>Object.defineProperty()</code></h2><p>引用<code>MDN</code>上的相关介绍该方法会直接在一个对象上定义一个新属性,或者修改一个对象的现有属性,并返回此对象。</p><p><code>Object.defineProperty(obj, prop, descriptor)</code></p><ul><li>参数<code>obj</code>表示定义的对象,</li><li>参数<code>prop</code>表示要定义或修改的属性名称</li><li>参数<code>descriptor</code>表示要定义或修改的属性的相关描述符</li></ul><p>相关的属性描述符分别为<code>configurable</code>、<code>enumerable</code>、<code>value</code> 、 <code>writable</code>、<code>get</code> 、<code>set</code>这里就不一一单的说明了,重点还是<code>set</code>、<code>get</code>这两个。更详细的<a href="https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Object/defineProperty" target="_blank" rel="noopener">MDN</a>上有很详细的介绍文。<br>然后对数据的劫持都是由对象属性触发<code>getter</code>与<code>setter</code>,以及对象的属性发生变化的时候就行特定的操作。<br><img src="https://raw.githubusercontent.com/jetBn/blog/master/assets/md_images/definproperypng.png"></p><h1 id="Proxy"><a href="#Proxy" class="headerlink" title="Proxy"></a>Proxy</h1><p>Proxy就像名称一样理解成代理的意思,它其实就在目标对象之前架设了一层“拦截”,就是访问该对象都必须通过该拦截。因此提供了一种机制,可以对目标对象访问进行过滤和改写。</p><p><code>const proxyObj = new Proxy(target, handler)</code></p><ul><li>参数<code>target</code>表示要使用<code>Proxy</code>包装的目标对象(可以是任何类型的对象,包括原生数组,函数,甚至另一个代理)。</li><li><code>handler</code>一个通常以函数作为属性的对象,各属性中的函数分别定义了再执行各种操作时代理<code>proxyObj</code>的行为。</li></ul><p>相关<code>handler</code>对象的方法有<code>set</code>、<code>get</code>、<code>apply</code>、<code>definePropery</code>、<code>has</code>、<code>construct</code>等等,更详细的<a href="https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Proxy#handler_%E5%AF%B9%E8%B1%A1%E7%9A%84%E6%96%B9%E6%B3%95" target="_blank" rel="noopener">MDN</a>上有详细的介绍。我们主要是对比与<code>Object.defineProperty</code>的数据劫持。</p><img src="https://raw.githubusercontent.com/jetBn/blog/master/assets/md_images/proxypng.png"><h1 id="总结"><a href="#总结" class="headerlink" title="总结"></a>总结</h1><p><code>Proxy</code>与<code>Object.defineProperty()</code>都能实现对数据劫持,对比而下而<code>Proxy</code>更优,它可以直接监听对象而非属性,可以直接监听数组的变化,有很多的拦截方法,实例返回的是一个新对象,操作这个对象就可以实现对原对象数据的改变。而<code>Object.defineProperty()</code>只能遍历对象的属性进行修改操作。</p>]]></content>
<summary type="html">
<h1 id="defineProperty与Proxy"><a href="#defineProperty与Proxy" class="headerlink" title="defineProperty与Proxy"></a>defineProperty与Proxy</h1><
</summary>
</entry>
<entry>
<title>理解call()、apply()、bind()用法与区别</title>
<link href="http://jetbn.github.io/2021/07/05/call-%E3%80%81apply-%E3%80%81bind-%E7%94%A8%E6%B3%95%E4%B8%8E%E5%8C%BA%E5%88%AB/"/>
<id>http://jetbn.github.io/2021/07/05/call-%E3%80%81apply-%E3%80%81bind-%E7%94%A8%E6%B3%95%E4%B8%8E%E5%8C%BA%E5%88%AB/</id>
<published>2021-07-05T03:53:26.000Z</published>
<updated>2021-07-05T03:55:26.957Z</updated>
<content type="html"><![CDATA[<h1 id="理解call-、apply-、bind-用法与区别"><a href="#理解call-、apply-、bind-用法与区别" class="headerlink" title="理解call()、apply()、bind()用法与区别"></a>理解call()、apply()、bind()用法与区别</h1><hr><h2 id="相关介绍"><a href="#相关介绍" class="headerlink" title="相关介绍"></a>相关介绍</h2><p>这三个函数都是在<code>JavaScript</code>中改变函数调用的<code>this</code>指向的,具体的可能就是参数传递不同。</p><h2 id="call-方法"><a href="#call-方法" class="headerlink" title="call()方法"></a><code>call()方法</code></h2><p>该方法使用一个指定的<code>this</code>值和给出一个或多个参数来调用一个函数,他们都是<code>Function</code>对象的方法,每个函数都能调用。它可传递两个参数第一个为在<code>function</code>函数运行时使用的<code>this</code>值,第二个为指定的参数。</p><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><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></pre></td><td class="code"><pre><code class="hljs plain">let obj = {age: 11}<br><br>function fun(arg) {<br> console.log(arg)<br> console.log(this.age)<br>}<br>fun('lili') //直接调用 此时的this指向window所以 第一行打印`lili`第二行打印`undefined`<br><br>// 使用call改变函数调用运行时的this<br><br>fun.call(obj, 'lili') // 分别打印 lili 11<br><br>// 多个参数<br><br>function fun(arg) {<br> console.log(arguments) <br> console.log(this.age) <br>}<br><br>fun.call(obj, 'lili', '20') // 此时的打印分别是arguments中两个参数 lili以及 20,以及11<br></code></pre></td></tr></table></figure><h2 id="apply-方法"><a href="#apply-方法" class="headerlink" title="apply()方法"></a><code>apply()方法</code></h2><p>该方法其实跟<code>call()</code>方法是一样的就是传递的参数不一样,它的第二个参数为一个数组(或类似数组对象)</p><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><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><code class="hljs plain">let obj = {age: 11}<br><br>function fun() {<br> console.log(arguments)<br> console.log(this.age)<br>}<br><br>fun.apply(obj, ['lili', '20']) //此时打印个跟上述call传递多个参数的时候是一致的<br></code></pre></td></tr></table></figure><p>通过此两个案例我们可以清楚发现,<code>call()</code>和<code>apply()</code>函数的第一个参数都是改变<code>this</code>的指向,而<code>call()</code>和<code>apply()</code>的区别仅仅就是<code>call()</code>传递参数需要一项一项的传, 但是<code>apply()</code>直接通过一个数组传递就好了。</p><h2 id="bind-方法"><a href="#bind-方法" class="headerlink" title="bind()方法"></a><code>bind()方法</code></h2><p>该方法与<code>apply()</code>和<code>call()</code>很相似,也是可以改变函数体内的<code>this</code>指向的,它是创建一个新的函数, 在<code>bind()</code>被调用的时候,这个新函数的<code>this</code>被指定为<code>bind()</code>的第一个参数,而其余的的参数将作为新函数的参数,供调用时使用。</p><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><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></pre></td><td class="code"><pre><code class="hljs plain">let obj = {age: 11}<br><br>function fun() {<br> console.log(this.age)<br>}<br><br>fun() // undefined<br><br>let newFun = fun.bind(obj)<br><br>newFun() // 11<br></code></pre></td></tr></table></figure><p>由上面的运行代码在<code>bind()</code>函数改变<code>this</code>的指向之前我们打印的是<code>undefined</code>,因为我此时的<code>this</code>指向是<code>window</code>在此里面没有定义<code>age</code>的属性,所以我们答应的是<code>undefined</code>,当我们通过<code>bind()</code>函数改变<code>this</code>传入<code>obj</code>此时又新生成一个<code>newFun()</code>函数,当我们调用此函数的时候,此时的<code>this</code>指向就是<code>obj</code>了,所以我们打印了 11。</p><h2 id="bind-apply-call-的共同和不同点:"><a href="#bind-apply-call-的共同和不同点:" class="headerlink" title="bind(), apply(), call()的共同和不同点:"></a>bind(), apply(), call()的共同和不同点:</h2><ul><li>三个都是<code>Fucntion</code>对象的方法都是改变函数的<code>this</code>对象的指向的;</li><li>三个函数的第一个参数都是<code>this</code>要指向的对象,也就是想指定的上下文,上下文就是指调用函数的那个对象。(如果没有传以及<code>null</code>都是指向<code>window</code>);</li><li>三个都可以传递参数,<code>apply()</code>是数组,<code>call()</code>与<code>bind()</code>都是有序传入参数;</li><li><code>bind</code>是返回函数,便于稍后调,而<code>apply()</code>与<code>call()</code>都是立即执行</li></ul><h2 id="最后分别手动实现"><a href="#最后分别手动实现" class="headerlink" title="最后分别手动实现"></a>最后分别手动实现</h2><ol><li><code>call()</code>函数</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><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></pre></td><td class="code"><pre><code class="hljs plain">Function.prototype.myCall = function(context, ...args) {<br> if(typeof context === 'object') {<br> context = context || window<br> } else {<br> context = Object.create(null)<br> }<br><br> let fn = Symbol() // 保证fn的唯一性<br><br> context[fn] = this<br><br> let result = context[fn](...args)<br><br> delete context[fn]<br><br> return result<br>}<br></code></pre></td></tr></table></figure><ol start="2"><li><code>apply()</code>函数</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><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></pre></td><td class="code"><pre><code class="hljs plain">Function.prototype.myApply = function(context, arg) {<br> if(typeof context === 'object') {<br> context = context || window<br> } else {<br> context = Object.create(null)<br> }<br> let fn = Symbol() // 保证fn的唯一性<br><br> context[fn] = this<br><br> let result = context[fn](...args)<br> <br> delete context[fn]<br><br> return result<br>}<br></code></pre></td></tr></table></figure><ol start="3"><li><code>bind()</code>函数</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><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></pre></td><td class="code"><pre><code class="hljs plain">Function.prototype.myBind = function(context) {<br> const that = this<br> const args = [...arguments].slice(1)<br> const tempFun = function() {}<br> const resultFun = function() {<br> const nextArgs = [...arguments]<br> return that.apply(this instanceof resultFun ? this : context, [...args, ...nextArgs])<br> }<br> tempFun.prototype = that.prototype<br> resultFun.prototype = new tempFun()<br> return resultFun<br>}<br></code></pre></td></tr></table></figure>]]></content>
<summary type="html">
<h1 id="理解call-、apply-、bind-用法与区别"><a href="#理解call-、apply-、bind-用法与区别" class="headerlink" title="理解call()、apply()、bind()用法与区别"></a>理解call()
</summary>
</entry>
<entry>
<title>原型与原型链</title>
<link href="http://jetbn.github.io/2021/07/05/%E5%9E%8B%E4%B8%8E%E5%8E%9F%E5%9E%8B%E9%93%BE/"/>
<id>http://jetbn.github.io/2021/07/05/%E5%9E%8B%E4%B8%8E%E5%8E%9F%E5%9E%8B%E9%93%BE/</id>
<published>2021-07-05T03:52:54.000Z</published>
<updated>2021-07-05T03:53:01.675Z</updated>
<content type="html"><![CDATA[<h1 id="原型"><a href="#原型" class="headerlink" title="原型"></a>原型</h1><hr><h2 id="前言介绍"><a href="#前言介绍" class="headerlink" title="前言介绍"></a>前言介绍</h2><p>每个函数都有<code>prototype</code>属性, 除了<code>Function.prototype.bind()</code>,该属性最终指向原型。每个对象都有<code>_proto_</code>属性, 指向了创建该对象构造函数的原型,其实这个属性指向了<code>[[prototype]]</code>,但是由于<code>[[prototype]]</code>是内部属性,所以并不能访问到,所以使用了<code>_proto_</code>来访问。<br><br>对象可以通过<code>_proto_</code>来寻找不属于改对象的属性,<code>_proto_</code>将对象连接起来组成了原型链。</p><div align="center"><img src="https://raw.githubusercontent.com/jetBn/blog/master/assets/md_images/prototype.png"></div><h2 id="prototype属性"><a href="#prototype属性" class="headerlink" title="prototype属性"></a><code>prototype</code>属性</h2><p>这个是一个显式的原型属性,只用函数才拥有,基本上所有函数都有这个属性,但是有一个另外</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs plain">const fun = Function.prototype.bind()<br></code></pre></td></tr></table></figure><p>这个<code>fun</code>函数的创建就是没有<code>prototype</code>属性的。</p><p><strong><code>prototype</code>的产生</strong></p><p>当我们声明一个函数的时候自动被创建的。</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs plain">function fun() {}<br></code></pre></td></tr></table></figure><p>通过方为<code>fun.prototype</code>我们能看到有一个<code>constructor</code>方法,其就是对应的构造函数也就是<code>fun</code></p><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><code class="hljs plain">fun.prototype<br>{constructor: ƒ}<br></code></pre></td></tr></table></figure><p><strong>constructor</strong></p><p><code>constructor</code>是一个公有的而且不可枚举的属性, 一旦我们改变了函数的<code>prototype</code>, 那么新的对象就没有这个属性了, 但是我们可以通过原型链取到。</p><img src="https://raw.githubusercontent.com/jetBn/blog/master/assets/md_images/constructor.png"><p>这个属性的作用:</p><ul><li>让实例对象知道是什么函数构造了它</li><li>如果想给某些类库中的构造函数增加一些自定义的方法,就可以通过 <code>xx.constructor.method</code> 来扩展</li></ul><h2 id="proto-属性"><a href="#proto-属性" class="headerlink" title="_proto_属性"></a>_proto_属性</h2><p>这是每个对象有的隐式原型属性,指向了创建该对象的构造函数的原型。其实这个属性指向了<code>[[prototype]]</code>,但是<code>[[prototype]]</code>是内部的属性,我们并不能访问到,所以使用了<code>_proto_</code>来访问。</p><p>因为在<code>js</code>中没有类的概念,为了实现类似的继承方式, 通过<code>_proto_</code>将对象和原型联系起来组成原型链,得以让对象可以访问到不属于自己的属性。</p><p><strong><code>_proto_</code>的产生</strong><br>从顶部的图我们看到, 当我是用<code>new</code>关键字的时候生成的对象就有了<code>_proto_</code>属性了。</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><code class="hljs plain">functon Fun() {}<br><br>// 这个函数是Function的实例对象<br>// functon其实就是一个语法糖<br>// 内部调用了 new Function()<br></code></pre></td></tr></table></figure><p>所以可以说, 在<code>new</code>的过程中就是向定对象添加了<code>_proto_</code>属性并且链接到构造函数的原型上了</p><p>一个<code>new</code>的过程</p><ul><li>新生成了一个对象</li><li>链接到原型</li><li>绑定this</li><li>返回新对象</li></ul><p>手动实现一个new的过程</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><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></pre></td><td class="code"><pre><code class="hljs plain">function cusNew() {<br> // 创建一个对象<br> let obj = new Object()<br> // 获取构造函数<br> const Con = [].shift.call(arguments)<br> // 链接到原型<br> obj._proto_ = Con.prototype<br> // 绑定this执行构造函数<br> let result = Con.apply(obj, arguments)<br><br> return typeof result === 'function' ? result : obj<br>}<br></code></pre></td></tr></table></figure><p>对于实力对象来说,都是通过<code>new</code>来产生的,不论是 <code>funciton Fun()</code>还是 <code>let obj = { name:'js' }</code></p><p>对于创建一个对象来说,创建最好都是用字面量的方式来创建。 因为当你 <code>new Object()</code>的方式创建对象需要通过作用域链一层层找到<code>Object</code>,但是你使用字面的方式就没有这个问题,性能更高。</p><p><strong><code>Function._proto_ === Function.prototype</code></strong></p><p>对于对象来说,<code>xx._proto_.contrcutor</code> 是该对象的构造函数,但是在上面的图中我们发现<code>Function._proto_ === Function.prototype</code>,难道这代表<code>Function</code>自己创建了自己?</p><p>答案是否定的。<code>Function.prototype</code>是由引擎来创建的。</p><p>从上图中我们可以发现,所有的对象都可以通过原型链最终找到<code>Object.prototype</code>,虽然<code>Object.prototype</code>也是一个对象,但是这个对象不是<code>Object</code>创造的,而是引擎自己创建了<code>Object.prototype</code>。所以可以这样说,所以实例都是对象,但是对象不一定都是实例。</p><p>我们通过<code>Function.prototype</code>在浏览器将这个对象打印出来,会发现其实是一个函数。</p><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><code class="hljs plain">Function.prototype<br>ƒ () { [native code] }<br></code></pre></td></tr></table></figure><p>由于<code>Function.prototype</code>和<code>Object.prototype</code>都是是由引擎创建的,它首先创建了<code>Function.prototype</code>,然后创建<code>Object.prototype</code>并且通过<code>_proto_</code>将两者联系起来。这里就很好解释了为什么<code>let fun = Function.prototype.bind()</code>创建没有<code>prototype</code>属性。因为<code>Function.prototype</code>是由于引擎创建出来的对象,引擎认为不需要给这个对象添加<code>prototype</code>属性。</p><p><strong>所以,不是所有函数都是<code>new Function()</code>产生的。</strong></p><p>有了<code>Function.prototype</code>以后才有了<code>fucntion Function()</code>,然后其他的构造函数都是<code>fucntion Function()</code>生成的。</p><p>所以<code>Function.__proto__ === Function.prototype</code>这个问题理解就是,其他所有构造函数都可以通过原型链找到<code>Function.prototype</code>, 并且<code>function Function()</code>本质也是一个函数,为了不产生混乱就将<code>function Function()</code>的<code>__proto__</code>联系到了<code>Function.prototype</code>上。</p><h2 id="总结"><a href="#总结" class="headerlink" title="总结"></a>总结</h2><ul><li><code>Object</code>是所有对象的爸爸,所有对象都可以通过<code>_proto_</code>找到它。</li><li><code>Function</code>是所有函数的爸爸,所有函数都可以通过<code>_proto_</code>找到它。</li><li><code>Function.prototype</code>和<code>Object.prototype</code>是两个特殊的对象, 是由引擎创建的。</li><li>除了以上两个对象,其他对象都是通过构造器<code>new</code>出来的。</li><li>函数的<code>prototype</code>是一个对象,也就是原型。</li><li>对象的<code>_proto</code>指向原型,<code>_proto_</code>将对象和原型连接起来组成了原型链。</li></ul>]]></content>
<summary type="html">
<h1 id="原型"><a href="#原型" class="headerlink" title="原型"></a>原型</h1><hr>
<h2 id="前言介绍"><a href="#前言介绍" class="headerlink" title="前言介绍"></a>前言
</summary>
</entry>
<entry>
<title>数组常用方法</title>
<link href="http://jetbn.github.io/2020/07/28/%E7%BB%84%E5%B8%B8%E7%94%A8%E6%96%B9%E6%B3%95/"/>
<id>http://jetbn.github.io/2020/07/28/%E7%BB%84%E5%B8%B8%E7%94%A8%E6%96%B9%E6%B3%95/</id>
<published>2020-07-28T08:53:00.000Z</published>
<updated>2020-07-28T08:55:50.637Z</updated>
<content type="html"><![CDATA[<h1 id="JavaScript中数组常用方法"><a href="#JavaScript中数组常用方法" class="headerlink" title="JavaScript中数组常用方法"></a>JavaScript中数组常用方法</h1><hr><h2 id="前言介绍"><a href="#前言介绍" class="headerlink" title="前言介绍"></a>前言介绍</h2><p>在日常开发中我们经常都会使用到数组的一些操作,比如增、删、循环等等。自己对此数组的一些方法(常用以及不常用的)整理一遍,特此记录一下。</p><ol><li><p><code>arr.push()</code>从数组的后面添加元素, 返回值为数组的长度</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></pre></td><td class="code"><pre><code class="hljs plain">let arr = []<br>console.log(arr.push(1)) // 1<br>console.log(arr) // [1]<br></code></pre></td></tr></table></figure></li><li><p><code>arr.pop()</code>从数组的后面删除元素,只能删除一个,返回值是删除的元素</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></pre></td><td class="code"><pre><code class="hljs plain">let arr = [1, 2, 3]<br>console.log(arr.pop()) // 3<br>console.log(arr) // [1, 2]<br></code></pre></td></tr></table></figure></li><li><p><code>arr.shift()</code>从数组前面删除一个元素,只能删除一个,返回值是删除的元素</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></pre></td><td class="code"><pre><code class="hljs plain">let arr = [1, 2, 3]<br>console.log(arr.shift()) // 1<br>console.log(arr) // [2, 3]<br></code></pre></td></tr></table></figure></li><li><p><code>arr.unshift()</code>从数组前面添加一个元素,返回值是数组的长度</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></pre></td><td class="code"><pre><code class="hljs plain">let arr = [2, 3]<br>console.log(arr.unshift(1)) // 3<br>console.log(arr) // [1, 2, 3]<br></code></pre></td></tr></table></figure></li><li><p><code>arr.concat()</code>连接两个数组,返回值为连接后的新数组(其实就是合并)参数可以数值或者数组</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></pre></td><td class="code"><pre><code class="hljs plain">let arr1 = [1, 2]<br>let arr2 = [3, 4]<br>console.log(arr1.concat(arr2)) // [1, 2, 3, 4]<br></code></pre></td></tr></table></figure></li><li><p><code>arr.splice(i, n, item1, item2, ... )</code> 删除从i(索引)开始之后的那个元素。返回值删除的元素的数组</p><p> 参数: <code>i</code> 表示索引,<code>n</code>表示个数(可选参数), <code>item1, item2, ...</code> 向数组添加项(可选参数)</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><code class="hljs plain">let arr = [1, 2, 3, 4, 5, 6, 7]<br>console.log(arr.splice(2,1)) // [3]<br>console.log(arr) // [1, 2, 4, 5, 6, 7]<br>console.log(arr.splice(2,1, 3, 4)) // [3, 4]<br>console.log(arr) // [1, 2, 3,4, 4, 5, 6, 7]<br></code></pre></td></tr></table></figure></li><li><p><code>str.split(s, n)</code>将字符串分割成数组<br> 参数<code>s</code>字符串或正则表达式(必需),<code>n</code>返回数组的最大长度(可选参数),不传则不规定数组的长度,根据字符分割。</p> <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><code class="hljs plain">let str = '1234'<br>console.log(str.split('')) // [1, 2, 3, 4]<br></code></pre></td></tr></table></figure></li><li><p><code>arr.join(separator)</code>将数组的所有元素(或者类数组)的所有元素链接成一个字符串并且返回这个字符串<br>参数:<code>separator</code>(可选)指定一个字符串分隔每个元素,默认为逗号(,)</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><code class="hljs plain">let arr = ['jon', 'tom', 'wang']<br>console.log(arr.join()) // jon,tom,wang<br>console.log(elements.join('')) // jontomwang<br>console.log(elements.join('-')); // jon-tom-wang<br></code></pre></td></tr></table></figure></li><li><p><code>arr.sort()</code>将数组进行排序,返回值是排好的数组,默认是按照最左边的数字进行排序,不是按照数组大小排序。</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><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><code class="hljs plain">let arr = [2, 10, 1, 4, 22, 3]<br>console.log(arr.sort()) // [1, 10, 2, 22, 3, 4]<br><br>let arr1 = arr.sort((a, b) => a - b)<br>console.log(arr1) // [1, 2, 3, 4, 10, 22]<br><br>let arr2 = arr.sort((a, b) => a - b)<br>console.log(arr2) // [22, 10, 4, 3, 2, 1]<br></code></pre></td></tr></table></figure></li><li><p><code>arr.reverse()</code>将数组进行反转,返回值是反转后的数组</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></pre></td><td class="code"><pre><code class="hljs plain">let arr = [1, 2, 3, 4]<br>console.log(arr.reverse()) // [4, 3, 2, 1]<br>console.log(arr) // [4, 3, 2, 1]<br></code></pre></td></tr></table></figure></li><li><p><code>arr.slice(start, end)</code>切去索引开始值start到索引值end的数组(浅拷贝),不包含end的索引的值,返回值是切出来的数组, 原始数组不会被改变。</p><p>参数<code>start</code>(可选),表示开始的索引值(不传为0),<code>end</code>(可选)表示结束的索引值(不传为数组的最后一项)。</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></pre></td><td class="code"><pre><code class="hljs plain">let arr = [1, 2, 3, 4, 5, 6]<br>console.log(arr.slice(1, 3)) // [2, 3]<br>console.log(arr) // [1, 2, 3, 4, 5, 6]<br></code></pre></td></tr></table></figure></li><li><p><code>arr.forEach(callback)</code>遍历数组, 无<code>return</code>即使有也不会返回任何值,并且不会影响原来的数组<br>callback的参数: </p><ul><li>value –当前索引的值,</li><li>index –索引, (可选)</li><li>array –原数组 (可选)<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></pre></td><td class="code"><pre><code class="hljs plain">let arr = [1, 2, 3, 4]<br>arr.forEach( (value, index, array)=>{<br> console.log(`value:${value} index:${index} array:${array}`)<br>})<br><br>/* value:1 index:0 array:1,2,3,4<br> value:2 index:1 array:1,2,3,4<br> value:3 index:2 array:1,2,3,4<br> value:4 index:3 array:1,2,3,4 */<br><br>let arr = [1, 2, 3, 4]<br>arr.forEach((value, index, array) => {<br> value = value * 2<br> console.log(`value:${value} index:${index} array:${array}`)<br>})<br><br>/* value:2 index:0 array:1,2,3,4<br> value:4 index:1 array:1,2,3,4<br> value:6 index:2 array:1,2,3,4<br> value:8 index:3 array:1,2,3,4 */<br><br>let arr = [1, 2, 3, 4]<br><br>let resArr = arr.forEach((value, index, array) => {<br> arr[index] = value * 2<br> return arr<br>})<br><br>console.log(resArr) // undefined<br>console.log(arr) // [2, 4, 6, 8]<br></code></pre></td></tr></table></figure></li></ul></li><li><p><code>arr.map(callback)</code>映射数组(遍历数组),有<code>return</code>返回一个新数组<br>callback的参数: </p><ul><li>value –当前索引的值,</li><li>index –索引, (可选)</li><li>array –原数组 (可选)<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></pre></td><td class="code"><pre><code class="hljs plain">let arr = [1, 2, 3, 4]<br>arr.map((value, index, array)=> {<br> value= value * 2<br> console.log(`value:${value} index:${index} array:${array}`)<br>})<br><br>/* value:2 index:0 array:1,2,3,4<br> value:4 index:1 array:1,2,3,4<br> value:6 index:2 array:1,2,3,4<br> value:8 index:3 array:1,2,3,4 */<br><br>let arr1 = [1, 2, 3, 4]<br>let resArr = arr1.map((value, index, array)=> {<br> item = item * 2<br> return item<br>})<br><br>console.log(arr1) // [1, 2, 3, 4]<br>console.log(resArr) // [2, 4, 6, 8]<br></code></pre></td></tr></table></figure><blockquote><ol><li><code>arr.forEach()</code>是和 <code>for</code>循环一样的,是代替<code>for</code>。<code>arr.map()</code>是修改数组其中的数据,并返回新的数据。</li><li><code>arr.forEach()</code>没有<code>return</code> 返回值,而<code>arr.map()</code>有</li></ol></blockquote></li></ul></li><li><p><code>arr.filter(callback)</code>过滤数组,返回一个满足条件的数组(数组中的每一个元素都执行一遍<code>callback</code>)<br>callback的参数: </p><ul><li>value –当前索引的值,</li><li>index –索引, (可选)</li><li>array –原数组 (可选)</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></pre></td><td class="code"><pre><code class="hljs plain">let arr = [1, 2, 3, 4]<br>let resArr = arr.filter((value, index) => value < 3)<br>console.log(resArr) // [1, 2]<br></code></pre></td></tr></table></figure></li><li><p><code>arr.every(callback)</code>依据判断条件,数组的元素是否全满足,若满足返回<code>true</code><br>callback的参数: </p><ul><li>value –当前索引的值,</li><li>index –索引, (可选)</li><li>array –原数组 (可选)<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></pre></td><td class="code"><pre><code class="hljs plain">let arr = [1, 2, 3, 4]<br>let result = arr.every((value, index) => value < 3) // false<br>let result = arr.every((value, index) => value < 6) // true<br></code></pre></td></tr></table></figure></li></ul></li><li><p><code>arr.some()</code>依据条件判断,数组的元素是否有一个满足,若有一个满足则返回<code>true</code><br>callback的参数: </p><ul><li>value –当前索引的值,</li><li>index –索引, (可选)</li><li>array –原数组 (可选)<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></pre></td><td class="code"><pre><code class="hljs plain">let arr = [1, 2, 3, 4, 5]<br>let result = arr.some((value, index) => value < 3) // true<br>let result = arr.some((value, index) => value > 6) // false<br></code></pre></td></tr></table></figure></li></ul></li><li><p><code>arr.reduce(callback, initialValue)</code>迭代数组的所有项,累加器。数组中每个值(从左到右)合并,最终计算为一个值。<br>callback的参数: </p><ul><li>previousValue –上一次调用回调返回的值,或者是提供的初始值(initialValue)(必选)</li><li>currentValue –数组中当前被处理的数组项 (必选)</li><li>index – 当前数组项在数组中的索引值(可选)</li><li>array –原数组 (可选)</li></ul><p>initialValue参数:初始值(可选)<br>具体的实行:回调函数第一次执行时,<code>previousValue</code>和<code>currentValue</code>可以是一个值,如果<code>initialValue</code>在调用<code>reduce()</code>时被提供,那么第一个值<code>previousValue</code>等于<code>initialValue</code>,并且<code>currentValue</code>等于数组中的第一个值,如果<code>initialValue</code>未被提供,那么<code>previousValue</code>就等于数组中的第一个值。</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></pre></td><td class="code"><pre><code class="hljs plain">let arr = [1, 2, 3, 4, 5]<br>let result = arr.reuce((preValue, curValue)=> prevValue + cuValue)<br>console.log(result) // 15<br></code></pre></td></tr></table></figure><table><thead><tr><th></th><th>previousValue</th><th>currentValue</th><th>index</th><th>array</th><th>返回值</th></tr></thead><tbody><tr><td>第一次回调</td><td>1</td><td>2</td><td>1</td><td>[1, 2, 3, 4, 5]</td><td>3</td></tr><tr><td>第二次回调</td><td>3</td><td>3</td><td>2</td><td>[1, 2, 3, 4, 5]</td><td>6</td></tr><tr><td>第三次回调</td><td>6</td><td>4</td><td>3</td><td>[1, 2, 3, 4, 5]</td><td>10</td></tr><tr><td>第四次回调</td><td>10</td><td>5</td><td>4</td><td>[1, 2, 3, 4, 5]</td><td>15</td></tr></tbody></table><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><code class="hljs plain">let arr2 = arr.reduce((preValue,curValue)=>preValue + curValue,3)<br>console.log(arr2)<br></code></pre></td></tr></table></figure><table><thead><tr><th></th><th>previousValue</th><th>currentValue</th><th>index</th><th>array</th><th>返回值</th></tr></thead><tbody><tr><td>第一次回调</td><td>3</td><td>1</td><td>0</td><td>[1, 2, 3, 4, 5]</td><td>4</td></tr><tr><td>第二次回调</td><td>4</td><td>2</td><td>1</td><td>[1, 2, 3, 4, 5]</td><td>6</td></tr><tr><td>第三次回调</td><td>6</td><td>3</td><td>2</td><td>[1, 2, 3, 4, 5]</td><td>9</td></tr><tr><td>第四次回调</td><td>9</td><td>4</td><td>3</td><td>[1, 2, 3, 4, 5]</td><td>13</td></tr><tr><td>第五次回调</td><td>13</td><td>5</td><td>4</td><td>[1, 2, 3, 4, 5]</td><td>18</td></tr></tbody></table><p><code>reduce</code>的高级用法</p><ul><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><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></pre></td><td class="code"><pre><code class="hljs plain">let arr = ['joi', 'tom', 'tom', 'mary', 'peter', 'mary']<br>let num = arr.reduce((preVal, curVal) => {<br> if(curVal in preVal) {<br> preVal[curVal]++<br> } else {<br> preVal[curVal] = 1<br> }<br>}, {})<br><br>console.log(num) // {jio: 1, tom: 2, mary: 2, peter: 1}<br></code></pre></td></tr></table></figure><ul><li>数组去重<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></pre></td><td class="code"><pre><code class="hljs plain">let arr = [1,2,3,4,2,1,1,5]<br>let resArr = arr.reduce((preVal, curVal)=> {<br> if(!preVal.includes(curVal)) {<br> return preVal.concat(curVal)<br> } else {<br> return preVal<br> }<br>}, [])<br>console.log(resArr) // [1, 2, 3, 4, 5]<br></code></pre></td></tr></table></figure></li><li>将多维数组转为一维数组<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></pre></td><td class="code"><pre><code class="hljs plain">let arr = [[0, 1], [2, 3], [4,[5,6,7]]]<br>const replaceArr = (arr) => arr.reduce((preVal, curVal) => preVal.concat(Array.isArray(curVal) ? replaceArr(curVal): curVal), [])<br>console.log(replaceArr(arr)) // [0, 1, 2, 3, 4, 5, 6, 7]<br></code></pre></td></tr></table></figure></li></ul></li></ul></li><li><p><code>arr.reduceRight(callback, initialValue)</code>与<code>arr.reduce</code>一样,不同的是,<code>reduceRight</code>是从数组的末尾向前将数组中数组项做累加<br>callback的参数: </p><ul><li>previousValue –上一次调用回调返回的值,或者是提供的初始值(initialValue)(必选)</li><li>currentValue –数组中当前被处理的数组项 (必选)</li><li>index – 当前数组项在数组中的索引值(可选)</li><li>array –原数组 (可选)</li></ul><p>initialValue参数:初始值(可选)<br>具体的实行:回调函数第一次执行时,<code>previousValue</code>和<code>currentValue</code>可以是两个值之一,如果<code>initialValue</code>在调用<code>reduceRight()</code>时被提供,那么第一个值<code>previousValue</code>等于<code>initialValue</code>,并且<code>currentValue</code>等于数组中的最后一个值,如果<code>initialValue</code>未被提供,那么<code>previousValue</code>就等于数组中的最后一个值。</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></pre></td><td class="code"><pre><code class="hljs plain">let arr = [1, 2, 3, 4, 5]<br>let result = arr.reuce((preValue, curValue)=> prevValue + cuValue)<br>console.log(result) // 15<br></code></pre></td></tr></table></figure><table><thead><tr><th></th><th>previousValue</th><th>currentValue</th><th>index</th><th>array</th><th>返回值</th></tr></thead><tbody><tr><td>第一次回调</td><td>5</td><td>4</td><td>3</td><td>[1, 2, 3, 4, 5]</td><td>9</td></tr><tr><td>第二次回调</td><td>9</td><td>3</td><td>2</td><td>[1, 2, 3, 4, 5]</td><td>12</td></tr><tr><td>第三次回调</td><td>12</td><td>2</td><td>1</td><td>[1, 2, 3, 4, 5]</td><td>14</td></tr><tr><td>第四次回调</td><td>14</td><td>1</td><td>0</td><td>[1, 2, 3, 4, 5]</td><td>15</td></tr></tbody></table><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><code class="hljs plain">let arr2 = arr.reduce((preValue,curValue)=>preValue + curValue,3)<br>console.log(arr2)<br></code></pre></td></tr></table></figure><table><thead><tr><th></th><th>previousValue</th><th>currentValue</th><th>index</th><th>array</th><th>返回值</th></tr></thead><tbody><tr><td>第一次回调</td><td>3</td><td>5</td><td>4</td><td>[1, 2, 3, 4, 5]</td><td>8</td></tr><tr><td>第二次回调</td><td>8</td><td>4</td><td>3</td><td>[1, 2, 3, 4, 5]</td><td>12</td></tr><tr><td>第三次回调</td><td>12</td><td>3</td><td>2</td><td>[1, 2, 3, 4, 5]</td><td>15</td></tr><tr><td>第四次回调</td><td>15</td><td>2</td><td>1</td><td>[1, 2, 3, 4, 5]</td><td>17</td></tr><tr><td>第五次回调</td><td>17</td><td>1</td><td>0</td><td>[1, 2, 3, 4, 5]</td><td>18</td></tr></tbody></table></li><li><p><code>arr.indexOf()</code>查找某个元素的索引值,若有重复的,则返回第一个查到的,若查不到的-1</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></pre></td><td class="code"><pre><code class="hljs plain">let arr = [1, 2, 3]<br>console.log(arr.indexOf(2)) // 1<br>console.log(arr.indexOf(5)) // -1<br></code></pre></td></tr></table></figure></li><li><p><code>arr.lastIndexOf()</code>功能和<code>indexOf()</code>一样,不同的是它是从数组尾端开始往前找</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></pre></td><td class="code"><pre><code class="hljs plain">let arr = [1, 2, 3, 4, 5]<br>console.log(arr.lastIndexOf(3)) // 2<br>console.log(arr.lastIndexOf(5)) // -1<br></code></pre></td></tr></table></figure></li><li><p><code>Array.from()</code>将伪数组转成数组,就是只要有<code>length</code>的就可以转化成数组</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><code class="hljs plain">let str = '12345'<br>console.log(Array.from(str)) // ["1", "2", "3", "4", "5"]<br>let obj = {0: 'a', 1:'b', length: 2}<br>console.log(Array.from(obj)) // ["a", "b"]<br></code></pre></td></tr></table></figure></li><li><p><code>Array.of()</code>将一值转为数组,类似于声明数组</p><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><code class="hljs plain">let str = '11'<br>console.log(Array.of(str)) // ['11']<br></code></pre></td></tr></table></figure><p>等价于</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs plain">console.log(new Array('11')<br></code></pre></td></tr></table></figure><blockquote><p><code>new Array()</code>有缺点,就是参数问题引起的重载</p><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><code class="hljs plain">console.log(new Array(2)) //[empty × 2] 是个空数组<br>console.log(Array.of(2)) // [2]<br></code></pre></td></tr></table></figure></blockquote></li><li><p><code>arr.copyWithin()</code>在当前数组内部,将定时位置的数组复制到其他位置,会覆盖原来数组项,返回当前数组<br>参数:</p><ul><li>target –索引从该位置开始替换数组项(必选)</li><li>start –索引从该位置开始读取数组项,默认为0,如果为负值,则从右往左读取。(可选)</li><li>end –索引到改位置停止读取的数组项,默认是<code>Array.length</code>,如果负数,表示倒数。<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></pre></td><td class="code"><pre><code class="hljs plain">let arr = [1, 2, 3, 4, 5, 6, 7]<br>let arr1 = arr.copyWithin(1) <br>console.log(arr1) // [1, 1, 2, 3, 4, 5, 6]<br>let arr2 = arr.copyWithin(1, 2)<br>console.log(arr2) // [1, 3, 4, 5, 6, 7, 7]<br>let arr3 = arr.copyWithin(1, 2, 4)<br>console.log(arr3) // // [1, 3, 4, 4, 5, 6, 7]<br></code></pre></td></tr></table></figure></li></ul></li><li><p><code>arr.findInex(callback)</code>找到一个符合条件的数组成员的索引值<br>callback的参数: </p><ul><li>value –当前索引的值,</li><li>index –索引, (可选)</li><li>array –原数组 (可选)<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></pre></td><td class="code"><pre><code class="hljs plain">let arr = [1, 2, 3, 4]<br>let index = arr.findIndex((value, index, array) => value > 3)<br>console.log(index) // 3<br></code></pre></td></tr></table></figure></li></ul></li><li><p><code>arr.find(callback)</code>找到第一个符合条件的数组成员<br>callback的参数: </p><ul><li>value –当前索引的值,</li><li>index –索引, (可选)</li><li>array –原数组 (可选)<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></pre></td><td class="code"><pre><code class="hljs plain">let arr = [1, 2, 3, 4]<br>let item = arr.find((value, index, array)=> value > 2)<br>console.log(item) // 3<br></code></pre></td></tr></table></figure></li></ul></li><li><p><code>arr.fill(target, start, end)</code>是用给定的值,填充一个数组,填完会改变原数组<br>参数: </p><ul><li>target –待填充的元素,</li><li>start –开始填充的位置索引, (可选)</li><li>end –结束填充元素的索引 (可选)<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></pre></td><td class="code"><pre><code class="hljs plain">let arr = [1, 2, 3, 4] <br><br>console.log(arr.fill(4)) // [4, 4, 4, 4]<br><br>console.log(arr.fill(4, 1)) // [1, 4, 4, 4]<br><br>console.log(arr.fill(4, 1, 2)) // [1, 4, 3, 4]<br></code></pre></td></tr></table></figure></li></ul></li><li><p><code>arr.includes()</code>判断数中是否包含给定的值</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><code class="hljs plain">let arr = [1, 2, 3, 4, 5, NaN]<br>console.log(arr.includes(5)) // true<br>console.log(arr.includes(8)) // false<br>console.log(arr.includes(NaN)) // true<br></code></pre></td></tr></table></figure><blockquote><p><code>includes()</code>与<code>indexOf()</code>的区别</p><ol><li><code>indexOf()</code>返回的是数值,而<code>includes()</code>返回的是布尔值</li><li><code>indexOf()</code>不能判断<code>NaN</code>,返回为 -1 ,<code>includes()</code>可以判断</li></ol></blockquote></li><li><p><code>arr.keys()</code> 获取数组的所有键名(遍历)</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><code class="hljs plain">let arr = [1, 2, 3, 4]<br>let arr2 = arr.keys()<br>for (let key of arr2) {<br> console.log(key); // 0,1,2,3<br>}<br></code></pre></td></tr></table></figure></li><li><p><code>arr.values()</code> 获取数组键值(遍历)</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><code class="hljs plain">let arr = ['apple', 'banner']<br>let arr1 = arr.values()<br>for(let val of arr1) {<br> console.log(val) // apple, banner<br>}<br></code></pre></td></tr></table></figure></li><li><p><code>arr.entries()</code> 获取数组的键名以及键值(遍历)</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><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></pre></td><td class="code"><pre><code class="hljs plain">let arr = [1, 2, 3, 4]<br>let arr1 = arr.entries()<br>for(let [key, val] of arr1) {<br> console.log(key, val)<br>}<br>/*<br> key:0 value:1<br> key:1 value:2<br> key:2 value:3<br> key:3 value:4<br>*/<br></code></pre></td></tr></table></figure></li><li><p><code>arr.toString()</code> 将数组元素返回一个字符串,表示指定的数组及其元素</p><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><code class="hljs plain">let arr = [1, 2, 3, 4]<br>console.log(arr.toString()) // 1,2,3,4<br></code></pre></td></tr></table></figure></li></ol>]]></content>
<summary type="html">
<h1 id="JavaScript中数组常用方法"><a href="#JavaScript中数组常用方法" class="headerlink" title="JavaScript中数组常用方法"></a>JavaScript中数组常用方法</h1><hr>
<h2 id="
</summary>
</entry>
<entry>
<title>Git常用命令记录</title>
<link href="http://jetbn.github.io/2020/05/09/t%E5%B8%B8%E7%94%A8%E5%91%BD%E4%BB%A4%E8%AE%B0%E5%BD%95/"/>
<id>http://jetbn.github.io/2020/05/09/t%E5%B8%B8%E7%94%A8%E5%91%BD%E4%BB%A4%E8%AE%B0%E5%BD%95/</id>
<published>2020-05-09T07:34:00.000Z</published>
<updated>2020-05-09T07:37:48.640Z</updated>
<content type="html"><![CDATA[<h3 id="git相关命令常用"><a href="#git相关命令常用" class="headerlink" title="git相关命令常用"></a>git相关命令常用</h3><ul><li><ol><li>git checkout -b sub_main origin/sub_main<br> 拉取远程分支到本地分支 并且切换到该分支</li></ol></li><li><ol start="2"><li>git branch<br> 查看本地所有分支</li></ol></li><li><ol start="3"><li>git branch -a<br> 查看远程本地所有分支</li></ol></li><li><ol start="4"><li>git branch -d <分支名称><br> 查看远程本地所有分支</li></ol></li><li><ol start="5"><li>git pull<br> 拉取最新的代码都本地</li></ol></li><li><ol start="6"><li>git commit -m<br> 进行commit操作</li></ol></li><li><ol start="7"><li>git add .<br> 进行添加到暂存区</li></ol></li><li><ol start="8"><li>git push origin <分支名称>:<远程分支名称><br> 将本地分支推送到远程分支</li></ol></li><li><ol start="9"><li>git push -u origin mybranch<br> 将本地分支推送到远程分支<blockquote><p>$ git push -u origin master <br> 上面命令将本地的master分支推送到origin主机,同时指定origin为默认主机,后面就可以不加任何参数使用git push了。</p></blockquote></li></ol></li></ul>]]></content>
<summary type="html">
<h3 id="git相关命令常用"><a href="#git相关命令常用" class="headerlink" title="git相关命令常用"></a>git相关命令常用</h3><ul>
<li><ol>
<li>git checkout -b sub_main or
</summary>
</entry>
<entry>
<title>JS节流与防抖</title>
<link href="http://jetbn.github.io/2020/05/09/%E4%B8%8E%E9%98%B2%E6%8A%96/"/>
<id>http://jetbn.github.io/2020/05/09/%E4%B8%8E%E9%98%B2%E6%8A%96/</id>
<published>2020-05-09T06:52:00.000Z</published>
<updated>2020-05-09T07:28:46.539Z</updated>
<content type="html"><![CDATA[<h2 id="前言"><a href="#前言" class="headerlink" title="前言"></a>前言</h2><hr><p>    在日常开发中进行窗口的resize、scroll,输入框内容校验等操作时,如果事件处理函数调用的频率无限制,会加重浏览器的负担,导致用户体验非常糟糕。这时候我们更希望把多次计算合并成一次,只操作一个精确点来减少调用频率,同时又不影响实际效果。 JS把这种方式称为debounce(防抖)和throttle(节流)。</p><h2 id="节流"><a href="#节流" class="headerlink" title="节流"></a>节流</h2><p>    高频事件触发,但在n秒内只会执行一次,所以节流会稀释函数的执行频率</p><ul><li><p>应用场景</p><pre><code>1. DOM元素的拖拽功能实现(mousemove) 2. 射击游戏的 mousedown/keydown 事件(单位时间只能发射一颗子弹)3. 计算鼠标移动的距离(mousemove)4. 搜索联想(keyup)5. 滚动事件scroll,(只要页面滚动就会间隔一段时间判断一次)</code></pre></li></ul><ul><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><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></pre></td><td class="code"><pre><code class="hljs plain"> function debounce(fn, delay, scope) {<br> let timer = null;<br> // 返回函数对debounce作用域形成闭包<br> return function () {<br> // setTimeout()中用到函数环境总是window,故需要当前环境的副本;<br> let context = scope || this, args = arguments;<br> // 如果事件被触发,清除timer并重新开始计时<br> clearTimeout(timer);<br> timer = setTimeout(function () {<br> fn.apply(context, args);<br> }, delay);<br> }<br>}<br></code></pre></td></tr></table></figure></li><li><p>代码解读</p><pre><code>1. 第一次调用函数,创建一个定时器,在指定的时间间隔之后运行代码; 2. 当第二次调用该函数时,它会清除前一次的定时器并设置另一个; 3. 如果前一个定时器已经执行过了,这个操作就没有任何意义; 4. 然而,如果前一个定时器尚未执行,其实就是将其替换为一个新的定时器;目的是只有在执行函数的请求停止了delay时间之后才执行。</code></pre></li></ul><h2 id="防抖"><a href="#防抖" class="headerlink" title="防抖"></a>防抖</h2><p>    触发高频事件后n秒内函数只会执行一次,如果n秒内高频事件再次被触发,则重新计算时间</p><ul><li><p>应用场景</p><pre><code>1. 手机号、邮箱输入检测2. 搜索框搜索输入(只需最后一次输入完后,再放松Ajax请求)3. 窗口大小resize(只需窗口调整完成后,计算窗口大小,防止重复渲染)4. 滚动事件scroll(只需执行触发的最后一次滚动事件的处理程序)5. 文本输入的验证(连续输入文字后发送 AJAX 请求进行验证,(停止输入后)验证一次就好</code></pre></li><li><p>防抖实现</p><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><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></pre></td><td class="code"><pre><code class="hljs plain">function throttle(fn, threshold, scope) {<br> let timer;<br> let prev = Date.now();<br> return function () {<br> let context = scope || this, args = arguments;<br> let now = Date.now();<br> if (now - prev > threshold) {<br> prev = now;<br> fn.apply(context, args);<br> }<br> }<br>}<br></code></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><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></pre></td><td class="code"><pre><code class="hljs plain">function throttle2(fn, threshold, scope) {<br> let timer;<br> return function () {<br> let context = scope || this, args = arguments;<br> if (!timer) {<br> timer = setTimeout(function () {<br> fn.apply(context, args);<br> timer = null;<br> }, threshold)<br> }<br> }<br>}<br></code></pre></td></tr></table></figure></li></ol></li></ul><h2 id="总结"><a href="#总结" class="headerlink" title="总结"></a>总结</h2><ol><li>防抖和节流有很多实现的方法,其大致思路基本是这样的。</li><li>防抖和节流是不同的,因为节流虽然中间的处理函数被限制了,但是只是减少了频率,而防抖则把中间的处理函数全部过滤掉了,只执行规判定时间内的最后一个事件。</li><li>防抖和节流各自有自己特点,需要在不同场景进行选择,不能混合乱使用。</li></ol>]]></content>
<summary type="html">
<h2 id="前言"><a href="#前言" class="headerlink" title="前言"></a>前言</h2><hr>
<p>&ensp;&ensp;&ensp;&ensp;在日常开发中进行窗口的resize、scroll,输入框内容校验等操作时,如果事件
</summary>
<category term="Web前端" scheme="http://jetBn.github.io/categories/Web%E5%89%8D%E7%AB%AF/"/>
</entry>
<entry>
<title>你不知道的CSS </title>
<link href="http://jetbn.github.io/2020/04/30/%E4%B8%8D%E7%9F%A5%E9%81%93%E7%9A%84CSS/"/>
<id>http://jetbn.github.io/2020/04/30/%E4%B8%8D%E7%9F%A5%E9%81%93%E7%9A%84CSS/</id>
<published>2020-04-30T05:42:00.000Z</published>
<updated>2020-04-30T07:22:17.122Z</updated>
<content type="html"><![CDATA[<h2 id="前言"><a href="#前言" class="headerlink" title="前言"></a>前言</h2><hr><p>    <code>CSS</code>的世界是神奇的。当今所以不管移动端还是PC端网页都是离不开<code>CSC</code>(层叠样式表),像类选择,id选择等等这些选择器 我们工作都有用到,但是难免忽略一些,<code>CSS</code>中更强大的属性我们很少用到,特此记录一些。</p><h2 id="用-兄弟选择器来美化表单元素"><a href="#用-兄弟选择器来美化表单元素" class="headerlink" title="用~/ +兄弟选择器来美化表单元素"></a>用<code>~</code>/ <code>+</code>兄弟选择器来美化表单元素</h2><ol><li><code>~</code>选择器:查找某一个元素的后面的所有兄弟元素</li><li><code>+</code>选择器:查找某一个元素的后面紧邻的兄弟元素</li></ol><h2 id="用font-size:0来清除间距"><a href="#用font-size:0来清除间距" class="headerlink" title="用font-size:0来清除间距"></a>用<code>font-size:0</code>来清除间距</h2><p>     <code>inline-block</code>的元素之间会受空白区域的影响,也就是元素之间差不多会有一个字符的间隙。如果在同一行内有4个25%相同宽度的元素,会导致最后一个元素掉下来(如图)。你可以利用元素浮动<code>float</code>,或者压缩html,清除元素间的空格来解决。但最简单有效的方法还是设置父元素的<code>font-size</code>属性为0。</p><h2 id="用-overflow-來清除浮动-创建块级格式化上下文"><a href="#用-overflow-來清除浮动-创建块级格式化上下文" class="headerlink" title="用 overflow 來清除浮动(创建块级格式化上下文)"></a>用 overflow 來清除浮动(创建块级格式化上下文)</h2><p> 通过触发BFC方式,实现清除浮动(父元素添加overflow:hidden)<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><span class="line">5</span><br></pre></td><td class="code"><pre><code class="hljs plain">.fahter{<br> width: 400px;<br> border: 1px solid deeppink;<br> overflow: hidden;<br> }<br></code></pre></td></tr></table></figure></p><h2 id="用pointer-event来禁用事件"><a href="#用pointer-event来禁用事件" class="headerlink" title="用pointer-event来禁用事件"></a>用pointer-event来禁用事件</h2><ol><li><p>阻止任何点击动作的执行</p></li><li><p>使链接显示为默认光标(cursor:default)</p></li><li><p>阻止触发hover和active状态</p></li><li><p>阻止JavaScript点击事件的触发</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></pre></td><td class="code"><pre><code class="hljs plain">//使用该类,任何点击事件将无效<br><br>.disabled { pointer-events: none; }<br></code></pre></td></tr></table></figure></li></ol><h2 id="用max-width来防止图片撑破容器"><a href="#用max-width来防止图片撑破容器" class="headerlink" title="用max-width来防止图片撑破容器"></a>用max-width来防止图片撑破容器</h2><p> 针对内容性的文案,图片大小都是未知的,为了防止图片过大而撑破容器,可以通过设置图片的max-width:100%来处理。<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><code class="hljs plain">img {<br> display:inline-block;<br> max-width: 100%; <br> }<br></code></pre></td></tr></table></figure></p><h2 id="实现三角形"><a href="#实现三角形" class="headerlink" title="实现三角形"></a>实现三角形</h2><p> 新建一个元素,将它的宽高都设置为0;然后通过设置border属性来实现三角形效果<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><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></pre></td><td class="code"><pre><code class="hljs plain"> .arrow{<br> width: 0;<br> height: 0;<br><br> /*直角三角形*/<br><br> /* border-width: 50px 50px 0 0;<br> border-style: solid;<br> border-color: transparent #000 transparent transparent; */<br><br> /*向下三角形*/<br> /* border-width: 100px 100px 0 100px;<br> border-style: solid;<br> border-color: brown transparent transparent transparent; */<br><br>}<br></code></pre></td></tr></table></figure></p><h2 id="移动端禁止用户长按文字选择功能"><a href="#移动端禁止用户长按文字选择功能" class="headerlink" title="移动端禁止用户长按文字选择功能"></a>移动端禁止用户长按文字选择功能</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></pre></td><td class="code"><pre><code class="hljs plain"> .unselect {<br> -webkit-touch-callout:none;<br> -webkit-user-select:none;<br> -khtml-user-select:none;<br> -moz-user-select:none;<br> -ms-user-select:none;<br> user-select:none<br>}<br></code></pre></td></tr></table></figure><h2 id="文字模糊"><a href="#文字模糊" class="headerlink" title="文字模糊"></a>文字模糊</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></pre></td><td class="code"><pre><code class="hljs plain"> .blur {<br> color: transparent;<br> text-shadow: 0 0 5px rgba(0, 0, 0, 0.5)<br>}<br></code></pre></td></tr></table></figure><h2 id="超出N行显示省略号"><a href="#超出N行显示省略号" class="headerlink" title="超出N行显示省略号"></a>超出N行显示省略号</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></pre></td><td class="code"><pre><code class="hljs plain"> .hide-text-n {<br> display: -webkit-box;<br> -webkit-box-orient: vertical;<br> -webkit-line-clamp: n;<br> overflow: hidden<br>}<br></code></pre></td></tr></table></figure><h2 id="硬件加速"><a href="#硬件加速" class="headerlink" title="硬件加速"></a>硬件加速</h2><p> 写transition、animation时,请用transform代替left、top等属性,从而使动画更流畅</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><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><code class="hljs plain"> cube {<br> -webkit-transform: translateZ(0);<br> -moz-transform: translateZ(0);<br> -ms-transform: translateZ(0);<br> -o-transform: translateZ(0);<br> transform: translateZ(0)<br>}<br></code></pre></td></tr></table></figure><h2 id="移动端屏幕旋转时,字体大小不改变"><a href="#移动端屏幕旋转时,字体大小不改变" class="headerlink" title="移动端屏幕旋转时,字体大小不改变"></a>移动端屏幕旋转时,字体大小不改变</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></pre></td><td class="code"><pre><code class="hljs plain"> html, body, form, p, div, h1, h2, h3, h4, h5, h6 {<br> -webkit-text-size-adjust: 100%;<br> -ms-text-size-adjust: 100%;<br> text-size-adjust: 100%<br>}<br></code></pre></td></tr></table></figure><h2 id="锚点跳转平滑过渡"><a href="#锚点跳转平滑过渡" class="headerlink" title="锚点跳转平滑过渡"></a>锚点跳转平滑过渡</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></pre></td><td class="code"><pre><code class="hljs plain">body {<br> scroll-behavior: smooth;<br> }<br></code></pre></td></tr></table></figure><h2 id="最后一个元素不需要边框、边距等"><a href="#最后一个元素不需要边框、边距等" class="headerlink" title="最后一个元素不需要边框、边距等"></a>最后一个元素不需要边框、边距等</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></pre></td><td class="code"><pre><code class="hljs plain">ul > li:not(:last-child) {<br> border-bottom: 1px solid #c5b7b7<br>}<br></code></pre></td></tr></table></figure><h2 id="清除浮动-适应伪类"><a href="#清除浮动-适应伪类" class="headerlink" title="清除浮动(适应伪类)"></a>清除浮动(适应伪类)</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></pre></td><td class="code"><pre><code class="hljs plain">.clearfix::after {<br> content: '';<br> display: block;<br> height: 0;<br> visibility: hidden;<br> clear: both<br>}<br></code></pre></td></tr></table></figure><h2 id="CSS选择器选基数项、偶数项、倍数分组项"><a href="#CSS选择器选基数项、偶数项、倍数分组项" class="headerlink" title="CSS选择器选基数项、偶数项、倍数分组项"></a>CSS选择器选基数项、偶数项、倍数分组项</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></pre></td><td class="code"><pre><code class="hljs plain">/* 基数 */<br>.selector:nth-child(2n-1) {}<br><br>/* 偶数 */<br>.selector:nth-child(2n) {}<br><br>/* 倍数分组项 */<br>.selector:nth-child(3n+1) {} /* 匹配第1、4、7、10... */<br>.selector:nth-child(3n+5) {} /* 匹配第5、8、11、14... */<br>.selector:nth-child(5n-1) {} /* 匹配第4、9、13、17... */<br></code></pre></td></tr></table></figure><h2 id="当输入框的value的长度不为0时,显示搜索按钮"><a href="#当输入框的value的长度不为0时,显示搜索按钮" class="headerlink" title="当输入框的value的长度不为0时,显示搜索按钮"></a>当输入框的value的长度不为0时,显示搜索按钮</h2><p>用到placeholder-shown伪类,简单来说就是当input标签有了placeholder属性并且内容不为空时,会触发该状态,但是当input标签有了value值之后,就会消除该状态,也要配合:not选择器</p><p><code>html</code></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><code class="hljs plain"><div class="input-line"><br> <input type="text" placeholder="请输入关键字进行搜索"><br> <button type="button" class="search-btn">搜索</button><br></div><br></code></pre></td></tr></table></figure><p><code>css</code></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><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><code class="hljs plain">.search-btn {<br> opacity: 0;<br> transition: all .5s ease-in-out<br>}<br><br> input:not(:placeholder-shown)~.search-btn {<br> opacity: 1<br> }<br></code></pre></td></tr></table></figure>]]></content>
<summary type="html">
<h2 id="前言"><a href="#前言" class="headerlink" title="前言"></a>前言</h2><hr>
<p>&ensp;&ensp;&ensp;&ensp;<code>CSS</code>的世界是神奇的。当今所以不管移动端还是PC端网页都
</summary>
<category term="Web前端" scheme="http://jetBn.github.io/categories/Web%E5%89%8D%E7%AB%AF/"/>
<category term="CSS" scheme="http://jetBn.github.io/tags/CSS/"/>
</entry>
<entry>
<title>Vue3.0尝试</title>
<link href="http://jetbn.github.io/2020/04/29/Vue3-0%E5%B0%9D%E8%AF%95/"/>
<id>http://jetbn.github.io/2020/04/29/Vue3-0%E5%B0%9D%E8%AF%95/</id>
<published>2020-04-29T02:59:17.000Z</published>
<updated>2020-04-30T02:09:54.002Z</updated>
<content type="html"><![CDATA[<p><img src="https://user-gold-cdn.xitu.io/2020/1/13/16f9e71255c62bc0?w=299&h=300&f=png&s=43799" alt=""></p><h2 id="前言"><a href="#前言" class="headerlink" title="前言"></a>前言</h2><hr><p>    有关vue2的相关相关语法我相信大家都已经的语法我相信大家都已经会了,现在都已经<code>2020</code>年了vue作为前端这么热门的框架, 不去学一波对的自己是做前端的吗?哈哈哈哈🤣🤣🤣。<br/><br>    一路就开始折腾,那是一路曲折啊,重不会到会也不知道自己经历了什么,到现在<code>vue3.x</code>马上又有开始了所以自己也是先试试水,玩了一波相关的语法。<br/><br>     废话不多说直接上代码记录下(由于本人没有用到<code>TS</code>所以都是进行与<code>ES6</code>进行)</p><h2 id="开始"><a href="#开始" class="headerlink" title="开始"></a>开始</h2><ol><li>在<code>vue-cli3.0</code>下安装 <code>composition-api</code> <figure class="highlight coffeescript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><code class="hljs coffeescript"><span class="hljs-built_in">npm</span> install @vue/composition-api --save<br><span class="hljs-comment"># OR</span><br>yarn add @vue/composition-api<br></code></pre></td></tr></table></figure></li><li>在使用任何 <code>@vue/composition-api</code> 提供的能力前,必须先通过 Vue.use() 进行安装 <figure class="highlight clean"><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><code class="hljs clean"><span class="hljs-keyword">import</span> Vue <span class="hljs-keyword">from</span> <span class="hljs-string">'vue'</span><br><span class="hljs-keyword">import</span> VueCompositionApi <span class="hljs-keyword">from</span> <span class="hljs-string">'@vue/composition-api'</span><br><br>Vue.use(VueCompositionApi)<br></code></pre></td></tr></table></figure> 安装完成后就可项目中使用相关<code>composition-api</code>来开发了</li></ol><h2 id="setup(入口函数)"><a href="#setup(入口函数)" class="headerlink" title="setup(入口函数)"></a>setup(入口函数)</h2><p>    <code>setup()</code>函数是<code>vue3</code>中,专门为组件提供的新属性,感觉就跟是跟<code>vue2.x</code>中的<code>data</code>一样需要返回一个<code>Object</code>中包含了自己定义的<code>function</code>, <code>computed</code>, <code>watch</code>以及属性和生命周期。</p><ol><li><p>setup 函数会在 beforeCreate 之后、created 之前执行。</p> <figure class="highlight pf"><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><code class="hljs pf">setup(props, context) {<br> const <span class="hljs-keyword">state</span> = reactive({count: <span class="hljs-number">0</span>}) // 创建数据<br> return <span class="hljs-keyword">state</span> // 返回页面中使用<br>}<br></code></pre></td></tr></table></figure></li><li><p>接收<code>props</code>数据</p><ol><li>在<code>props</code>中定义当前组件允许外界传递过来的参数名称: <figure class="highlight css"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><code class="hljs css"> <span class="hljs-selector-tag">props</span>: {<br> <span class="hljs-attribute">name</span>: String<br>}<br></code></pre></td></tr></table></figure></li><li>通过<code>setup</code>函数的第一个形参,接收 props 数据: <figure class="highlight maxima"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><code class="hljs maxima">setup(<span class="hljs-built_in">props</span>) {<br> console.<span class="hljs-built_in">log</span>(<span class="hljs-built_in">props</span>.name)<br>}<br></code></pre></td></tr></table></figure></li></ol></li><li><p>context形参</p><p> <code>setup</code>函数的第二个形参是一个上下文对象,就是<code>vue2.x</code>中的<code>this</code>,在<code>vue 3.x</code>中,它们的访问方式如下</p> <figure class="highlight maxima"><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><code class="hljs maxima"> setup(<span class="hljs-built_in">props</span>, <span class="hljs-built_in">context</span>) {<br> <span class="hljs-built_in">context</span>.slots<br> <span class="hljs-built_in">context</span>.emit<br> <span class="hljs-built_in">context</span>.refs<br>}<br></code></pre></td></tr></table></figure></li></ol><h2 id="reactive与ref(响应式数据源)"><a href="#reactive与ref(响应式数据源)" class="headerlink" title="reactive与ref(响应式数据源)"></a>reactive与ref(响应式数据源)</h2><ol><li><p><code>reactive()</code>函数接收一个普通的对象,返回一个响应的数据对象。</p><p> 这等价于<code>vue2.x</code>中的<code>Vue.observable()</code>函数,<code>vue3.x</code>然后就是可以直接用reactive()函数直接创建响应的数据对象。</p><ol><li><p>按需导入<code>reactive</code>相关函数</p><p> <code>import { reactive } from '@vue/composition-api'</code></p></li><li><p>在<code>setup()</code>的函数中调用<code>reactive()</code>函数,创建对应的响应式数据对象</p> <figure class="highlight pf"><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><code class="hljs pf">setup() {<br> // 这个类似于vue2中的data()返回的响应式对象<br> const <span class="hljs-keyword">state</span> = reactive({ count: <span class="hljs-number">0</span> }) <br> return <span class="hljs-keyword">state</span><br>}<br></code></pre></td></tr></table></figure></li><li><p>在<code>template</code>中访问响应式数据</p> <figure class="highlight django"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><code class="hljs django"><span class="xml"><span class="hljs-tag"><<span class="hljs-name">template</span>></span></span><br><span class="xml"> <span class="hljs-tag"><<span class="hljs-name">span</span>></span>当前的count值为:</span><span class="hljs-template-variable">{{count}}</span><span class="xml"><span class="hljs-tag"></<span class="hljs-name">span</span>></span></span><br><span class="xml"><span class="hljs-tag"></<span class="hljs-name">template</span>></span></span><br></code></pre></td></tr></table></figure></li></ol></li><li><p><code>ref()</code>函数用来根据给定值创建一个响应式的数据对象,<code>ref()</code>函数的调用返回值是一个对象,这个对象上只包含一个<code>value</code>属性。</p><ol><li><p>导入相关<code>ref</code>相关函数</p><p> <code>import { ref } from '@vue/composition-api'</code></p></li><li><p>创建响应式对象</p> <figure class="highlight applescript"><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></pre></td><td class="code"><pre><code class="hljs applescript">setup() {<br> const <span class="hljs-built_in">count</span> = <span class="hljs-keyword">ref</span>(<span class="hljs-number">0</span>)<br><span class="hljs-built_in"> return</span> {<br> <span class="hljs-built_in">count</span>,<br> <span class="hljs-built_in">name</span>: <span class="hljs-keyword">ref</span>('vue')<br> }<br>}<br></code></pre></td></tr></table></figure><ol start="3"><li>在<code>template</code>中访问响应式数据<figure class="highlight django"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><code class="hljs django"><span class="xml"><span class="hljs-tag"><<span class="hljs-name">template</span>></span></span><br><span class="xml"> <span class="hljs-tag"><<span class="hljs-name">span</span>></span></span><span class="hljs-template-variable">{{count}}</span><span class="xml">--- </span><span class="hljs-template-variable">{{name}}</span><span class="xml"><span class="hljs-tag"></<span class="hljs-name">span</span>></span></span><br><span class="xml"><span class="hljs-tag"></<span class="hljs-name">template</span>></span></span><br></code></pre></td></tr></table></figure></li></ol></li></ol></li><li><p><code>isRef</code>的使用<br> ,<code>isRef()</code>函数主要用来判断某个值是否为<code>ref()</code>创建出来的对象;应用场景:当需要展开某个可能为<code>ref()</code>创建出来的值得时候,例如:</p> <figure class="highlight cs"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><code class="hljs cs">import { isRef } <span class="hljs-keyword">from</span> <span class="hljs-string">'@vue/composition-api'</span><br><br><span class="hljs-keyword">const</span> fooData = isRef(foo) ? foo.<span class="hljs-keyword">value</span> : foo<br></code></pre></td></tr></table></figure></li><li><p><code>toRefs</code>的使用,<code>toRefs()</code>函数可以将<code>reactive()</code>创建出来的响应式对象,转为普通对象,只不过这个对象上的属性节点都是以<code>ref()</code>类型的像是数据, 最常见应用场景</p> <figure class="highlight pf"><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></pre></td><td class="code"><pre><code class="hljs pf">import { <span class="hljs-keyword">to</span>Refs, reactive } <span class="hljs-keyword">from</span> '@vue/composition-api'<br><br>setup() {<br> // 定义响应式数据对象<br> const <span class="hljs-keyword">state</span> = reactive({<br> count: <span class="hljs-number">0</span><br> })<br> <br> // 定义页面上可用的事件处理函数<br> const increment = () => {<br> <span class="hljs-keyword">state</span>.count++<br> }<br> <br> // 在 setup 中返回一个对象供页面使用<br> // 这个对象中可以包含响应式的数据,也可以包含事件处理函数<br> return {<br> // 将 <span class="hljs-keyword">state</span> 上的每个属性,都转化为 ref 形式的响应式数据<br> ...<span class="hljs-keyword">to</span>Refs(<span class="hljs-keyword">state</span>),<br> // 自增的事件处理函数<br> increment<br> }<br>}<br></code></pre></td></tr></table></figure><p> 在<code>template</code>中就直接可以使用<code>count</code>属性和相对应的<code>increment</code>方法了,如果没有使用<code>roRefs</code>直接返回<code>state</code>那么就得通过<code>state.xx</code>来访问数据</p> <figure class="highlight django"><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></pre></td><td class="code"><pre><code class="hljs django"><span class="xml"><span class="hljs-tag"><<span class="hljs-name">template</span>></span></span><br><span class="xml"> <span class="hljs-tag"><<span class="hljs-name">div</span>></span></span><br><span class="xml"> <span class="hljs-tag"><<span class="hljs-name">span</span>></span>当前的count值为:</span><span class="hljs-template-variable">{{count}}</span><span class="xml"><span class="hljs-tag"></<span class="hljs-name">span</span>></span></span><br><span class="xml"> <span class="hljs-tag"><<span class="hljs-name">button</span> @<span class="hljs-attr">click</span>=<span class="hljs-string">"increment"</span>></span>add<span class="hljs-tag"></<span class="hljs-name">button</span>></span></span><br><span class="xml"> <span class="hljs-tag"></<span class="hljs-name">div</span>></span></span><br><span class="xml"><span class="hljs-tag"></<span class="hljs-name">template</span>></span></span><br></code></pre></td></tr></table></figure><h2 id="computed与watch(计算属性与监听)"><a href="#computed与watch(计算属性与监听)" class="headerlink" title="computed与watch(计算属性与监听)"></a>computed与watch(计算属性与监听)</h2><ol><li><p><code>computed()</code> 用来创建计算属性,<code>computed()</code> 函数的返回值是一个 ref 的实例。使用 <code>computed</code> 之前需要按需导入:</p><figure class="highlight nginx"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs nginx"><span class="hljs-section">import</span> { <span class="hljs-attribute">computed</span> } from <span class="hljs-string">'<span class="hljs-variable">@vue</span>/composition-api'</span><br></code></pre></td></tr></table></figure><ol><li><p>创建只读的计算属性,在调用<code>computed()</code>函数的时候,传入一个<code>function</code>函数,可以得到一个只读的计算属性。</p><figure class="highlight cs"><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></pre></td><td class="code"><pre><code class="hljs cs"><span class="hljs-comment">// 创建一个响应式数据</span><br><span class="hljs-keyword">const</span> count = <span class="hljs-keyword">ref</span>(<span class="hljs-number">1</span>) <br><br><span class="hljs-comment">// 根据count的值创建一个响应式的计算属性, 它会根据ref自动计算并且返回一个新的ref</span><br><span class="hljs-keyword">const</span> computedCount = computed(() => count.<span class="hljs-keyword">value</span> + <span class="hljs-number">1</span> ) <br><br>console.log(computedCount.<span class="hljs-keyword">value</span>) <span class="hljs-comment">// 打印 2</span><br><br>computedCount.<span class="hljs-keyword">value</span>++ <span class="hljs-comment">//报错</span><br></code></pre></td></tr></table></figure></li><li><p>创建可读可写的计算属性</p><p>在调用<code>computed()</code>函数的时候传入一个包含<code>get</code>和<code>set</code>的对象,就可以得到一个可读可写的计算属性了。</p><figure class="highlight q"><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></pre></td><td class="code"><pre><code class="hljs q"><span class="hljs-comment">// 创建一个响应式数据</span><br>const <span class="hljs-built_in">count</span> = ref(<span class="hljs-number">1</span>) <br><br><span class="hljs-comment">// 根据count的值创建一个响应式的计算属性, 它会根据ref自动计算并且返回一个新的ref</span><br>const computedCount = computed({<br> <span class="hljs-built_in">get</span>: () => <span class="hljs-built_in">count</span>.<span class="hljs-built_in">value</span> + <span class="hljs-number">1</span>,<br> <span class="hljs-built_in">set</span>: (val) => <span class="hljs-built_in">count</span>.<span class="hljs-built_in">value</span> = val - <span class="hljs-number">1</span><br>} ) <br><br>computedCount.<span class="hljs-built_in">count</span> = <span class="hljs-number">6</span><br><br>console.log(<span class="hljs-built_in">count</span>.<span class="hljs-built_in">value</span>) <span class="hljs-comment">// 打印 5</span><br></code></pre></td></tr></table></figure></li></ol><p>2.<code>watch()</code> 函数用来监听数据的变化,跟<code>vue2.x</code>中的是一样的不过在这得像<code>computed</code>的使用方法一样导入相关<code>api</code>方法</p><p>使用前导入 <code>import { watch } from '@vue/composition-api'</code></p><ol><li><p>基本用法</p><figure class="highlight javascript"><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></pre></td><td class="code"><pre><code class="hljs javascript"><span class="hljs-keyword">const</span> count = ref(<span class="hljs-number">0</span>)<br><br><span class="hljs-comment">// 定义watch只要count的值变化,就会触发watch的回调</span><br><span class="hljs-comment">// watch 会在创建的时候自动调用一次</span><br><br>watch(<span class="hljs-function"><span class="hljs-params">()</span> =></span> <span class="hljs-built_in">console</span>.log(count.value))<br><br><br>setTimeout(<span class="hljs-function"><span class="hljs-params">()</span> =></span> {<br> count.value++<br>}, <span class="hljs-number">1000</span>)<br></code></pre></td></tr></table></figure></li><li><p>监听指定数据</p><figure class="highlight pf"><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></pre></td><td class="code"><pre><code class="hljs pf">/ 定义reactive数据源<br>const <span class="hljs-keyword">state</span> = reactive({ count: <span class="hljs-number">0</span> })<br>// 监视 <span class="hljs-keyword">state</span>.count 这个数据节点的变化<br>watch(() => <span class="hljs-keyword">state</span>.count, (now, prev) => { <br> console.<span class="hljs-keyword">log</span>(now, prev)<br>})<br><br>/ 定义ref数据源<br>const count = ref(<span class="hljs-number">0</span>)<br>// 监视count这个数据的变化<br>watch(count, (now, prev) => { <br> console.<span class="hljs-keyword">log</span>(now, prev)<br>})<br></code></pre></td></tr></table></figure><h2 id="LifeCycle-Hooks-生命周期"><a href="#LifeCycle-Hooks-生命周期" class="headerlink" title="LifeCycle Hooks(生命周期)"></a>LifeCycle Hooks(生命周期)</h2><p>在新版中的生命周期需要按需导入,并且只能写<code>setup()</code>函数中。</p></li></ol></li></ol></li></ol><p>使用<code>onBeforeMount</code>, <code>onMounted</code>, <code>updated</code>相关生命周期,使用前导入相关<code>api</code>方法</p><figure class="highlight clean"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs clean"><span class="hljs-keyword">import</span> { onBeforeMount, onMounted, updated } <span class="hljs-keyword">from</span> <span class="hljs-string">'@vue/composition-api'</span><br></code></pre></td></tr></table></figure> <figure class="highlight coffeescript"><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></pre></td><td class="code"><pre><code class="hljs coffeescript">setup () {<br> onBeforeMount(<span class="hljs-function"><span class="hljs-params">()</span> =></span> {<br> <span class="hljs-built_in">console</span>.log(<span class="hljs-string">'onBeforeMount!'</span>)<br> })<br> onMounted(<span class="hljs-function"><span class="hljs-params">()</span> =></span> {<br> <span class="hljs-built_in">console</span>.log(<span class="hljs-string">'onMounted!'</span>)<br> })<br> updated(<span class="hljs-function"><span class="hljs-params">()</span> =></span> {<br> <span class="hljs-built_in">console</span>.log(<span class="hljs-string">'updated!'</span>)<br> }) <br>}<br></code></pre></td></tr></table></figure><p> 相关每个生命周期方法都是传入一个<code>function</code>函数。</p><p> <code>vue2.x</code>与新版<code>Composition API</code>之间的映射关系</p><ul><li><code>beforeCreate</code> -> <code>setup</code></li><li><code>created</code> -> <code>setup</code></li><li><code>beforeMount</code> -> <code>onBeforeMount</code></li><li><code>mounted</code> -> <code>onMounted</code></li><li><code>beforeUpdate</code> -> <code>onBeforeUpdate</code></li><li><code>updated</code> -> <code>onUpdated</code></li><li><code>beforeDestroy</code> -> <code>onBeforeUnmount</code></li><li><code>destroyed</code> -> <code>onUnmounted</code></li><li><code>errorCaptured</code> -> <code>onErrorCaptured</code></li></ul><h2 id="provide-amp-inject(数据共享)"><a href="#provide-amp-inject(数据共享)" class="headerlink" title="provide & inject(数据共享)"></a>provide & inject(数据共享)</h2><p><code>provide()</code>和 <code>inject()</code>可以实现嵌套组件之间的数据传递。这个两个函数只能在<code>setup()</code>函数中使用。父级组件中使用<code>provide()</code>函数可以使数据向下传递,子组件中使用<code>inject()</code>接收上层传过来的数据。</p><p>实现代码:</p><p>根组件(父组件)<code>parent.vue</code></p><figure class="highlight xml"><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></pre></td><td class="code"><pre><code class="hljs xml"><span class="hljs-tag"><<span class="hljs-name">template</span>></span><br> <span class="hljs-tag"><<span class="hljs-name">div</span>></span><br> <span class="hljs-tag"><<span class="hljs-name">child-one</span>></span><span class="hljs-tag"></<span class="hljs-name">child-one</span>></span><br> <span class="hljs-tag"><<span class="hljs-name">child-two</span>></span><span class="hljs-tag"></<span class="hljs-name">child-two</span>></span><br> <span class="hljs-tag"></<span class="hljs-name">div</span>></span><br><span class="hljs-tag"></<span class="hljs-name">template</span>></span><br><br><span class="hljs-tag"><<span class="hljs-name">script</span>></span><br><span class="javascript"> <span class="hljs-keyword">import</span> { provide } <span class="hljs-keyword">from</span> <span class="hljs-string">'@vue/composition-api'</span></span><br><span class="javascript"> <span class="hljs-keyword">import</span> ChildOne <span class="hljs-keyword">from</span> <span class="hljs-string">'@/components/Child'</span></span><br><span class="javascript"> <span class="hljs-keyword">import</span> ChildTwo <span class="hljs-keyword">from</span> <span class="hljs-string">'@/components/Child'</span></span><br><span class="javascript"> <span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> {</span><br> components: {<br> ChildOne,<br> ChildTwo<br> },<br> setup() {<br><span class="actionscript"> <span class="hljs-comment">// provide('要共享的数据名称', 被共享的数据)</span></span><br><span class="actionscript"> provide(<span class="hljs-string">'globalName'</span>, <span class="hljs-string">'vue'</span>) </span><br> }<br> }<br><br><span class="hljs-tag"></<span class="hljs-name">script</span>></span><br></code></pre></td></tr></table></figure><p>子组件1 <code>ChildOne.vue</code></p><figure class="highlight django"><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></pre></td><td class="code"><pre><code class="hljs django"><span class="xml"><span class="hljs-tag"><<span class="hljs-name">template</span>></span></span><br><span class="xml"> <span class="hljs-tag"><<span class="hljs-name">div</span>></span></span><br><span class="xml"> <span class="hljs-comment"><!--页面展示数据globalName --></span></span><br><span class="xml"> </span><span class="hljs-template-variable">{{globalName}}</span><span class="xml"> </span><br><span class="xml"> <span class="hljs-tag"></<span class="hljs-name">div</span>></span></span><br><span class="xml"><span class="hljs-tag"></<span class="hljs-name">template</span>></span></span><br><br><span class="xml"><span class="hljs-tag"><<span class="hljs-name">script</span>></span></span><br><span class="xml"> import { inject } from '@vue/composition-api'</span><br><span class="xml"> export default {</span><br><span class="xml"> name: 'ChildOne',</span><br><span class="xml"> setup() {</span><br><span class="xml"> const globalName = inject('globalName') 调用 inject 函数时,通过指定的数据名称,获取到父级共享的数据</span><br><span class="xml"> return {</span><br><span class="xml"> globalName</span><br><span class="xml"> }</span><br><span class="xml"> }</span><br><span class="xml"> }</span><br><span class="xml"><span class="hljs-tag"></<span class="hljs-name">script</span>></span></span><br></code></pre></td></tr></table></figure><p>子组件2 <code>ChildTwo.vue</code></p><figure class="highlight django"><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></pre></td><td class="code"><pre><code class="hljs django"><span class="xml"><span class="hljs-tag"><<span class="hljs-name">template</span>></span></span><br><span class="xml"> <span class="hljs-tag"><<span class="hljs-name">div</span>></span></span><br><span class="xml"> <span class="hljs-comment"><!--页面展示数据globalName --></span></span><br><span class="xml"> </span><span class="hljs-template-variable">{{globalName}}</span><span class="xml"> </span><br><span class="xml"> <span class="hljs-tag"></<span class="hljs-name">div</span>></span></span><br><span class="xml"><span class="hljs-tag"></<span class="hljs-name">template</span>></span></span><br><br><span class="xml"><span class="hljs-tag"><<span class="hljs-name">script</span>></span></span><br><span class="xml"> import { inject } from '@vue/composition-api'</span><br><span class="xml"> export default {</span><br><span class="xml"> name: 'ChildTwo',</span><br><span class="xml"> setup() {</span><br><span class="xml"> const globalName = inject('globalName') 调用 inject 函数时,通过指定的数据名称,获取到父级共享的数据</span><br><span class="xml"> return {</span><br><span class="xml"> globalName</span><br><span class="xml"> }</span><br><span class="xml"> }</span><br><span class="xml"> }</span><br><span class="xml"><span class="hljs-tag"></<span class="hljs-name">script</span>></span></span><br></code></pre></td></tr></table></figure><p><code>provide</code>函数被共享的数据可以使<code>ref</code>和<code>reactive</code>定义的响应式数据,用法类似</p><h2 id="template-refs(元素组件)"><a href="#template-refs(元素组件)" class="headerlink" title="template refs(元素组件)"></a>template refs(元素组件)</h2><p>我们知道在<code>vue2.x</code>中获取页面元素的<code>DOM</code>可以通过<code>ref</code>写在页面元素上然后在<code>js</code>中通过<code>$refs.x</code>来拿取当前元素的<code>DOM</code>元素信息,操作<code>DOM</code>,在<code>composition-api</code>中我们通过提供的<code>ref</code>方法传入一个<code>null</code>并且定义与页面元素上<code>ref</code>相对应。</p><p>代码实现: </p><figure class="highlight xml"><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></pre></td><td class="code"><pre><code class="hljs xml"><span class="hljs-tag"><<span class="hljs-name">template</span>></span><br> <span class="hljs-tag"><<span class="hljs-name">div</span>></span><br> <span class="hljs-tag"><<span class="hljs-name">h1</span> <span class="hljs-attr">ref</span>=<span class="hljs-string">"h1Ref"</span>></span>Hello Word<span class="hljs-tag"></<span class="hljs-name">h1</span>></span><br> <span class="hljs-tag"></<span class="hljs-name">div</span>></span><br><span class="hljs-tag"></<span class="hljs-name">template</span>></span><br><br><span class="hljs-tag"><<span class="hljs-name">script</span>></span><br><span class="javascript"><span class="hljs-keyword">import</span> { ref, onMounted } <span class="hljs-keyword">from</span> <span class="hljs-string">'@vue/composition-api'</span></span><br><br><span class="javascript"><span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> {</span><br> setup() {<br><span class="actionscript"> <span class="hljs-comment">// 创建一个 DOM 引用</span></span><br><span class="actionscript"> <span class="hljs-keyword">const</span> h1Ref = ref(<span class="hljs-literal">null</span>)</span><br><br><span class="actionscript"> <span class="hljs-comment">// 在 DOM 首次加载完毕之后,才能获取到元素的引用</span></span><br><span class="javascript"> onMounted(<span class="hljs-function"><span class="hljs-params">()</span> =></span> {</span><br><span class="actionscript"> <span class="hljs-comment">// 为 dom 元素设置字体颜色</span></span><br><span class="actionscript"> <span class="hljs-comment">// h1Ref.value 是原生DOM对象</span></span><br><span class="javascript"> <span class="hljs-built_in">console</span>.log(h1Ref.value)</span><br> })<br><br><span class="actionscript"> <span class="hljs-comment">// 把创建的引用 return 出去</span></span><br><span class="actionscript"> <span class="hljs-keyword">return</span> {</span><br> h1Ref<br> }<br> }<br>}<br><span class="hljs-tag"></<span class="hljs-name">script</span>></span><br></code></pre></td></tr></table></figure><h2 id="结尾"><a href="#结尾" class="headerlink" title="结尾"></a>结尾</h2><p>    感觉<code>composition-api</code>都是以导入的形式使用,感觉没有直接<code>vue2.x</code>中直接使用的方便哈😂。虽然都是说按需引入,使用想用的方法。对比了与<code>vue2.x</code>的各种写法感觉突然转过来有很大不适应,写的各种数据方法都要在<code>setup</code>的入口函数中导出才能在页面上使用。虽然<code>vue2.x</code>定义的数据也需要通过<code>data</code>函数返回值然后在页面中使用,但是方法不用啊,什么计算属性监听也都是不用的啊。可能是自己适应了<code>vue2.x</code>的各种写法,感觉用起来各种爽。转变到<code>vue3.x</code>也就是现在的<code>composition-api</code>还需要点时间。</p><p>最后自己还是有个问题没有解决有大佬给我思路吗?就是子父组件的通信怎么写?之前版本是通过<code>$emit</code>进行,我发现这<code>setup</code>函数中写了父组件拿不到。</p><p>最后贴上<code>composition-api</code>官方文档</p><p><a href="https://vue-composition-api-rfc.netlify.com" target="_blank" rel="noopener">https://vue-composition-api-rfc.netlify.com</a></p>]]></content>
<summary type="html">
<p><img src="https://user-gold-cdn.xitu.io/2020/1/13/16f9e71255c62bc0?w=299&h=300&f=png&s=43799" alt=""></p>
<h2 id="前言"><a href="#前言" class
</summary>
<category term="Web前端" scheme="http://jetBn.github.io/categories/Web%E5%89%8D%E7%AB%AF/"/>
<category term="Vue" scheme="http://jetBn.github.io/categories/Web%E5%89%8D%E7%AB%AF/Vue/"/>
<category term="Vue" scheme="http://jetBn.github.io/tags/Vue/"/>
</entry>
<entry>
<title>Shopify插件开发入坑体验</title>
<link href="http://jetbn.github.io/2020/04/29/Shopify%E6%8F%92%E4%BB%B6%E5%BC%80%E5%8F%91%E5%85%A5%E5%9D%91%E4%BD%93%E9%AA%8C/"/>
<id>http://jetbn.github.io/2020/04/29/Shopify%E6%8F%92%E4%BB%B6%E5%BC%80%E5%8F%91%E5%85%A5%E5%9D%91%E4%BD%93%E9%AA%8C/</id>
<published>2020-04-29T02:58:15.000Z</published>
<updated>2020-04-30T02:39:34.782Z</updated>
<content type="html"><<br> 然后在自己创建的应用中设置中添加`对应的url`(得用`https`的)就在上面所说的填写`url`<br> <br>5. 使用`node`的 `koa`来进行渲染页面操作<br> 1. 创建`env`环境变量文件并写入在上面创建的应用的`KEY`<br></code></pre></td></tr></table></figure><pre><code>SHOPIFY_API_KEY='YOUR API KEY FROM SHOPIFY PARTNERS DASHBOARD'SHOPIFY_API_SECRET_KEY='YOUR API SECRET KEY FROM SHOPIFY PARTNERS DASHBOARD' <figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs plain">2. 安装相关`Shopify`的验证`koa`中间件<br></code></pre></td></tr></table></figure>npm install --save koa @shopify/koa-shopify-auth dotenv koa-session isomorphic-fetch<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs plain">3. 创建`server.js`写入相关验证代码<br></code></pre></td></tr></table></figure>require('isomorphic-fetch');const dotenv = require('dotenv');const Koa = require('koa');const next = require('next');const { default: createShopifyAuth } = require('@shopify/koa-shopify-auth');const { verifyRequest } = require('@shopify/koa-shopify-auth');const session = require('koa-session');dotenv.config();// graphql的相关中间件const { default: graphQLProxy } = require('@shopify/koa-shopify-graphql-proxy'); const { ApiVersion } = require('@shopify/koa-shopify-graphql-proxy');const port = parseInt(process.env.PORT, 10) || 3000;const dev = process.env.NODE_ENV !== 'production';const app = next({ dev });const handle = app.getRequestHandler();const { SHOPIFY_API_SECRET_KEY, SHOPIFY_API_KEY } = process.env; // 环境变量里读取 api-key与api-secret-keyapp.prepare().then(() => { const server = new Koa(); server.use(session(server)); server.keys = [SHOPIFY_API_SECRET_KEY]; server.use( createShopifyAuth({ apiKey: SHOPIFY_API_KEY, secret: SHOPIFY_API_SECRET_KEY, scopes: ['read_products', 'write_products'], //填写相关应用api相关请求的权限 afterAuth(ctx) { const { shop, accessToken } = ctx.session; // 通过session拿取相关商店地址以及请求api需要的accessToken ctx.cookies.set('shopOrigin', shop, { httpOnly: false }); ctx.redirect('/'); // 重定向到index首页 }, }), ); server.use(verifyRequest()); server.use(async (ctx) => { await handle(ctx.req, ctx.res); ctx.respond = false; ctx.res.statusCode = 200; return }); server.use(graphQLProxy({version: ApiVersion.October19})) // 这里填写相关api的版本 server.listen(port, () => { console.log(`> Ready on http://localhost:${port}`); // 监听端口 });});<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs plain">4. 修改`package.json`文件使用我们的`server.js`来启动项目<br></code></pre></td></tr></table></figure>{ "scripts": { "test": "echo \"Error: no test specified\" && exit 1", "dev": "node server.js", "start": "NODE_ENV=production node server.js", "build": "next build", }}<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><code class="hljs plain">现在我们启动项目并且用`ngrok`暴露出去的域名就能看到<br><br><br>这里还要在域名的`shop`填写我们的商店地址例如我自己的:<br></code></pre></td></tr></table></figure>https://e44132cd.ngrok.io/auth/inline?shop=jetbn.myshopify.com<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></pre></td><td class="code"><pre><code class="hljs plain"> 一切填写就绪之后一`enter`页面就自动跳转了。<br> <br> 最后展示的页面:<br> <br><br>## 折腾其他框架尝试<br>&ensp;&ensp;&ensp;&ensp;前前后后都是使用`React`的`next.js`开发了两三个应用,感觉就是开发的时候太麻烦了,总要内网穿透,而且展示的页面都是`Shopify`的的自己平台上,而且开发写完代码等它响应过来还很慢。就这原因我又开始折腾了寻求其他的方案看看有没有能在自己开发完了再到它那上面,而且让验证`Shopify`的一系列操作让我们的后端小哥来操作。最终我前端选择`Vue`并且验证都放后端了,这样我就能像平常开发`Vue`项一样了。<br><br>下面介绍下我纯前端进行` Shopify`的验证操作使用`vue`。(前提要素内网穿透,不过开发的时候不需要)<br><br>1. 添加安装应用路由<br></code></pre></td></tr></table></figure></code></pre><p> {</p><pre><code>path: '/shopify/install',beforeEnter(to, _from, next) { if (to.query.shop) { //要在域名后添加开发的商店地址 const shop = to.query.shop, scopes = 'read_orders,read_products,write_products', // api权限 // 重定向地址就是在创建应用的时候填写的第二个(重定向URL可以自己随意写了),我这里是域名加/shopify/auth redirect_uri = 'https://' + process.env.VUE_APP_ROOT_URL + '/shopify/auth', // 拼接安装应用地址需要SHOPIFY_API_KEY我填写在我的.env文件中了 install_url = 'http://' + shop + '/admin/oauth/authorize?client_id=' + process.env.VUE_APP_SHOPIFY_API_KEY + '&scope=' + scopes + '&redirect_uri=' + redirect_uri // 本地跳转安装地址 window.location = install_url } else { next({ path: '/error' }) }}</code></pre><p> },</p> <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><code class="hljs plain"> <br>2. 重定向验证路由<br></code></pre></td></tr></table></figure><p> {</p><pre><code>path: '/shopify/auth',beforeEnter(to, _from, next) {// 通过回调的url获取相关的参数 const shop = to.query.shop, hmac = to.query.hmac, code = to.query.code// 使用SHOPIFY_API_SECRET_KEY验证 并且之后拿取access_token(这步没写) if (shop && hmac && code) { const map = Object.assign({}, to.query) delete map['signature'] delete map['hmac'] const message = querystring.stringify(map) const encrypted = crypto.createHmac('sha256', process.env.VUE_APP_SHOPIFY_API_SECRET_KEY) .update(message) .digest('hex') // const providedHmac = Buffer.from(hmac, 'utf-8') // const generatedHash = Buffer.from(encrypted, 'utf-8') let hashEquals = false try { // later: Auth fails with `crypto.timingSafeEqual` // hashEquals = crypto.timingSafeEqual(generatedHash, providedHmac) hashEquals = hmac === encrypted } catch (e) { hashEquals = false } if (!hashEquals) { next({ path: '/error' }) } else { next('/') } } else { next({ path: '/error' }) }}</code></pre><p> }</p><pre><code>`Vue`这相关的验证方案也是从`Github`上面捞的,特地记录下。具体地址忘了,有需要自己可以搜搜。🤣</code></pre></li></ol><h2 id="总结"><a href="#总结" class="headerlink" title="总结"></a>总结</h2><p>    经过一段时间的熟悉,自己也算又掌握一项新东西了。刚开始这个<code>Shopify</code>插件应用开发真的是巨坑啊,虽然官方有文档流程,但是都是英文的而且基础的搭建都是<code>api</code>都是用<code>GraphQL</code>然后我自己尝试了都是各种超时操作,请求不到最后就自己弃用了,用<code>ResfulApi</code>。然后就是遇到问题啊啥的都跟本搜不到,我想着这也太难了我,然后只能硬着头皮去官方文档里找,最后到现在也算是起起伏伏终于都熟悉了,搞懂了。</p><p>     这之后发现了英文水平太重要了。虽然开发文档基本内容能看懂,但是都是半猜半疑的,然后翻译一波。(各种不准确),然后开始补英文吧。🤞</p><p>     最后放上几个<code>Shopify</code>开发常用的官方文档地址:</p><p>    Shopify Partners(创建应用查看应用): <a href="https://vue-composition-api-rfc.netlify.com" target="_blank" rel="noopener">https://vue-composition-api-rfc.netlify.com</a></p><p>    Shopify Developers(官方开发文档): <a href="https://developers.shopify.com" target="_blank" rel="noopener">https://developers.shopify.com</a>(搭建参考文档)</p><p>    Shopify Polaris(官方UI框架): <a href="https://polaris.shopify.com" target="_blank" rel="noopener">https://developers.shopify.com</a></p>]]></content>
<summary type="html">
<p><img src="https://user-gold-cdn.xitu.io/2020/1/16/16facfbcc2c3ad20?w=500&h=144&f=png&s=18435" alt=""></p>
<h2 id="前言"><a href="#前言" class
</summary>
<category term="Web前端" scheme="http://jetBn.github.io/categories/Web%E5%89%8D%E7%AB%AF/"/>
<category term="React" scheme="http://jetBn.github.io/categories/Web%E5%89%8D%E7%AB%AF/React/"/>
<category term="Shopify" scheme="http://jetBn.github.io/tags/Shopify/"/>
<category term="React" scheme="http://jetBn.github.io/tags/React/"/>
<category term="Next.js" scheme="http://jetBn.github.io/tags/Next-js/"/>
</entry>
<entry>
<title>mpvue入坑记录</title>
<link href="http://jetbn.github.io/2020/04/29/mpvue%E5%85%A5%E5%9D%91%E8%AE%B0%E5%BD%95/"/>
<id>http://jetbn.github.io/2020/04/29/mpvue%E5%85%A5%E5%9D%91%E8%AE%B0%E5%BD%95/</id>
<published>2020-04-29T02:57:09.000Z</published>
<updated>2020-04-30T02:39:23.172Z</updated>
<content type="html"><![CDATA[<h2 id="使用MpVue开发小程序记录"><a href="#使用MpVue开发小程序记录" class="headerlink" title="使用MpVue开发小程序记录"></a>使用MpVue开发小程序记录</h2><p>        当下轻应用,遍布各大互联网公司。像百度、支付宝、微信、字节都是有自己的小程序形式,就现在QQ也推出了小程序的形式,像这种轻应用又不需要安装,就能打开,而且也类似了app形式。当然相对于形式也不能说不会开发吧,该学的还是得学。所以现在也有很多基于框架延伸而出的打包生成多个平台的小程序,例如 基于react的taro、还有wepy、mpvue目前应该这个三个最火热了,然后我尝试了mpvue开发了过程不说坑还是有的。自己也是一步步解决,所以决定记录一下。</p><ol><li><p>首先就搭建了项目使用相关环境自己也是全部尝试了一遍安装了<code>scss</code>环境以及<code>vuex</code>,好像有解决的<code>vue-router</code>自己没有尝试.</p><p>1.1 首先讲下<code>scss</code>的<code>mixin</code>我在全局的时候引入在页面页面中能用,为什么在组件中用不了这是啥我也不是清楚。还有就是我在<code>scss</code>中使用<code>font</code>字体的问题,在此中我通过本地的方式引入发现就是加载不了,后来寻找方案在交流群中得知是得将文件放在<code>static</code>文件下并且使用绝对路径的方式引用,是有效不报错了。但是小程序打包又上传了不了,后来我就直接干脆放服务器上了,再通过引用,这下总没问题了。</p><p>1.2 再次就是<code>vuex</code>在<code>main.js</code>中引用在<code>vue</code>的原型上加而不是像<code>vue-cli</code>中使用一样 直接写在<code>new VUE</code>中。</p><p>在main.js中定义</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><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></pre></td><td class="code"><pre><code class="hljs plain">import Vue from 'vue'<br>import App from './App'<br>import store from './store'<br><br>Vue.config.productionTip = false<br>App.mpType = 'app'<br>Vue.prototype.$store = store<br><br>const app = new Vue(App)<br>app.$mount()<br></code></pre></td></tr></table></figure><p>在页面中使用</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs plain">this.$store.state<br></code></pre></td></tr></table></figure><p>也可以使用vuex的mapState引用某个state</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><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><code class="hljs plain">// 头部导入<br>import { mapState } from 'vuex'<br><br>// 在计算属性中<br><br>...mapState([<br> 'carBrandCityPrev' // 对应stae中定义的<br>]),<br></code></pre></td></tr></table></figure></li><li><p>自定义TabBar自己刚开始使用也是一头水雾,微信小程序更新的很快。我之前写的一个小程序用的是原生开发的时候,那时候还没有什么定义TabBar啊、导航栏、组件啊什么的。后来我也是看了下官方的demo以及github中mpuve项目的issue中找解决方案,最终还是直接上手搞了一波。中途也是坎坎坷坷。</p><blockquote><p>贴个自定义tabbar地址: <a href="https://github.com/jetBn/mpvue-custom-tab-bar" target="_blank" rel="noopener">https://github.com/jetBn/mpvue-custom-tab-bar</a></p></blockquote></li><li><p>小程序中获取地理位置授权问题,只有在第一次进入的会提示是否授权如果拒绝了授权第二进入都不会授权,都会走授权位置的<code>fail</code>方法,所以这个原因问题。我们只能是通过微信的获取用户的当前设置检查 <code>wx.getSetting</code>api去检查当前是否授权,通过此方法放在<code>fail</code>方法中检测当前是否开启授权地理位置,如果没有重新调用地理位置授权的方法。</p><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><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><code class="hljs plain">// fn指相关重新授权的方法<br> export function checkGetLocationPermison (fn) {<br> wx.getSetting({<br> success: (res) => {<br> const status = res.authSetting<br> if (!status['scope.userLocation']) {<br> wx.showModal({<br> title: '是否授权当前位置',<br> content: '需要获取您的地理位置,请确认授权,否则地图功能将无法使用获取不了优惠券信息',<br> success: (subRes) => {<br> if (subRes.confirm) {<br> wx.openSetting({<br> success: (subRes) => {<br> if (subRes.authSetting['scope.userLocation'] === true) {<br> wx.showToast({<br> title: '授权成功',<br> icon: 'success',<br> duration: 1000<br> })<br> fn()<br> } else {<br> wx.showToast({<br> title: '授权失败',<br> icon: 'success',<br> duration: 1000<br> })<br> }<br> }<br> })<br> }<br> }<br> })<br> }<br> },<br> fail: () => {<br> wx.showToast({<br> title: '调用授权窗口失败',<br> icon: 'success',<br> duration: 1000<br> })<br> }<br> })<br> }<br></code></pre></td></tr></table></figure></li><li><p>在mpvue是axios全局处理请求返回值以及请求头设置等等。在<code>npm i axios qs</code>后新建<code>request.js</code>文件,引入<code>qs</code>处理<code>axios</code>中post请求,然后微信小程序中是使用<code>wx.request</code>发送请求的并不是直接使用axios就可以的,所以使用<code>axios</code>的<code>adapter</code> 属性进行我们的请求操作。</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><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></pre></td><td class="code"><pre><code class="hljs plain">// 创建axios实例<br>const Axios = axios.create({<br> baseURL: '', // 设置请求域名地址<br> timeout: 1000 * 60 * 10, // 设置请求超时时间<br> responseType: 'json' // 设置返回值类型<br>})<br><br><br>// 然后使用Axios实例的adapter进行封装微信请求<br>Axios.defaults.adapter = (config) => {<br> return new Promise((resolve, reject) => {<br> let data = config.method === 'get' ? config.params : qs.stringify(config.params)<br> wx.request({<br> url: config.url,<br> method: config.method,<br> header: {'Content-type': 'application/x-www-form-urlencoded'},<br> data,<br> success: (res) => (resolve(res)),<br> fail: (err) => (reject(err))<br> })<br> })<br>}<br><br>// 请求拦截<br>Axios.interceptors.request.use((request) => {<br> return request<br>}, (error) => {<br> return Promise.reject(error)<br>})<br><br>// 响应拦截<br>Axios.interceptors.response.use((response) => {<br> return response<br>}, (error) => {<br> return Promise.reject(error)<br>})<br><br>// 导出响应的方法<br>export function fetch (options) {<br> return new Promise((resolve, reject) => {<br> Axios(options)<br> .then(response => {<br> resolve(response)<br> })<br> .catch(error => {<br> reject(error)<br> })<br> })<br>}<br></code></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><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></pre></td><td class="code"><pre><code class="hljs plain">//微信获取相关设备信息的API<br>wx.getSystemInfo({<br> success (system) {<br> // console.log(`system:`, system)<br> self.statusBarHeight = system.statusBarHeight<br> self.platform = system.platform<br> const windowHeight = system.windowHeight<br> let platformReg = /ios/i<br> if (platformReg.test(system.platform)) {<br> self.titleBarHeight = 44 // iso的高度<br> } else {<br> self.titleBarHeight = 48 //android 的高度<br> }<br> self.navBarHeight = self.statusBarHeight + self.titleBarHeight<br> }<br>})<br></code></pre></td></tr></table></figure></li><li><p>mpvue中使用组件式封装 然后是内容使用插槽形式,在使用组件的使用插槽内的内容数据更新页面不会实时更新 。(父组件插槽内容块中使用的也是组件封装的组件)(问题1)。然后我使用了 不封装组件 直接写页面样式点击组件的事件会触发插槽中的事件???(问题2) 事件跟插槽中的事件不在同一个div中。最后就是不用插槽才解决了上述问题1,2</p></li><li><p><code>npm run dev</code> 会卡在<code>node build/dev-server.js wx</code> 最后我自己也是在官方的github仓库中的<code>issu</code>中找到解决方案在build文件夹的<code>build.js</code>中<code>require('./check-versions')()</code>注释掉然后也就能正常运行了。具体的好像是在经过<code>check-versions</code>函数的时候执行特别的慢。</p></li></ol><p>       最后总结下<code>MpVue</code>这个相对于<code>vue</code>针对于小程序的框架,大部分都是使用<code>vue</code>相关语法所以对于熟悉<code>vue</code>的来说还是很容易上手的。开发效率也还可以。感觉会使用<code>vue</code>再次熟悉微信小程序官方的API开发效率还是很高的,不过还是有挺多坑的,我这边坑可能是没有遇到很多。很幸运,具体的相关的语法情况可以对应官方网站的介绍情况。</p><p>       最后附上相关网站地址:</p><p>       官方网站:<a href="http://mpvue.com" target="_blank" rel="noopener">http://mpvue.com</a></p><p>       github相关仓库地址: <a href="https://github.com/Meituan-Dianping/mpvue" target="_blank" rel="noopener">https://github.com/Meituan-Dianping/mpvue</a></p>]]></content>
<summary type="html">
<h2 id="使用MpVue开发小程序记录"><a href="#使用MpVue开发小程序记录" class="headerlink" title="使用MpVue开发小程序记录"></a>使用MpVue开发小程序记录</h2><p>&#160; &#160; &#160; &
</summary>
<category term="Web前端" scheme="http://jetBn.github.io/categories/Web%E5%89%8D%E7%AB%AF/"/>
<category term="Vue" scheme="http://jetBn.github.io/categories/Web%E5%89%8D%E7%AB%AF/Vue/"/>
<category term="小程序" scheme="http://jetBn.github.io/categories/Web%E5%89%8D%E7%AB%AF/Vue/%E5%B0%8F%E7%A8%8B%E5%BA%8F/"/>
<category term="小程序" scheme="http://jetBn.github.io/tags/%E5%B0%8F%E7%A8%8B%E5%BA%8F/"/>
</entry>
</feed>