1 Star 0 Fork 0

Kaelinda/kaelindaTop

加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
文件
该仓库未声明开源许可证文件(LICENSE),使用请关注具体项目描述及其代码上游依赖。
克隆/下载
atom.xml 91.15 KB
一键复制 编辑 原始数据 按行查看 历史
zuosong 提交于 2019-03-12 15:13 . 2019-03-12 15:13:57
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985
<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
<title><![CDATA[kaelinda]]></title>
<link href="http://kaelinda.top/atom.xml" rel="self"/>
<link href="http://kaelinda.top/"/>
<updated>2018-09-27T13:54:50+08:00</updated>
<id>http://kaelinda.top/</id>
<author>
<name><![CDATA[]]></name>
</author>
<generator uri="http://www.mweb.im/">MWeb</generator>
<entry>
<title type="html"><![CDATA[OC中枚举写法 以及 字符串枚举探索]]></title>
<link href="http://kaelinda.top/15523077857608.html"/>
<updated>2019-03-11T20:36:25+08:00</updated>
<id>http://kaelinda.top/15523077857608.html</id>
<content type="html"><![CDATA[
<h2 id="toc_0">常见枚举写法</h2>
<h3 id="toc_1">C语言模式的枚举写法:enum</h3>
<pre><code class="language-text">typedef enum{
KLTypeRed = 1,
KLTypeGreen = 2,
KLTypeOrange = 3,
} KLType;
</code></pre>
<h3 id="toc_2">普通【整型】枚举写法 :NS_ENUM</h3>
<pre><code class="language-text">typedef NS_ENUM(NSUInteger, KLType) {
KLTypeRed = 1,
KLTypeGreen = 2,
KLTypeOrange = 3,
};
</code></pre>
<h3 id="toc_3">位移枚举 :NS_OPTIONS</h3>
<pre><code class="language-text">typedef NS_OPTIONS(NSUInteger, KLType) {
KLTypeRed = 1 &lt;&lt; 0,
KLTypeGreen = 1 &lt;&lt; 1,
KLTypeOrange = 1 &lt;&lt; 2,
};
</code></pre>
<h2 id="toc_4">字符串类型枚举实现方式探索</h2>
<h3 id="toc_5">基于普通枚举,定义C方法实现</h3>
<pre><code class="language-text">// 先定义一个常见的枚举
typedef NS_ENUM(NSUInteger, KLType) {
KLTypeRed = 1,
KLTypeGreen = 2,
KLTypeOrange = 3,
};
// 定义一个C方法,C方法就是通过枚举值匹配字符串
NSString *KLTypeString(KLType status) {
switch (status) {
case KLTypeRed:
return @&quot;红色&quot;;
case KLTypeGreen:
return @&quot;绿色&quot;;
case KLTypeOrange:
return @&quot;橘色&quot;;
default:
return @&quot;&quot;;
}
}
</code></pre>
<h3 id="toc_6">基于普通枚举,定义C数组,设置 枚举值为 index</h3>
<pre><code class="language-text">// 先定义一个常见的枚举
typedef NS_ENUM(NSUInteger, KLType) {
KLTypeRed = 1,
KLTypeGreen = 2,
KLTypeOrange = 3,
};
// 这个是 Map NSString * 类型的数组
NSString *KLTypeStringMap[] = {
[KLTypeRed] = @&quot;红色&quot;,
[KLTypeGreen] = @&quot;绿色&quot;,
[KLTypeOrange] = @&quot;橘色&quot;
};
// 使用:
KLTypeStringMap[KLTypeRed];// 枚举值
</code></pre>
<h3 id="toc_7">日常做法 宏定义</h3>
<pre><code class="language-text">#define static NSString * const KLTypeStringRed = @&quot;红色&quot;;
#define static NSString * const KLTypeStringGreen = @&quot;绿色&quot;;
#define static NSString * const KLTypeStringOrange = @&quot;橘色&quot;;
</code></pre>
<h3 id="toc_8">定义一种新的数据类型</h3>
<pre><code class="language-text">// 定义一个新的类型 是 NSSting * 类型 类型名字叫 KLTypeStr
typedef NSString *KLTypeStr NS_STRING_ENUM;
static KLTypeStr const KLTypeStringRed = @&quot;红色&quot;;
static KLTypeStr const KLTypeStringGreen = @&quot;绿色&quot;;
static KLTypeStr const KLTypeStringOrange = @&quot;橘色&quot;;
</code></pre>
<h3 id="toc_9">Apple官方的做法</h3>
<pre><code class="language-text">.h 文件中 -------------
typedef NSString *KLTypeStr NS_STRING_ENUM;
FOUNDATION_EXPORT KLTypeStr const KLTypeStringRed;
FOUNDATION_EXPORT KLTypeStr const KLTypeStringGreen;
FOUNDATION_EXPORT KLTypeStr const KLTypeStringOrange;
.m 文件中 --------------
NSString * const KLTypeStringRed = @&quot;红色&quot;;
NSString * const KLTypeStringGreen = @&quot;绿色&quot;;
NSString * const KLTypeStringOrange = @&quot;橘色&quot;;
</code></pre>
<blockquote>
<p>比较的时候 <code>StringEnum1 == StringEnum2</code> 直接比较的是内存地址,效率会更高。<br/>
相比会产生过多二进制文件的宏定义方式,假如宏定义比较多,建议用FOUNDATION_EXPORT。</p>
</blockquote>
]]></content>
</entry>
<entry>
<title type="html"><![CDATA[iOS 动画全解 (1)]]></title>
<link href="http://kaelinda.top/15522686353535.html"/>
<updated>2019-03-11T09:43:55+08:00</updated>
<id>http://kaelinda.top/15522686353535.html</id>
<content type="html"><![CDATA[
<h2 id="toc_0">iOS动画&quot;概述&quot;(瞎说一通)</h2>
<p>Apple 为开发者提供的视图动画框架有如下几种:</p>
<ul>
<li><code>UIKit</code>:高级别框架,允许程序员创建视图,窗口,按钮,和其他 UI 相关的控件。它也将低层的 API 组合到一个 易于使用的高级别 API 中。</li>
<li><code>Quartz 2D</code>:运行内部的用于 iOS 画图的主引擎;UIKit 使用了 Quarz。 重点在画图。</li>
<li><p><code>Core Graphics</code>(核心图层):加载图片,绘制图片等的框架重点在图形图片的渲染。</p></li>
<li><p><code>Core Animation</code>:iOS上的最基础的,应用最广泛的动画框架。(加载到CALayer上的动画)<br/>
<code>Core Animation</code> 其实是一个令人误解的命名。你可能认为它只是用来做动画的,但实际上它是从一个叫做<code>Layer Kit</code>这么一个不怎么和动画有关的名字演变而来,所以做动画这只是<code>Core Animation</code>特性的冰山一角。 <code>Core Animation</code>是一个复合引擎,它的职责就是尽可能快地组合屏幕上不同的可视内容,这个内容是被分解成独立的图层,存储在一个叫做图层树的体系之中。于是这个树形成了<code>UIKit</code>以及在iOS应用程序当中你所能在屏幕上 看见的一切的基础。</p></li>
</ul>
<h2 id="toc_1">CALayer 和 UIView</h2>
<h3 id="toc_2">CALayer</h3>
<p><code>CALayer</code> 类在概念上和 <code>UIView</code> 类似,同样也是一些被层级关系树管理的矩形块,同样也可以包含一些内 容(像图片,文本或者背景色),管理子图层的位置。它们有一些方法和属性用来做动画和变换。和 最 大的不同是<code>CALayer</code>不处理用户的交互。</p>
<h3 id="toc_3">平行的层级关系</h3>
<p>每一个<code>UIView</code>都有一个<code>CALayer</code>实例的图层属性,也就是所谓的<code>backing layer</code>,视图的职责就是创建并管理这个图层,以确保当子视图在层级关系中添加或者被移除的时候,他们关联的图层也同样对应在层级关系树当中有相同的操作。(可以理解为 UIViewController 和 VC.view的关系,只不过VC是UIView的管理调度者,UIView 是 CALayer的管理调度者)</p>
<h3 id="toc_4">CALayer的能力</h3>
<ul>
<li>阴影,圆角,带颜色的边框 • 3D变换</li>
<li>非矩形范围</li>
<li>透明遮罩</li>
<li><p>多级非线性动画</p></li>
<li><p>contents属性</p></li>
</ul>
]]></content>
</entry>
<entry>
<title type="html"><![CDATA[UITableView顶部空白的几种解决办法]]></title>
<link href="http://kaelinda.top/15501356584731.html"/>
<updated>2019-02-14T17:14:18+08:00</updated>
<id>http://kaelinda.top/15501356584731.html</id>
<content type="html"><![CDATA[
<ul>
<li><p>一、iOS7在Controller中增加了<code>automaticallyAdjustsScrollViewInsets</code>这个属性,当设置为YES时(默认YES),如果视图里面存在唯一一个UIScrollView或其子类View,那么它会自动设置相应的内边距,这样可以让scroll占据整个视图,又不会让导航栏遮盖。但是这个属性在iOS11之后被遗弃了,新增了一个<code>contentInsetAdjustmentBehavior</code>属性:</p>
<pre><code class="language-text">if (@available(iOS 11.0, *)) {        
self.tableview.contentInsetAdjustmentBehavior = UIScrollViewContentInsetAdjustmentNever;    <br/>
}else {<br/>
self.automaticallyAdjustsScrollViewInsets = NO;<br/>
}
</code></pre></li>
<li><p>二、UINavigationBar的透明度设置<code>self.navigationController.navigationBar.translucent = NO;</code><br/>
当这个属性设为NO时,tableview会在上方留出64.f的高度给navigationbar</p></li>
<li><p>三、tableView  </p>
<p>section的Header/Footer高度设置如果这个Header/Footer的height设置为0时,系统会认为你没有设置,从而给一个默认40的高度;若不需要显示这两个view,将他们的height设置一个无限小的数字即可,常用:CGFLOAT_MIN。</p>
<pre><code class="language-text">- (CGFloat)tableView:(UITableView*)tableView heightForHeaderInSection:(NSInteger)section{   
return CGFLOAT_MIN;<br/>
}
</code></pre></li>
<li><p>四、tableHeaderView、tableFooterView高度设置以下操作会导致tableView顶部空白:</p>
<pre><code class="language-text">self.tableView.tableHeaderView = nil; 
self.tableView.tableHeaderView = [[UIView alloc] init]; <br/>
self.tableView.tableHeaderView = [[UIView alloc] initWithFrame:CGRectZero]; 
</code></pre>
<p>同理,tableFooterView也是如此。footer和header只要设置了任意一个都会使两个地方都出现空白。应这样设置:</p>
<pre><code class="language-text">self.tableView.tableHeaderView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, SCREEN_WIDTH, CGFLOAT_MIN)]; 
self.tableView.tableFooterView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, SCREEN_WIDTH, CGFLOAT_MIN)];
</code></pre></li>
</ul>
]]></content>
</entry>
<entry>
<title type="html"><![CDATA[Objective-C中的字符串类型枚举 探索]]></title>
<link href="http://kaelinda.top/15488351784332.html"/>
<updated>2019-01-30T15:59:38+08:00</updated>
<id>http://kaelinda.top/15488351784332.html</id>
<content type="html"><![CDATA[
<p>实际开发中的iOSer会发现,有些情况我们需要字符串类型的枚举值。但是OC偏偏没有提供这种类型。Swift语言或者Java这些语言都有,于是我就有些不甘心了。经过一番探索,尝试了以下几种情况。</p>
]]></content>
</entry>
<entry>
<title type="html"><![CDATA[【Swift笔记】引用计数]]></title>
<link href="http://kaelinda.top/15409691048860.html"/>
<updated>2018-10-31T14:58:24+08:00</updated>
<id>http://kaelinda.top/15409691048860.html</id>
<content type="html"><![CDATA[
<ul>
<li>和OC一样,Swift也是用ARC,也会有循环引用导致内存泄露</li>
<li>吧如果属性是可选类型,只能用weak修饰符避免循环引用。所引用对象被回收后改属性会被自动置为nil</li>
<li>如果属性不是可选类型,只能用无主引用(unowned)。所引用对象被回收后属性不会被置为nil,此时访问会导致运行时错误。类似OC中的unsafe_unretained修饰符</li>
</ul>
]]></content>
</entry>
<entry>
<title type="html"><![CDATA[Swift中类(Class)和 结构体(Struct)]]></title>
<link href="http://kaelinda.top/15402889434646.html"/>
<updated>2018-10-23T18:02:23+08:00</updated>
<id>http://kaelinda.top/15402889434646.html</id>
<content type="html"><![CDATA[
<h2 id="toc_0">分析</h2>
<p>共同点:</p>
<ul>
<li>定义属性用于存储值</li>
<li>定义方法用于提供功能</li>
<li>定义下标操作使得可以通过下标语法来访问实例所包含的值</li>
<li>定义构造器用于生成初始化值</li>
<li>通过扩展以增加默认实现的功能</li>
<li>实现协议以提供某种标准功能</li>
</ul>
<p>与结构体相比,类还有如下的附加功能:</p>
<ul>
<li>继承允许一个类继承另一个类的特征</li>
<li>类型转换允许在运行时检查和解释一个类实例的类型</li>
<li>析构器允许一个类实例释放任何其所被分配的资源</li>
<li>引用计数允许对一个类的多次引用(对象引用)结构体总是通过被复制的方式在代码中传递,不使用引用计数。</li>
</ul>
<h2 id="toc_1">逐一对比</h2>
<h3 id="toc_2">定义</h3>
<pre><code class="language-text">//: ### 定义
class StudentClass{ }
struct StudebtStruct{ }
</code></pre>
<h3 id="toc_3">定义存储属性</h3>
<pre><code class="language-text">//: &gt; 类中定义的存储属性,如果不是可选类型,需要进行初始化;结构体则默认带有初始化方法
class StudentC01{
var name: String!
}
struct StudebtS01{
var name: String!
}
</code></pre>
<h3 id="toc_4">定义属性函数function</h3>
<p>关于@objc 请参考 <a href="https://blog.csdn.net/qq_35612929/article/details/79563110">Swift 4.0学习之:@objc的使用</a></p>
<pre><code class="language-text">//: ### 定义属性函数function
//: &gt; 类中可以使用 static 和 class两种修饰符;但是结构体中只能使用static修饰
class StudentC02{
static var des:String = &quot;学生的类&quot;
var name:String!
@objc class func objc_describe()-&gt;String{
return des
}
class func class_describe()-&gt;String{
return des
}
static func static_describe()-&gt;String{
return des
}
}
struct StudentS02{
static var des:String = &quot;学生的结构体&quot;
var name:String!
static func describe()-&gt;String{
return &quot;这是一个定义学生的类&quot;
}
}
</code></pre>
<h3 id="toc_5">扩展下标</h3>
<pre><code class="language-text">//: ### 扩展下标
//: &gt; *subscript*
class StudentC003{
var names:[String] = [&quot;1&quot;,&quot;2&quot;,&quot;3&quot;,&quot;4&quot;,&quot;5&quot;]
subscript (index:Int)-&gt;String?{
get{
if names.count &lt;= index{
return nil
}
return names[index]
}
}
}
struct StudentS003{
var names:[String] = [&quot;1&quot;,&quot;2&quot;,&quot;3&quot;,&quot;4&quot;,&quot;5&quot;]
subscript (index:Int)-&gt;String?{
get{
if names.count &lt;= index{
return nil
}
return names[index]
}
}
}
let sc003 = StudentC003()
sc003[1]// 2
let ss003 = StudentS003()
ss003[1]// 2
</code></pre>
<h3 id="toc_6">初始化</h3>
<pre><code class="language-text">//: ### 初始化
//: &gt; 结构体自带初始化方法(可以不写初始化方法);
//: &gt; 类必须手写init方法,否则报错;
class StudentC004{
var name:String
init(name:String) {
self.name = name
}
}
struct StudentS004 {
var name:String
}
let studentc004 = StudentC004(name: &quot;行走在北方&quot;)
let students004 = StudentS004(name: &quot;行走在北方&quot;)
</code></pre>
<h3 id="toc_7">扩展功能 Extention</h3>
<pre><code class="language-text">//: ### 扩展功能 Extention
extension StudentC004{
func discribe() -&gt; String {
return &quot;student class:&quot;+self.name
}
}
extension StudentS004{
func discribe() -&gt; String {
return &quot;student struct:&quot; + self.name
}
}
</code></pre>
<h3 id="toc_8">实现协议 protocol</h3>
<pre><code class="language-text">//: ### 实现协议 protocol
//: * 定义协议
protocol Capacity {
func draw()//协议方法
}
//: * 实现协议方法
class StudentC05:Capacity{
internal func draw() {
}
var name:String
init(name:String) {
self.name = name
}
}
struct StudentS05:Capacity{
internal func draw() {
}
var name:String
}
</code></pre>
<h3 id="toc_9">mutating 关键字的使用</h3>
<p>科普下:</p>
<ul>
<li><p>枚举和结构体都是值类型,Swift默认值类型的对象方法不能修改属性值,但是如果一定要修改 那就在函数前面添加mutating关键字</p></li>
<li><p>计算属性setter方法中不需要更改属性值的时候,不需要添加mutating关键字;</p></li>
<li><p>计算属性setter方法中更改属性值的时候,必须要添加mutating关键字</p></li>
</ul>
<pre><code class="language-text">protocol Action{
var myY:Int{
mutating get
}
}
struct Point {
var x:Int
var y:Int
mutating func modifyX(x: Int){
self.x = x
}
var myY:Int{
mutating get {//getter方法前面添加mutating关键字
self.y = self.y*2
return y
}
}
}
class ActionClass {
var name:String?
init(name:String) {
self.name = name
}
var myName:String? {
get {// class 是对象类型 可以直接修改
self.name = &quot;666 -&gt; :&quot; + self.name!
return self.name
}
}
}
let actionclass = ActionClass(name: &quot;NB&quot;)
</code></pre>
<h2 id="toc_10">判断两个对象地址是否相同(验证 引用类型 和 值类型)</h2>
<pre><code class="language-text">//: ### 判断两个对象地址是否相同
//: &gt; 类是引用类型;结构体是值类型;结构体不能通过=== 、!==类判断比较
//: &gt;
class StudentC07{
var name: String
init(name:String) {
self.name = name
}
}
let studentc071 = StudentC07(name: &quot;原始名字&quot;)
var studentc072 = studentc071
studentc071.name = &quot;新名字&quot;
print(&quot;student071:\(studentc071.name)\nstudent072:\(studentc072.name)&quot;)
if studentc071 === studentc072 {
print(&quot;类是引用类型,最终指向同一块内存&quot;)
}
struct StudentS07{
var name: String
init(name:String) {
self.name = name
}
}
let students071 = StudentS07(name: &quot;结构体:原始名字&quot;)
var students072 = students071
students072.name = &quot;结构体:新名字&quot;
print(&quot;students071:\(students071.name)\nstudents072\(students072.name)&quot;)
</code></pre>
<h3 id="toc_11">deinit 释放资源</h3>
<p><a href="https://www.jianshu.com/p/9e725362eeb1">Swift中的deinit方法</a></p>
<pre><code class="language-text">//: ### deinit 释放资源
//: &gt; 类有deinit方法;结构体中没有deinit方法。
class StudentC08{
var name: String
init(name:String) {
self.name = name
}
deinit {
//这里释放资源
}
}
</code></pre>
<h3 id="toc_12">lazy:延迟属性(懒加载)</h3>
<p>class 有延迟属性;struct没有延迟属性</p>
<pre><code class="language-text">//: &gt; 延迟存储属性是指当第一次被调用的时候才会计算其初始值的属性。在属性声明前使用 lazy 来标示一个延迟存储属性
class Importor{
var fileName = &quot;data.txt&quot;
}
class DataManager{
lazy var importor = Importor()
var Data = [String]()
}
</code></pre>
<h3 id="toc_13">继承</h3>
<pre><code class="language-text">//: ### 继承
//: &gt; 类能继承;结构体不能继承。
class Person{
var name:String
init(name:String) {
self.name = name
}
}
class Student06: Person {
var score : Float
init(name: String, score: Float){
self.score = score//先给父类中没有的属性赋值,再调用父类init方法
super.init(name: name)
}
}
</code></pre>
<ul>
<li><p>继承之后 可重写父类方法/属性</p>
<ol>
<li><p>重写计算属性:只能增加功能不能减少功能——&gt;父类中有setter getter,那么子类重写计算属性 setter getter都必须要有。父类中只有setter 子类中可以在重写setter的同时增加getter</p></li>
<li><p>final 关键字可以让属性不被重写 或者 继承</p></li>
</ol></li>
</ul>
<pre><code class="language-text">//: * 重写计算属性
//: * 重写对象方法
//: * 重写类方法
//: * 重写初始化方法
//: * 重写存储属性
//: _父类_
class Person{
//存储属性
var name:String = &quot;person&quot;
//计算属性
var rename:String{
return self.name
}
//初始化方法
init(_ name:String) {
self.name = name
}
//对象方法
func describe() -&gt; String {
return self.name
}
//类方法
class func describeClass()-&gt;String{
return &quot;这是一个描述人的类&quot;
}
}
//: _子类_
class Man: Person {
//重写存储属性
override var name: String{
didSet{
print(&quot;man 对象中 name 的原始值:\(self.name)&quot;)
self.name = &quot;man:&quot;+self.name
}
}
var score : Double
//重写setter getter
override var rename: String{
set{
self.name = &quot;man:&quot;+newValue
}
get{
return &quot;_&quot;+self.name
}
}
//重写初始化方法
override init(_ name: String) {
self.score = 0.0
super.init(name)
}
//重写对象方法
override func describe() -&gt; String {
return self.name + &quot;_score:\(self.score)&quot;
}
// 重写类方法
override class func describeClass() -&gt; String {
return &quot;我是描述男人的类&quot;
}
}
var man00 = Man(&quot;kael&quot;)
print(man00.name)
</code></pre>
<h3 id="toc_14">class 的类型检测</h3>
<ol>
<li>首先在自己的初始化方法中先给自己的属性初始化</li>
<li>然后调用父类的初始化</li>
<li>最后修改父类的属性</li>
</ol>
<pre><code class="language-text">//: ### 类型检测 is as?
var person01 = Person(&quot;person01&quot;)
var man01 = Man(&quot;man01&quot;)
if person01 is Person {
print(&quot;person01:我是Person&quot;)
}else{
print(&quot;person01:我不是Person&quot;)
}
if person01 is Man {
print(&quot;person01:我是Man&quot;)
}else{
print(&quot;person01:我不是Man&quot;)
}
if man01 is Person {
print(&quot;man01:我是Person&quot;)
}else{
print(&quot;man01:我不是Person&quot;)
}
if man01 is Man {
print(&quot;man01:我是Man&quot;)
}else{
print(&quot;man01:我不是Man&quot;)
}
if let p = person01 as? Person {
print(&quot;person01 是 Person&quot;)
}
if let p = person01 as? Man{
print(&quot;person01 是Man&quot;)
}else{
print(&quot;person01 不是Man&quot;)
}
if let p = man01 as? Person {
print(&quot;man01 是 Person&quot;)
}
if let p = man01 as? Man{
print(&quot;man01 是Man&quot;)
}else{
print(&quot;man01 不是Man&quot;)
}
</code></pre>
]]></content>
</entry>
<entry>
<title type="html"><![CDATA[网络是怎样连接的]]></title>
<link href="http://kaelinda.top/15341646765442.html"/>
<updated>2018-08-13T20:51:16+08:00</updated>
<id>http://kaelinda.top/15341646765442.html</id>
<content type="html"><![CDATA[
<h2 id="toc_0">生成HTTP请求信息</h2>
<p>URL种类:<code>http:</code> <code>ftp:</code> <code>file:</code> <code>mailto:</code> <code>news:</code></p>
<p>URL组成:协议 + 用户名(可省略) + 密码(省略) + 服务器域名 + 端口号(可省略) + 文件路径名</p>
<p><img src="https://ws2.sinaimg.cn/large/0069RVTdly1fu8d5d2w7jj313e19atf8.jpg" alt=""/></p>
<h3 id="toc_1">网络请求</h3>
<p><img src="https://ws1.sinaimg.cn/large/0069RVTdly1fu8fexsc00j313a10ewp6.jpg" alt=""/></p>
<h3 id="toc_2">HTTP</h3>
<ul>
<li><code>URI</code>:Uniform Resource Identifier,统一资源标识符</li>
<li><code>CGI</code>:对 Web 服务器程序调用其他程序的规则所做的定义就是 CGI</li>
</ul>
<h3 id="toc_3">DNS服务器</h3>
<p>DNS查询服务包含下面三部分:</p>
<ul>
<li><code>域名</code>:服务器、邮件服务器(邮件地址中 @ 后面的部分)的名称</li>
<li><code>Class</code>:在最早设计 DNS 方案时,DNS 在互联网以外的其他网络中的应用也被考虑到了,而 Class 就是用来识别网络的信息。不过,如今除了互联网并没有其他的网络了,因此 Class 的值永远是代表互联网的 IN</li>
<li><code>记录类型</code>:表示域名对应何种类型的记录。例如,当类型为 A 时,表示域名 对应的是 IP 地址;当类型为 MX 时,表示域名对应的是邮件服务 器。对于不同的记录类型,服务器向客户端返回的信息也会不同</li>
</ul>
<p><img src="https://ws2.sinaimg.cn/large/0069RVTdly1fubcsxb3lzj318812ualm.jpg" alt="DNS服务器的基本工作"/></p>
<p><strong>敲黑板,划重点!!!</strong></p>
<blockquote>
<p>上级 DNS 服务器保管着所有下级 DNS 服务器的信息,所以我们可以从根域开始一路往下顺藤摸瓜找到任意 一个域的 DNS 服务器;<br/>
根域的 DNS 服务器信息保存在互联网中所有的 DNS 服务器中,任何 DNS 服务器就都可 以找到并访问根域 DNS 服务器了。</p>
</blockquote>
<p>协议栈传输数据:</p>
<ol>
<li>服务器一方创建套接字,等待客户端向该套接字连接管道 (创建套接字阶段)</li>
<li>客户端创建一个套接字,然后从该套接字伸出管道去连接服务端的套接字 (创建套接字阶段 、连接套接字阶段)</li>
<li>客户端套接字 和 服务端套接字建立连接以后就可以传输网络数据了(数字信息 digital data)(通信阶段)</li>
<li>断开通道、删除套接字 (断开阶段)</li>
</ol>
<p><img src="https://ws4.sinaimg.cn/large/006tNbRwly1fup9h6snmhj316s0zg7ah.jpg" alt=""/></p>
<ul>
<li>描述符:应用程序用来识别套接字的机制</li>
<li>IP 地址和端口号:客户端和服务器之间用来识别对方套接字的机制
<img src="https://ws2.sinaimg.cn/large/006tNbRwly1fupfvmg5jwj31j40x60xr.jpg" alt=""/></li>
</ul>
]]></content>
</entry>
<entry>
<title type="html"><![CDATA[Alfred workflow 教程]]></title>
<link href="http://kaelinda.top/15282021908171.html"/>
<updated>2018-06-05T20:36:30+08:00</updated>
<id>http://kaelinda.top/15282021908171.html</id>
<content type="html"><![CDATA[
<h2 id="toc_0">简介</h2>
<blockquote>
<p>新创建一个空白的workflow<br/>
<img src="https://ws1.sinaimg.cn/large/006tKfTcly1fs193q68k7j30we0kawh2.jpg" alt=""/><br/>
<img src="https://ws3.sinaimg.cn/large/006tKfTcly1fs194xjqm9j30k804g0t0.jpg" alt=""/></p>
<ul>
<li>1.workflow 名字</li>
<li>2.workflow功能描述</li>
<li>3.Category:workflow的类别 工具 网络 或者别的分类</li>
<li>4.唯一标识</li>
<li>5.作者</li>
<li>6.网站</li>
</ul>
<p>空白区,点击鼠标右键<br/>
<img src="https://ws3.sinaimg.cn/large/006tKfTcly1fs0l0zl2crj307e0bydgg.jpg" alt=""/></p>
<p>知识点:{query} 可以接收上个模块的输出参数<br/>
如果是输出多个参数,那就是{var:var1,var:var2}</p>
</blockquote>
<h2 id="toc_1">Triggers 触发器</h2>
<p><img src="https://ws4.sinaimg.cn/large/006tKfTcly1fs0ljq33rnj30g20c20ua.jpg" alt=""/></p>
<h3 id="toc_2">Hotkey 热键触发</h3>
<p><img src="https://ws4.sinaimg.cn/large/006tKfTcly1fs16vk8gidj30to0n4tc1.jpg" alt=""/><br/>
<img src="https://ws2.sinaimg.cn/large/006tKfTcly1fs16yvki0ej30jy04qdgs.jpg" alt=""/><br/>
<img src="https://ws1.sinaimg.cn/large/006tKfTcly1fs16zp561fj30my05yt9m.jpg" alt=""/></p>
<ul>
<li>Hotkey: 热键设置触发 选中后可以设置激活热键组合</li>
<li><p>Action: 行为 </p>
<ul>
<li>Pass through to workflow</li>
<li>Show Alfred</li>
</ul>
<blockquote>
<p>当热键被按下时该怎么做。注意,如果你选择“show alfred”。即使连接成功,则不会从该处理器的输出中输出任何内容。</p>
</blockquote></li>
<li><p>Argument:</p>
<ul>
<li>none:什么都没有</li>
<li>selection in macOS: 电脑中选中的内容</li>
<li>MacOS Clipboard Content:电脑粘贴板内容</li>
<li>Text: 输入文本</li>
</ul></li>
<li><p>prefix :前缀</p>
<blockquote>
<p>Argument是一个可选参数,如果输入的是文本那么会动态的添加prefix配置的前缀。</p>
</blockquote></li>
</ul>
<h3 id="toc_3">Remote 远程触发</h3>
<blockquote>
<p>注意,这个触发器对象与远程对象是分离的。这里提供的图像和名称是建议默认的,并在使用中复制到Remote中。只要保持标识符的一致性,就可以删除和替换对象。</p>
</blockquote>
<p><img src="https://ws4.sinaimg.cn/large/006tKfTcly1fs17yod1hlj30vq0k20wk.jpg" alt=""/></p>
<ul>
<li>1.这是自定制的要触发的workflow 的 icon</li>
<li>2.这是按钮上的button上的文字</li>
<li>3.这个触发器内部使用的唯一标识符,通过远程标识要运行哪个触发器。</li>
<li>4.触发器携带参数</li>
<li>5.触发器携带参数前缀</li>
<li>6.此触发器仅可用于添加到此工作流中的远程页面,而不能用于一般的远程页面。</li>
</ul>
<h3 id="toc_4">Snippet 片段触发</h3>
<p><img src="https://ws4.sinaimg.cn/large/006tNc79ly1fs3mx57k39j30qa0j4wh3.jpg" alt=""/></p>
<ul>
<li>1.关键字:</li>
<li>关注APP的变量</li>
<li></li>
</ul>
<h3 id="toc_5">External 扩展触发</h3>
<p>触发该触发器后会执行一段Applescript 脚本</p>
<p><img src="https://ws3.sinaimg.cn/large/006tNc79ly1fs3pxvlwyvj30ui0futb2.jpg" alt=""/></p>
<ul>
<li>1.identifier : 触发ID</li>
<li>2.简单脚本</li>
</ul>
<h3 id="toc_6">Connect Action</h3>
<p>联系人Action,这个具体干什么笔者也没搞清楚。</p>
<h3 id="toc_7">Fallback search</h3>
<blockquote>
<p>select the title and subtext you would like to use for this keyword based input.<br/>
these represent the text you see in Alfred’s results when using the keyword.</p>
</blockquote>
<p>选择您希望用于这个基于关键字的输入的标题和字幕。这些代表在使用关键字时在Alfred的结果中看到的文本。</p>
<h2 id="toc_8">Inputs 输入</h2>
<p><img src="https://ws3.sinaimg.cn/large/006tKfTcly1fs0ll364vbj30f80bymye.jpg" alt=""/></p>
<h3 id="toc_9">关键字</h3>
<p><img src="https://ws3.sinaimg.cn/large/006tNc79ly1fs3qapb1rnj30qw0f277f.jpg" alt=""/></p>
<ul>
<li>1.keyword:激活改Action的关键字</li>
<li>2.是否需要参数:require-必须传入参数 optional-可选 NO argument-不需要参数</li>
<li>3.action 标题</li>
<li>4.action的副标题</li>
<li>5.可以自定制的icon</li>
</ul>
<h3 id="toc_10">文件过滤器</h3>
<p><img src="https://ws2.sinaimg.cn/large/006tNc79ly1fs3qecoaf0j31060ogtc1.jpg" alt=""/></p>
<ul>
<li>1.keyword:激活改Action的关键字</li>
<li>2.默认提示字符标题</li>
<li>3.默认提示字符副标题</li>
<li>4.文件类型 右下角+号可以添加文件类型</li>
</ul>
<p><img src="https://ws1.sinaimg.cn/large/006tNc79ly1fs3qykwxjqj31060ogdis.jpg" alt=""/></p>
<p>Search Scope 设置的是可搜索范围。需要手动将文件夹拖入条目范围中,即可。</p>
<p><img src="https://ws2.sinaimg.cn/large/006tNc79ly1fs3qzl6u7nj31060o6te8.jpg" alt=""/></p>
<p><img src="https://ws4.sinaimg.cn/large/006tNc79ly1fs3wm2d3mfj316u0ocjzc.jpg" alt=""/></p>
<ul>
<li>1.日期搜索范围设置 任意日期,今天,三天内,七天内,30天内,超过30天</li>
<li>2.文件排序方式设置 名字</li>
</ul>
<h3 id="toc_11">语言过滤器</h3>
<p>预言过滤 具体也不知道能干啥。</p>
<p><img src="https://ws2.sinaimg.cn/large/006tNc79ly1fs3r25at3ij30v00h8tbm.jpg" alt=""/></p>
<h3 id="toc_12">List过滤器</h3>
<p><img src="https://ws4.sinaimg.cn/large/006tNc79ly1fs3r5fichuj31bs0u6gsx.jpg" alt=""/></p>
<p>这就相当于 编程预言里面的 <code>switch case</code></p>
<ul>
<li>1.关键字</li>
<li>2.模块标题</li>
<li>3.模块的subtitle</li>
<li>4.参数配置:require-必须传参 optional-可选 No argument-不需要参数</li>
<li>5.该模块的icon设置</li>
<li>6.list:输入关键字后会出现这个list </li>
<li>7.list子模块title</li>
<li>8.子模块的subtitle</li>
<li>9.选中子模块后输出的参数</li>
<li>10.list中的子模块排序方式 一种是一直保持固定排序;另一种是Alfred自己学习根据使用频率 进行排序</li>
</ul>
<h3 id="toc_13">Script filter 脚本过滤器</h3>
<p><img src="https://ws4.sinaimg.cn/large/006tNc79ly1fs3zcesy1gj317e0zmjwi.jpg" alt=""/></p>
<h2 id="toc_14">Action 行为</h2>
<p><img src="https://ws3.sinaimg.cn/large/006tKfTcly1fs0llhujngj30go0g840r.jpg" alt=""/></p>
<h3 id="toc_15">打开文件</h3>
<p>用某个APP打开指定文件。</p>
<p><img src="https://ws4.sinaimg.cn/large/006tNc79ly1fs3zldzgjzj30yw0rw778.jpg" alt=""/></p>
<h3 id="toc_16">Reveal file in the finder 打开文件所在位置</h3>
<h3 id="toc_17">browse in Alfred</h3>
<h3 id="toc_18">Launch APPs</h3>
<h3 id="toc_19">Default web search</h3>
<p><img src="https://ws4.sinaimg.cn/large/006tNc79ly1fs3zrfdl12j30ma0aidha.jpg" alt=""/></p>
<h3 id="toc_20">open URL</h3>
<p><img src="https://ws1.sinaimg.cn/large/006tNc79ly1fs3zvl5nuwj30zk0didj1.jpg" alt=""/></p>
<h3 id="toc_21">System Command</h3>
<p><img src="https://ws1.sinaimg.cn/large/006tNc79ly1fs3zz6vwjxj30q00judkl.jpg" alt=""/></p>
<h3 id="toc_22">iTunes Command</h3>
<p><img src="https://ws2.sinaimg.cn/large/006tNc79ly1fs3zzs0mrnj30no0ig42v.jpg" alt=""/></p>
<h3 id="toc_23">Terminal Command</h3>
<p>通过终端APP 运行终端命令组件</p>
<h3 id="toc_24">Run Script</h3>
<p>运行脚本</p>
<h3 id="toc_25">Run NSAppleScript</h3>
<p>运行apple 脚本</p>
<h2 id="toc_26">Utilities 实用工具</h2>
<p><img src="https://ws4.sinaimg.cn/large/006tKfTcly1fs16kjx74kj30e60fojsx.jpg" alt=""/></p>
<h3 id="toc_27">Arg and Vars</h3>
<p><img src="https://ws3.sinaimg.cn/large/006tNc79ly1fs403j1t5aj30ws0nqmzg.jpg" alt=""/></p>
<h3 id="toc_28">JSON Config</h3>
<p>通过输入的参数 自行组合成自己想要的json文本</p>
<h3 id="toc_29">Junction 结点</h3>
<p>这个只是处理复杂逻辑的节点。如果线条逻辑过多 错综复杂的时候 可以通过节点来处理。</p>
<h3 id="toc_30">Filter</h3>
<h3 id="toc_31">Delay</h3>
<h3 id="toc_32">Transform</h3>
<h3 id="toc_33">Replace</h3>
<h3 id="toc_34">Hide Alfred</h3>
<h3 id="toc_35">Debug</h3>
<h2 id="toc_36">Outputs 输出</h2>
<p><img src="https://ws2.sinaimg.cn/large/006tKfTcly1fs16lacns8j30h60eqtai.jpg" alt=""/></p>
<h3 id="toc_37">Post Notification 发送本地通知</h3>
<p>发送本地通知。Alfred 3 的本地推送不好用,一直没成功。</p>
<h3 id="toc_38">Large Type 大文字显示</h3>
<p>大文字显示 一些文本。</p>
<h3 id="toc_39">Copy to Clipboard copy文本到粘贴板</h3>
<p>复制结果到粘贴板</p>
<h3 id="toc_40">Write Text File 把text写入文件</h3>
<p>将text文本写入文件</p>
<h3 id="toc_41">Play Sound 播放声音</h3>
<p>播放声音</p>
<h3 id="toc_42">Dispath Key Combo 按键连击</h3>
<h3 id="toc_43">Call External trigger 触发别的触发器</h3>
]]></content>
</entry>
<entry>
<title type="html"><![CDATA[每天学习一个shell技能(8)]]></title>
<link href="http://kaelinda.top/15232599795686.html"/>
<updated>2018-04-09T15:46:19+08:00</updated>
<id>http://kaelinda.top/15232599795686.html</id>
<content type="html"><![CDATA[
<h2 id="toc_0">shell 终端打印</h2>
<pre><code class="language-text">```
printf &quot;%-5s %-10s %-4s \n&quot; NO Name Mark
printf &quot;%-5s %-10s %-4s \n&quot; 1 kael 100
printf &quot;%-5s %-10s %-4s \n&quot; 2 linda 99
printf &quot;%-5s %-10s %-4s \n&quot; 3 rouse 98
// 打印结果
NO Name Mark
1 kael 100
2 linda 99
3 rouse 98
```
</code></pre>
<blockquote>
<p>printf 行尾 默认自带换行 \n</p>
</blockquote>
<ul>
<li>%-5s : 左对齐,宽度为5的字符串替换;默认右对齐</li>
<li>%-4.2f:指定保留2位小数</li>
</ul>
]]></content>
</entry>
<entry>
<title type="html"><![CDATA[每天学习一个shell技能(7)]]></title>
<link href="http://kaelinda.top/15226648731246.html"/>
<updated>2018-04-02T18:27:53+08:00</updated>
<id>http://kaelinda.top/15226648731246.html</id>
<content type="html"><![CDATA[
<h2 id="toc_0">文件包含 导入文件</h2>
<p>测试文件 test1.sh</p>
<pre><code class="language-text">#!/bin/bash
# author:菜鸟教程
# url:www.runoob.com
url=&quot;http://www.runoob.com&quot;
</code></pre>
<p>测试文件 test2.sh</p>
<pre><code class="language-text">#!/bin/bash
# author:菜鸟教程
# url:www.runoob.com
#使用 . 号来引用test1.sh 文件
. ./test1.sh
# 或者使用以下包含文件代码
# source ./test1.sh
echo &quot;菜鸟教程官网地址:$url&quot;
</code></pre>
<span id="more"></span><!-- more -->
<pre><code class="language-text">$ chmod +x test2.sh
$ ./test2.sh
菜鸟教程官网地址:http://www.runoob.com
</code></pre>
<h2 id="toc_1">输入/输出 重定向</h2>
<table>
<thead>
<tr>
<th style="text-align: center">命令</th>
<th style="text-align: center">说明</th>
</tr>
</thead>
<tbody>
<tr>
<td style="text-align: center">command &gt; file</td>
<td style="text-align: center">先清空文件中内容,将输出重定向到文件</td>
</tr>
<tr>
<td style="text-align: center">command &lt; file</td>
<td style="text-align: center">将输入重定向到文件</td>
</tr>
<tr>
<td style="text-align: center">command &gt;&gt; file</td>
<td style="text-align: center">将输出以追加的形式重定向到file</td>
</tr>
<tr>
<td style="text-align: center">N &gt; file</td>
<td style="text-align: center">将描述符为N的文件,重定向到文件file</td>
</tr>
<tr>
<td style="text-align: center">N &gt;&gt; file</td>
<td style="text-align: center">将描述符为N的文件,追加到file</td>
</tr>
<tr>
<td style="text-align: center">n&gt;&amp;m</td>
<td style="text-align: center">将输出文件m 和  n合并</td>
</tr>
<tr>
<td style="text-align: center">n&lt;&amp;m</td>
<td style="text-align: center">将输入文件m 和 n合并</td>
</tr>
<tr>
<td style="text-align: center">&lt;&lt;tag</td>
<td style="text-align: center">将开始标记为tag何结尾标记为tag 之间的内容作为输入</td>
</tr>
</tbody>
</table>
]]></content>
</entry>
<entry>
<title type="html"><![CDATA[每天学习一个shell技能(6)]]></title>
<link href="http://kaelinda.top/15226603064743.html"/>
<updated>2018-04-02T17:11:46+08:00</updated>
<id>http://kaelinda.top/15226603064743.html</id>
<content type="html"><![CDATA[
<h2 id="toc_0">test</h2>
<h3 id="toc_1">test文件</h3>
<pre><code class="language-text">if test -e ./test.sh
then
echo &#39;文件已存在!&#39;
else
echo &#39;文件不存在!&#39;
fi
</code></pre>
<ul>
<li>-e fileName : 如果文件存在则为真</li>
<li>-r fileName : 如果文件存在且可读则为真</li>
<li>-w fileName : 如果文件存在且可写则为真</li>
<li>-x fileName : 如果文件存在且可执行则为真</li>
<li>-s fileName: 文件存在且至少有一个字符</li>
<li>-d fileName : 文件存在且为目录</li>
<li>-f fileName: 文件存在且为文件</li>
<li>-c fileName:文件存在,且为字符型特殊文件</li>
<li>-b fileName: 如果文件存在且为块特殊文件则为真</li>
</ul>
<span id="more"></span><!-- more -->
<h3 id="toc_2">test字符串</h3>
<ul>
<li>= :等于则为真</li>
<li>!= :不等于则为真</li>
<li>-z : 字符串长度为零则为真</li>
<li>-n : 字符串长度不为零则为真</li>
</ul>
<h3 id="toc_3">数值测试</h3>
<ul>
<li>-eq :等于</li>
<li>-ne : 不等于</li>
<li>-gt:大于</li>
<li>-lt:小于</li>
<li>-ge:大于等于</li>
<li>-le: 小于等于</li>
</ul>
<h2 id="toc_4">流程控制(条件)</h2>
<h3 id="toc_5">if</h3>
<pre><code class="language-text">if condition
then
command1
command2
...
commandN
fi
</code></pre>
<h3 id="toc_6">if else</h3>
<pre><code class="language-text">if condition
then
command1
command2
...
commandN
else
command
fi
</code></pre>
<h3 id="toc_7">if else-if else</h3>
<pre><code class="language-text">if condition1
then
command1
elif condition2
then
command2
else
commandN
fi
</code></pre>
<p>实例 用法:</p>
<pre><code class="language-text">a=10
b=20
if [ $a == $b ]
then
echo &quot;a 等于 b&quot;
elif [ $a -gt $b ]
then
echo &quot;a 大于 b&quot;
elif [ $a -lt $b ]
then
echo &quot;a 小于 b&quot;
else
echo &quot;没有符合的条件&quot;
fi
</code></pre>
<h2 id="toc_8">控制流(for 循环)</h2>
<pre><code class="language-text">for var in item1 item2 ... itemN
do
command1
command2
...
commandN
done
</code></pre>
<p>改成一行:</p>
<pre><code class="language-text">for var in item1 item2 ... itemN; do command1; command2… done;
</code></pre>
<h2 id="toc_9">while</h2>
<pre><code class="language-text">while condition
do
command
done
</code></pre>
<pre><code class="language-text">int=1
while(( $int&lt;=5 ))
do
echo $int
let &quot;int++&quot;
done
</code></pre>
<p>无限循环:</p>
<pre><code class="language-text">while :
do
command
done
// 或者
while true
do
command
done
// 或者
for (( ; ; ))
</code></pre>
<h2 id="toc_10">until 循环</h2>
<pre><code class="language-text">until condition
do
command
done
</code></pre>
<h2 id="toc_11">case in</h2>
<pre><code class="language-text">case 值 in
模式1)
command1
command2
...
commandN
;;
模式2)
command1
command2
...
commandN
;;
esac
</code></pre>
<h2 id="toc_12">跳出循环</h2>
<h3 id="toc_13">break</h3>
<blockquote>
<p>break命令允许跳出所有循环(终止执行后面的所有循环)</p>
</blockquote>
<h3 id="toc_14">continue</h3>
<blockquote>
<p>continue命令与break命令类似,只有一点差别,它不会跳出所有循环,仅仅跳出当前循环</p>
</blockquote>
<pre><code class="language-text">while :
do
echo -n &quot;输入 1 到 5 之间的数字: &quot;
read aNum
case $aNum in
1|2|3|4|5) echo &quot;你输入的数字为 $aNum!&quot;
;;
*) echo &quot;你输入的数字不是 1 到 5 之间的!&quot;
continue
echo &quot;游戏结束&quot;
;;
esac
done
</code></pre>
<h3 id="toc_15">esac</h3>
<blockquote>
<p>case的语法和C family语言差别很大,它需要一个esac(就是case反过来)作为结束标记,每个case分支用右圆括号,用两个分号表示break。</p>
</blockquote>
]]></content>
</entry>
<entry>
<title type="html"><![CDATA[每天学习一个shell技能(5)]]></title>
<link href="http://kaelinda.top/15224936933861.html"/>
<updated>2018-03-31T18:54:53+08:00</updated>
<id>http://kaelinda.top/15224936933861.html</id>
<content type="html"><![CDATA[
<h2 id="toc_0">Shell echo命令</h2>
<h3 id="toc_1">打印字符</h3>
<pre><code class="language-text">// 下面两行代码效果一致
echo &quot;It is a test&quot;
echo It is a test
</code></pre>
<h3 id="toc_2">打印转义字符</h3>
<pre><code class="language-text">echo &quot;\&quot;It is a test\&quot;&quot;
// 引号也可以省略
echo \&quot;It is a test\&quot;
</code></pre>
<p>打印结果:</p>
<pre><code class="language-text">&quot;It is a test&quot;
&quot;It is a test&quot;
</code></pre>
<span id="more"></span><!-- more -->
<h3 id="toc_3">打印 隐藏 换行</h3>
<pre><code class="language-text">// 显示换行
echo -e &quot;OK! \n&quot; # -e 开启转义
echo &quot;It it a test&quot;
// 不显示换行
echo -e &quot;OK! \c&quot; # -e 开启转义 \c 不换行
echo &quot;It is a test&quot;
</code></pre>
<h3 id="toc_4">显示结果定向至文件</h3>
<pre><code class="language-text">echo &quot;It is a test&quot; &gt; myfile
</code></pre>
<h3 id="toc_5">原样显示字符 不进行转义</h3>
<pre><code class="language-text">echo &#39;$name\&quot;&#39;
// 输出结果: $name\&quot;
</code></pre>
<h2 id="toc_6">录入参数</h2>
<pre><code class="language-text">read -p &quot;请输入一段文字:&quot; -n 6 -t 5 -s password
echo &quot;\npassword is $password&quot;
</code></pre>
<ul>
<li> -p 输入提示文字</li>
<li>-n 输入字符长度限制(达到6位,自动结束)</li>
<li>-t 输入限时</li>
<li>-s 隐藏输入内容</li>
</ul>
]]></content>
</entry>
<entry>
<title type="html"><![CDATA[每天学习一个shell技能(4)]]></title>
<link href="http://kaelinda.top/15224613481161.html"/>
<updated>2018-03-31T09:55:48+08:00</updated>
<id>http://kaelinda.top/15224613481161.html</id>
<content type="html"><![CDATA[
<h2 id="toc_0">shell基本运算符</h2>
<p>基本使用:</p>
<pre><code class="language-text">#!/bin/bash
val=`expr 2 + 2`
echo &quot;两数之和为 : $val&quot;
</code></pre>
<ul>
<li>表达式和运算符之间要有空格,例如 2+2 是不对的,必须写成 2 + 2,这与我们熟悉的大多数编程语言不一样</li>
<li>完整的表达式要被 ` ` 包含,注意这个字符不是常用的单引号,在 Esc 键下边</li>
</ul>
<span id="more"></span><!-- more -->
<h3 id="toc_1">算术运算符</h3>
<table>
<thead>
<tr>
<th style="text-align: center">运算符</th>
<th style="text-align: center">说明</th>
<th style="text-align: center">举例</th>
</tr>
</thead>
<tbody>
<tr>
<td style="text-align: center">+</td>
<td style="text-align: center">加法</td>
<td style="text-align: center">`expr $a + $b` 结果为 30。</td>
</tr>
<tr>
<td style="text-align: center">-</td>
<td style="text-align: center">减法</td>
<td style="text-align: center">`expr $a - $b` 结果为 -10。</td>
</tr>
<tr>
<td style="text-align: center">*</td>
<td style="text-align: center">乘法</td>
<td style="text-align: center">`expr $a * $b` 结果为  200。</td>
</tr>
<tr>
<td style="text-align: center">/</td>
<td style="text-align: center">除法</td>
<td style="text-align: center">`expr $b / $a` 结果为 2。</td>
</tr>
<tr>
<td style="text-align: center">%</td>
<td style="text-align: center">取余</td>
<td style="text-align: center">`expr $b % $a` 结果为 0。</td>
</tr>
<tr>
<td style="text-align: center">=</td>
<td style="text-align: center">赋值</td>
<td style="text-align: center">a=$b 将把变量 b 的值赋给 a。</td>
</tr>
<tr>
<td style="text-align: center">==</td>
<td style="text-align: center">相等</td>
<td style="text-align: center">[ \(a == \)b ] 返回 false。</td>
</tr>
<tr>
<td style="text-align: center">!=</td>
<td style="text-align: center">不相等</td>
<td style="text-align: center">[ \(a != \)b ] 返回 true。</td>
</tr>
</tbody>
</table>
<blockquote>
<p>条件表达式要放在方括号之间,并且要有空格,例如: [\(a==\)b] 是错误的,必须写成 [ \(a == \)b ]</p>
</blockquote>
<pre><code class="language-text">a=10
b=20
val=`expr $a + $b`
echo &quot;a + b : $val&quot;
val=`expr $a - $b`
echo &quot;a - b : $val&quot;
val=`expr $a \* $b`
echo &quot;a * b : $val&quot;
val=`expr $b / $a`
echo &quot;b / a : $val&quot;
val=`expr $b % $a`
echo &quot;b % a : $val&quot;
if [ $a == $b ]
then
echo &quot;a 等于 b&quot;
fi
if [ $a != $b ]
then
echo &quot;a 不等于 b&quot;
fi
</code></pre>
<h3 id="toc_2">关系运算符</h3>
<ul>
<li>-eq: 是否等于</li>
<li>-ne: 是否不等于</li>
<li>-gt: 是否大于</li>
<li>-lt: 是否小于</li>
<li>-ge: 是否大于等于</li>
<li>-le: 是否小于等于</li>
</ul>
<hr/>
<blockquote>
<p>EQ 就是 EQUAL等于<br/>
NE 就是 NOT EQUAL不等于 <br/>
GT 就是 GREATER THAN大于  <br/>
LT 就是 LESS THAN小于 <br/>
GE 就是 GREATER THAN OR EQUAL 大于等于 <br/>
LE 就是 LESS THAN OR EQUAL 小于等于</p>
</blockquote>
<hr/>
<pre><code class="language-text">a=10
b=20
if [ $a -eq $b ]
then
echo &quot;$a -eq $b : a 等于 b&quot;
else
echo &quot;$a -eq $b: a 不等于 b&quot;
fi
if [ $a -ne $b ]
then
echo &quot;$a -ne $b: a 不等于 b&quot;
else
echo &quot;$a -ne $b : a 等于 b&quot;
fi
if [ $a -gt $b ]
then
echo &quot;$a -gt $b: a 大于 b&quot;
else
echo &quot;$a -gt $b: a 不大于 b&quot;
fi
if [ $a -lt $b ]
then
echo &quot;$a -lt $b: a 小于 b&quot;
else
echo &quot;$a -lt $b: a 不小于 b&quot;
fi
if [ $a -ge $b ]
then
echo &quot;$a -ge $b: a 大于或等于 b&quot;
else
echo &quot;$a -ge $b: a 小于 b&quot;
fi
if [ $a -le $b ]
then
echo &quot;$a -le $b: a 小于或等于 b&quot;
else
echo &quot;$a -le $b: a 大于 b&quot;
fi
</code></pre>
<h3 id="toc_3">布尔运算符</h3>
<ul>
<li>!: 非运算</li>
<li>-o: 或运算</li>
<li>-a: 与运算</li>
</ul>
<h3 id="toc_4">逻辑运算符</h3>
<ul>
<li>&amp;&amp;:与</li>
<li>||:或</li>
</ul>
<h3 id="toc_5">字符串运算</h3>
<pre><code class="language-text">a=&quot;abc&quot;
b=&quot;efg&quot;
if [ $a = $b ]
then
echo &quot;$a = $b : a 等于 b&quot;
else
echo &quot;$a = $b: a 不等于 b&quot;
fi
if [ $a != $b ]
then
echo &quot;$a != $b : a 不等于 b&quot;
else
echo &quot;$a != $b: a 等于 b&quot;
fi
if [ -z $a ]
then
echo &quot;-z $a : 字符串长度为 0&quot;
else
echo &quot;-z $a : 字符串长度不为 0&quot;
fi
if [ -n $a ]
then
echo &quot;-n $a : 字符串长度不为 0&quot;
else
echo &quot;-n $a : 字符串长度为 0&quot;
fi
if [ $a ]
then
echo &quot;$a : 字符串不为空&quot;
else
echo &quot;$a : 字符串为空&quot;
fi
</code></pre>
]]></content>
</entry>
<entry>
<title type="html"><![CDATA[每天学习一个shell技能 (3)]]></title>
<link href="http://kaelinda.top/15223750607281.html"/>
<updated>2018-03-30T09:57:40+08:00</updated>
<id>http://kaelinda.top/15223750607281.html</id>
<content type="html"><![CDATA[
<h2 id="toc_0">shell参数传递</h2>
<p>我们可以在脚本执行时,向脚本传递参数</p>
<pre><code class="language-text">// 终端运行 脚本,并传入参数
sh testBash.sh 0 1 2
echo &quot;Shell 传递参数实例!&quot;
echo &quot;\$0 =&gt; $0&quot;
echo &quot;\$1 =&gt; $1&quot;
</code></pre>
<p>打印结果:</p>
<pre><code class="language-text">Shell 传递参数实例!
$0 =&gt; testBash.sh
$1 =&gt; 0
</code></pre>
<span id="more"></span><!-- more -->
<table>
<thead>
<tr>
<th style="text-align: center">参数处理</th>
<th style="text-align: center">参数说明</th>
</tr>
</thead>
<tbody>
<tr>
<td style="text-align: center">$#</td>
<td style="text-align: center">传递到脚本的参数个数</td>
</tr>
<tr>
<td style="text-align: center">$*</td>
<td style="text-align: center">以一个单字符串显示所有向脚本传递的参数</td>
</tr>
<tr>
<td style="text-align: center">$$</td>
<td style="text-align: center">脚本运行的当前进程ID号</td>
</tr>
<tr>
<td style="text-align: center">$!</td>
<td style="text-align: center">后台运行的最后一个进程的ID号</td>
</tr>
<tr>
<td style="text-align: center">$@</td>
<td style="text-align: center">与$*相同,但是使用时加引号,并在引号中返回每个参数</td>
</tr>
<tr>
<td style="text-align: center">$-</td>
<td style="text-align: center">显示Shell使用的当前选项</td>
</tr>
<tr>
<td style="text-align: center">$?</td>
<td style="text-align: center">显示最后命令的退出状态。0表示没有错误,其他任何值表明有错误</td>
</tr>
</tbody>
</table>
<pre><code class="language-text">// 运行脚本
sh testBash.sh 0 1 2
</code></pre>
<pre><code class="language-text">echo &quot;\$0 =&gt; $0&quot;
echo &quot;\$1 =&gt; $1&quot;
echo &quot;\$@ =&gt; $@&quot;
echo &quot;\$* =&gt; $*&quot;
echo &quot;\$\$ =&gt; $$&quot;
echo &quot;\$! =&gt; $!&quot;
echo &quot;\$- =&gt; $-&quot;
echo &quot;\$? =&gt; $?&quot;
echo &quot;\$*传递的参数作为一个字符串显示:$*&quot;
echo &quot;\$@是作为一个数组返回 =&gt; $@&quot;
</code></pre>
<p>打印结果:</p>
<pre><code class="language-text">$0 =&gt; testBash.sh
$1 =&gt; 0
$@ =&gt; 0 1 2
$* =&gt; 0 1 2
$$ =&gt; 18859
$! =&gt;
$- =&gt; hB
$? =&gt; 0
$*传递的参数作为一个字符串显示:0 1 2
$@是作为一个数组返回 =&gt; 0 1 2
</code></pre>
]]></content>
</entry>
<entry>
<title type="html"><![CDATA[每天学习一个shell技能 (1)]]></title>
<link href="http://kaelinda.top/15223028228569.html"/>
<updated>2018-03-29T13:53:42+08:00</updated>
<id>http://kaelinda.top/15223028228569.html</id>
<content type="html"><![CDATA[
<h2 id="toc_0">准备</h2>
<p>bash 环境位置</p>
<pre><code class="language-text">#!/bin/bash
</code></pre>
<p><code>#!</code> 一个约定的标记,它告诉系统这个脚本需要什么解释器来执行,即使用哪一种 Shell</p>
<span id="more"></span><!-- more -->
<h2 id="toc_1">运行shell</h2>
<ol>
<li><p>作为可执行程序</p>
<pre><code class="language-shell">chmod +x ./mybash.sh
./mybash.sh
</code></pre></li>
<li><p>作为解释器参数</p></li>
</ol>
<pre><code class="language-text">/bin/bash test.sh
/bin/php test.php
// 如果这样运行,文件内的第一行就可以不需要指定 解释器信息了
</code></pre>
<h2 id="toc_2">pwd</h2>
<ol>
<li><p>命令简介</p>
<p><code>pwd</code> :打印当前目录 ,命令以 <code>绝对路径</code> 的形式显示用户的 当前工作目录</p></li>
<li><p>用法</p>
<p><code>pwd [-LP]</code></p></li>
</ol>
<h2 id="toc_3">变量</h2>
<h3 id="toc_4">定义变量</h3>
<ul>
<li>定义变量时 不需要制定 <code>$</code>符号</li>
<li>变量名和值、等号之间不能有空格</li>
</ul>
<p><strong>命名规范:</strong></p>
<ul>
<li>命名只能使用英文字母,数字和下划线,首个字符不能以数字开头</li>
<li>中间不能有空格,可以使用下划线(_)</li>
<li>不能使用标点符号</li>
<li>不能使用bash里的关键字(可用help命令查看保留关键字)</li>
</ul>
<pre><code class="language-shell">user_name=&#39;kael linda&#39;
</code></pre>
<h3 id="toc_5">使用变量</h3>
<p>使用时,变量名前面加上<code>$</code>符号即可</p>
<pre><code class="language-text">your_name=&quot;qinjx&quot;
echo $your_name
echo ${your_name}
</code></pre>
<p>花体括号 加不加都行,视情况而定。<br/>
加是为了区分变量边界</p>
<pre><code class="language-text">user_name=&quot;kaelinda&quot;
echo &quot;I&#39;m ${user_name}&#39; brother&quot;
</code></pre>
<h3 id="toc_6">只读变量</h3>
<pre><code class="language-text">user_name=&quot;kaelinda&quot;
readonly user_name
user_name=&quot;kael&quot;
</code></pre>
<h3 id="toc_7">删除变量</h3>
<pre><code class="language-text">unset variable_name
</code></pre>
<ul>
<li>删除变量删除之后的变量不可再使用</li>
<li>unset 命令不能删除只读变量</li>
</ul>
<h3 id="toc_8">变量类型</h3>
<ul>
<li>局部变量 局部变量在脚本或命令中定义,仅在当前shell实例中有效,其他shell启动的程序不能访问局部变量。</li>
<li>环境变量 所有的程序,包括shell启动的程序,都能访问环境变量,有些程序需要环境变量来保证其正常运行。必要的时候shell脚本也可以定义环境变量。</li>
<li>shell变量 shell变量是由shell程序设置的特殊变量。shell变量中有一部分是环境变量,有一部分是局部变量,这些变量保证了shell的正常运行</li>
</ul>
<h2 id="toc_9">shell 字符串</h2>
<h3 id="toc_10">单引号</h3>
<pre><code class="language-text">str=&#39;this is a string&#39;
</code></pre>
<ul>
<li>单引号里的任何字符都会原样输出,单引号字符串中的变量是无效的</li>
<li>单引号字串中不能出现单引号(对单引号使用转义符后也不行)</li>
</ul>
<h3 id="toc_11">双引号</h3>
<pre><code class="language-text">your_name=&#39;qinjx&#39;
str=&quot;Hello, I know your are \&quot;$your_name\&quot;! \n&quot;
</code></pre>
<ul>
<li>双引号里可以有变量</li>
<li>双引号里可以出现转义字符</li>
</ul>
<h3 id="toc_12">拼接字符串</h3>
<pre><code class="language-text">your_name=&quot;qinjx&quot;
greeting=&quot;hello, &quot;$your_name&quot; !&quot;
greeting_1=&quot;hello, ${your_name} !&quot;
</code></pre>
<h3 id="toc_13">获取字符串长度</h3>
<pre><code class="language-text">string=&quot;abcd&quot;
echo ${#string} #输出 4
</code></pre>
<h3 id="toc_14">提取字符串</h3>
<pre><code class="language-text">string=&quot;runoob is a great site&quot;
echo ${string:1:4} # 输出 unoo
</code></pre>
<h3 id="toc_15">查找字符串位置</h3>
<pre><code class="language-text">string=&quot;runoob is a great company&quot;
echo `expr index &quot;$string&quot; is` # 输出 8
</code></pre>
<blockquote>
<p>以上脚本中 &quot;`&quot; 是反引号,而不是单引号 &quot;&#39;&quot;,不要看错了. 这是用了正则表达式匹配字符</p>
</blockquote>
]]></content>
</entry>
<entry>
<title type="html"><![CDATA[每天学习一个shell 技能 (2)]]></title>
<link href="http://kaelinda.top/15223210751913.html"/>
<updated>2018-03-29T18:57:55+08:00</updated>
<id>http://kaelinda.top/15223210751913.html</id>
<content type="html"><![CDATA[
<h2 id="toc_0">Shell 数组</h2>
<h3 id="toc_1">定义数组</h3>
<pre><code class="language-bash">array_name=(value1 value2 value3)
array_name2=(
value1
value2
value3
)
// 单独定义某个分量的值
array_name(0)=value0
</code></pre>
<span id="more"></span><!-- more -->
<h3 id="toc_2">读取数组</h3>
<pre><code class="language-text">// 读取单个元素
value0=${array_name[0]}
//使用@符号可以获取数组中的所有元素
echo ${array_name(@)}
</code></pre>
<h3 id="toc_3">获取数组的长度</h3>
<pre><code class="language-text">// 获取元素个数
length=${#array_name[@]}
//或者
length=${#array_name[*]}
// 获取的单个元素的长度
item_length=${#array_name[n]}
</code></pre>
<h2 id="toc_4">Shell 注释</h2>
<blockquote>
<p>&quot;#&quot;开头的行就是注释,会被解释器忽略。sh里没有多行注释,只能每一行加一个#号。只能像这样</p>
</blockquote>
<pre><code class="language-text">#--------------------------------------------
# 这是一个注释
# author:菜鸟教程
# site:www.runoob.com
# slogan:学的不仅是技术,更是梦想!
#--------------------------------------------
##### 用户配置区 开始 #####
#
#
# 这里可以添加脚本描述信息
#
#
##### 用户配置区 结束 #####
</code></pre>
]]></content>
</entry>
<entry>
<title type="html"><![CDATA[从零开始学习使用 vuex]]></title>
<link href="http://kaelinda.top/15168925544178.html"/>
<updated>2018-01-25T23:02:34+08:00</updated>
<id>http://kaelinda.top/15168925544178.html</id>
<content type="html"><![CDATA[
<blockquote>
<p>本文是建立在,对vuex理论有一定理解的基础上写的。<br/>
因为官方文档的写法是 针对 有一定的vue开发经验 和 JavaScript 有一定理解的开发者看的,对于小白级别的我来说,理解起来有一定困难。所以,唯一想我一向的小白想尽快上手vuex....</p>
</blockquote>
<p><a href="https://vuex.vuejs.org/zh-cn/installation.html">详情请参考vuex官方文档</a></p>
<h2 id="toc_0">安装</h2>
<h3 id="toc_1">直接下载 CDN 安装</h3>
<p>CDN 链接地址:<code>https://unpkg.com/vuex</code><br/>
指定到固定版本:<code>https://unpkg.com/vuex@2.0.0</code></p>
<pre><code class="language-text">&lt;script src=&quot;/path/to/vue.js&quot;&gt;&lt;/script&gt;
&lt;script src=&quot;/path/to/vuex.js&quot;&gt;&lt;/script&gt;
</code></pre>
<h3 id="toc_2">npm 方式安装 (推荐!简单快捷,便于管理)</h3>
<p><code>npm install -save vuex</code></p>
<h3 id="toc_3">yar</h3>
<p><code>yarn add vuex</code></p>
<h3 id="toc_4">自己构建</h3>
<pre><code class="language-bash">git clone https://github.com/vuejs/vuex.git node_modules/vuex
cd node_modules/vuex
npm install
npm run build
</code></pre>
<h2 id="toc_5">导入vue工程中使用</h2>
<ul>
<li>main.js 入口文件</li>
</ul>
<blockquote>
<p>按照如下方式导入,工程就可以使用vuex的环境了</p>
</blockquote>
<pre><code class="language-javascript">// 导入vuex头文件
import Vuex from &#39;vuex&#39;
// 这里表示全局导入vuex
Vue.use(Vuex)
// 这里是我自定义的store文件 导出store对象
import store from &#39;@/study/vuexStudy/store/store.js&#39;
</code></pre>
<blockquote>
<p>入口组件<App/>中,绑定store</p>
</blockquote>
<pre><code class="language-text">new Vue({
el: &#39;#app&#39;,
template: &#39;&lt;App/&gt;&#39;,
components: { App },
store
})
</code></pre>
<p>到这里 算是万里长征走了第一步。</p>
<h3 id="toc_6">创建Store对象</h3>
<h4 id="toc_7">store 的结构:</h4>
<pre><code class="language-javascript">export const store = new Vuex.Store({
// ------state:状态值存储,这里可以存储n个状态的值
state: {count: &#39;1&#39;},
// ------getter:store中定义的getters可以认为是store的计算属性
// getters接收state作为其第一个参数
getters: {
done (state) {
return state.count + 5
}
},
// ------mutations:状态值的改变,操作状态值
// $store.commit(mutationsName, params)是更改状态值的唯一方法
mutations: {
increment (state) {
// 变更状态
state.count++
}
},
// ------actions:可以认为是包装了mutations的function 需要用 dispatch(actionName) 的方式去派发
actions: {
add (context) {
context.commit(&#39;increment&#39;)
},
addAsync (context) {
// 延时1秒
setTimeout(() =&gt; {
context.commit(&#39;increment&#39;)
}, 1000)
}
},
// store可以合并几个子store,以此来进行项目的模块化
modules: {
a: moduleA,
b: moduleB
}
})
</code></pre>
<h4 id="toc_8">编辑定义store实体对象:</h4>
<ul>
<li>store.js文件中</li>
</ul>
<blockquote>
<p>这里为了便于抽离 我们外部声明城对象实体后嵌入绑定到store</p>
</blockquote>
<ol>
<li><p>创建一个store对象</p>
<pre><code class="language-javascript">export default const store = new Vuex.Store({
state,//绑定之前创建的state对象到store中<br/>
mutations,<br/>
getters,<br/>
actions,<br/>
modules<br/>
})
</code></pre></li>
<li><p>定义一个状态对象 <code>state</code>(实体)</p>
<pre><code class="language-javascript">const state = {
count: 0,<br/>
state1: 1,<br/>
state2: 2,<br/>
state3: 3<br/>
}
</code></pre></li>
<li><p>定义getters对象</p>
<pre><code class="language-text">const getters = {
done (state) {<br/>
return state.count + 5<br/>
},<br/>
getState1: function (state) {<br/>
return state.state3<br/>
},<br/>
// ES6简写<br/>
getState2: state =&gt; state.state2<br/>
}
</code></pre></li>
<li><p>.vue 文件中直接获取state值</p>
<p>首先导入辅助函数:</p>
<pre><code class="language-text">import {
mapState, <br/>
mapGetters, <br/>
mapMutations, <br/>
mapActions <br/>
} from &#39;vuex&#39;
</code></pre>
<ul>
<li>第一种方式:绑定到组件属性中,直接获取 (一般不用这个,绑定到computed中是最合适的)<code>$store.state.count</code>并使用</li>
</ul>
<pre><code class="language-javascript">export default {
data() {<br/>
return {<br/>
testCount: this.$store.state.count<br/>
}<br/>
}<br/>
}
</code></pre>
<ul>
<li>第二种方式: 绑定到计算属性中(适合对store中的原始状态值进行一定处理的情况)</li>
</ul>
<pre><code class="language-javascript">export default {
data() {<br/>
return {<br/>
testCount: this.$store.state.count<br/>
}<br/>
},<br/>
computed:{<br/>
testComputedCount1: function () {<br/>
return this.$store.state.count + 22<br/>
}<br/>
}<br/>
}
</code></pre>
<ul>
<li>第三种方式:mapState辅助函数绑定状态state值到组件计算属性中</li>
</ul>
<pre><code class="language-javascript">export default {
data() {<br/>
return {<br/>
testCount: this.$store.state.count<br/>
}<br/>
},<br/>
computed:{<br/>
testComputedCount1: function () {<br/>
return this.$store.state.count + 22<br/>
},<br/>
...mapState({<br/>
count: state =&gt; state.count,<br/>
mapState1: state =&gt; state.state1,<br/>
mapState2: state =&gt; state.state2<br/>
}),<br/>
}<br/>
}
</code></pre>
<ul>
<li>第四种方式:使用store中绑定的getters进行获取</li>
</ul>
<pre><code class="language-javascript">export default {
data() {<br/>
return {<br/>
testCount: this.$store.state.count<br/>
}<br/>
},<br/>
computed:{<br/>
testComputedCount1: function () {<br/>
return this.$store.state.count + 22<br/>
},<br/>
...mapState({<br/>
count: state =&gt; state.count,<br/>
mapState1: state =&gt; state.state1,<br/>
mapState2: state =&gt; state.state2<br/>
}),<br/>
testComputedGettersCount2: funtion () {<br/>
return this.$store.getters.done<br/>
}<br/>
}<br/>
}
</code></pre>
<ul>
<li>第五种方式: 借助mapGetters辅助函数绑定getters到vue的计算属性中</li>
</ul>
<pre><code class="language-javascript">export default {
data() {<br/>
return {<br/>
testCount: this.$store.state.count<br/>
}<br/>
},<br/>
computed:{<br/>
testComputedCount1: function () {<br/>
return this.$store.state.count + 22<br/>
},<br/>
...mapState({<br/>
count: state =&gt; state.count,<br/>
mapState1: state =&gt; state.state1,<br/>
mapState2: state =&gt; state.state2<br/>
}),<br/>
testComputedGettersCount2: funtion () {<br/>
return this.$store.getters.done<br/>
},<br/>
//直接绑定方法数组的方式<br/>
...mapGetters([<br/>
&#39;getState1&#39;,<br/>
&#39;getState2&#39;,<br/>
&#39;getState3&#39;<br/>
]),<br/>
//重命名对象绑定方式<br/>
...mapGetters({<br/>
mapGetterState1: &#39;getState1&#39;,<br/>
mapGetterState3: &#39;getState3&#39;<br/>
}),<br/>
}<br/>
}
</code></pre></li>
<li><p>触发动作行为改变状态值</p>
<blockquote>
<p>方式一:$store.commit(&#39;mutationsName&#39;)</p>
<p>方式二:$store.dispatch(&#39;actionsName&#39;) </p>
</blockquote>
<p>store.js文件中:</p>
<ul>
<li>初始化 mutations 和 actions (相当于是methods)</li>
</ul>
<pre><code class="language-text">const mutations = {
increment (state) {<br/>
// 变更状态<br/>
state.count = state.count * 5<br/>
}<br/>
}
</code></pre>
<pre><code class="language-text">import {action4} from &#39;@/path/actions.js&#39;
const actions = {<br/>
// 同步方法<br/>
add: function (context) {<br/>
context.commit(&#39;increment&#39;)<br/>
},<br/>
// 延时操作 用于网络请求啊啥的<br/>
addAsync (context) {<br/>
// 延时1秒<br/>
setTimeout(() =&gt; {<br/>
context.commit(&#39;increment&#39;)<br/>
}, 1000)<br/>
},<br/>
// 简写方式<br/>
action2 (context) {<br/>
context.commit(&#39;increment&#39;)<br/>
},<br/>
// 抽离到单独文件中,在导进封装好的变量来直接使用即可(导进来的目的是为了接收第一个参数:state),不绑定到store,需要手动传入store对象<br/>
action4: action4,<br/>
}
</code></pre></li>
</ol>
<ul>
<li><p>绑定action 和 mutations 到 methods,然后 调用就行了</p>
<pre><code class="language-text">export default {
methods: {<br/>
// 数组形式直接载入<br/>
...mapActions([<br/>
&#39;add&#39;<br/>
]),<br/>
// 重命名形式 <br/>
...mapActions({<br/>
add: &#39;add&#39;,<br/>
addAsync: &#39;addAsync&#39;,<br/>
action4: &#39;action4&#39;<br/>
}),<br/>
// 同上<br/>
...mapMutations([<br/>
&#39;increment&#39;<br/>
]),<br/>
...mapMutations({<br/>
incrementMutation: &#39;increment&#39;<br/>
})<br/>
}<br/>
}
</code></pre></li>
</ul>
]]></content>
</entry>
<entry>
<title type="html"><![CDATA[]]></title>
<link href="http://kaelinda.top/15151216159291.html"/>
<updated>2018-01-05T11:06:55+08:00</updated>
<id>http://kaelinda.top/15151216159291.html</id>
<content type="html"><![CDATA[
<h1 id="toc_0">react-native-splash-screen 给安卓项目添加启动图</h1>
<h2 id="toc_1">react-native-splash-screen 基本配置</h2>
<ul>
<li>安装插件:<code>npm install react-native-splash-screen --save</code></li>
<li>关联项目:<code>react-native link react-native-splash-screen</code> or <code>rnpm link react-native-splash-screen</code></li>
</ul>
<blockquote>
<p>link 之后,安卓项目中会自动添加头文件 以及部分代码,为保证项目顺利运行,还请确认下面代码是否已经完善。</p>
</blockquote>
<ul>
<li><p>确保 <code>android/settings.gradle</code>文件夹已经有下面代码</p>
<pre><code class="language-javascript">include &#39;:react-native-splash-screen&#39;
project(&#39;:react-native-splash-screen&#39;).projectDir = new File(rootProject.projectDir, &#39;../node_modules/react-native-splash-screen/android&#39;)
</code></pre></li>
<li><p>android/app/build.gradle 文件中 添加依赖 <code>react-native-splash-screen</code></p>
<pre><code class="language-text">...
dependencies {<br/>
...<br/>
compile project(&#39;:react-native-splash-screen&#39;)<br/>
}
</code></pre></li>
</ul>
<span id="more"></span><!-- more -->
<ul>
<li>更新 <code>MainApplication.java</code> 文件</li>
</ul>
<pre><code class="language-text">// react-native-splash-screen &gt;= 0.3.1
import org.devio.rn.splashscreen.SplashScreenReactPackage;
// react-native-splash-screen &lt; 0.3.1
import com.cboy.rn.splashscreen.SplashScreenReactPackage;
public class MainApplication extends Application implements ReactApplication {
private final ReactNativeHost mReactNativeHost = new ReactNativeHost(this) {
@Override
protected boolean getUseDeveloperSupport() {
return BuildConfig.DEBUG;
}
@Override
protected List&lt;ReactPackage&gt; getPackages() {
return Arrays.&lt;ReactPackage&gt;asList(
new MainReactPackage(),
new SplashScreenReactPackage() //here
);
}
};
@Override
public ReactNativeHost getReactNativeHost() {
return mReactNativeHost;
}
}
</code></pre>
<h2 id="toc_2">准备添加代码和文件配置</h2>
<ul>
<li><code>app/src/main/res/layout</code> 文件夹下 添加 <code>launch_screen.xml</code> 并copy如下代码:</li>
</ul>
<pre><code class="language-text">&lt;?xml version=&quot;1.0&quot; encoding=&quot;utf-8&quot;?&gt;
&lt;LinearLayout xmlns:android=&quot;http://schemas.android.com/apk/res/android&quot;
android:orientation=&quot;vertical&quot; android:layout_width=&quot;match_parent&quot;
android:layout_height=&quot;match_parent&quot;
android:background=&quot;@drawable/launch_screen&quot;&gt;
&lt;/LinearLayout&gt;
</code></pre>
<ul>
<li>创建文件夹 <code>drawable-xhdpi</code><code>drawable-xxhdpi</code>(暂时先创建这两个就够了),将准备好的启动图 命名为 <code>launch_screen.png</code> 分别放入创建好的文件夹</li>
<li><p>白屏问题,设置透明背景:<code>android/app/src/main/res/values/styles.xml</code> 文件夹下 添加 <code>&lt;item name=&quot;android:windowIsTranslucent&quot;&gt;true&lt;/item&gt;</code></p>
<pre><code class="language-text">&lt;resources&gt;
&lt;!-- Base application theme. --&gt;<br/>
&lt;style name=&quot;AppTheme&quot; parent=&quot;Theme.AppCompat.Light.NoActionBar&quot;&gt;<br/>
&lt;!-- Customize your theme here. --&gt;<br/>
&lt;!--设置透明背景--&gt;<br/>
&lt;item name=&quot;android:windowIsTranslucent&quot;&gt;true&lt;/item&gt;<br/>
&lt;/style&gt;<br/>
&lt;/resources&gt;
</code></pre></li>
<li><p><code>android/app/src/main/res/values/colors.xml</code> 文件夹下,添加如下:</p>
<pre><code class="language-text">&lt;?xml version=&quot;1.0&quot; encoding=&quot;utf-8&quot;?&gt; &lt;resources&gt; &lt;color name=&quot;primary_dark&quot;&gt;#660B0B0B&lt;/color&gt; &lt;/resources&gt;
</code></pre></li>
<li><p>适当的时刻 隐藏启动图 可以是在视图挂载完毕,可以是网络请求结束之后</p></li>
</ul>
<pre><code class="language-text">import SplashScreen from &#39;react-native-splash-screen&#39;
componentDidMount() {
SplashScreen.hide();
}
</code></pre>
]]></content>
</entry>
<entry>
<title type="html"><![CDATA[Rect-Native 之 Promise 深入浅出从入门到精通]]></title>
<link href="http://kaelinda.top/15139057022845.html"/>
<updated>2017-12-22T09:21:42+08:00</updated>
<id>http://kaelinda.top/15139057022845.html</id>
<content type="html"><![CDATA[
<h2 id="toc_0">概念理解</h2>
<p><img src="https://ws1.sinaimg.cn/large/006tNc79ly1fhp9dw6vxpj307406ewek.jpg" alt="icon" title="React icon"/></p>
<blockquote>
<p>所谓Promise,简单说就是一个容器,里面保存着某个未来才会结束的事件(通常是一个异步操作)的结果。从语法上说,Promise 是一个对象,从它可以获取异步操作的消息。</p>
</blockquote>
<span id="more"></span><!-- more -->
<h3 id="toc_1">Promise 状态</h3>
<ul>
<li>Pending 进行中</li>
<li>Resolved 已完成 又称Fulfilled</li>
<li>Rejected 已失败</li>
</ul>
<h3 id="toc_2">Promise 特点</h3>
<ul>
<li>对象的状态不受外部因素影响。Promise对象代表的是一个异步操作,只有异步操作的结果能决定Promise的状态,任何其他操作都不能决定其状态。</li>
<li>一旦Promise有了结果状态就不会再变。<code>Pending==&gt;Resolved</code>,或者<code>Pending==&gt;Rejected</code></li>
</ul>
<h3 id="toc_3">Promise 缺点</h3>
<p>Promise的缺点是:一旦建立就会立即执行,无法中途取消。</p>
<h2 id="toc_4">Promise 基本用法</h2>
<pre><code class="language-javascript">var promise = new Promise(function(resolve, reject) {
// ... some code
if (/* 异步操作成功 */){
resolve(value);
} else {
reject(error);
}
});
</code></pre>
<p>Promise对象接受一个参数,这个参数是一个函数体。<br/>
这个函数有两个参数:一个是resolve,一个是reject。这两个参数是Promise自动提供,不需要使用者传值。</p>
<ul>
<li>resolve函数的作用是,将Promise对象的状态从“未完成”变为“成功”(即从 Pending 变为 Resolved),在异步操作成功时调用,并将异步操作的结果,作为参数传递出去</li>
<li>reject函数的作用是,将Promise对象的状态从“未完成”变为“失败”(即从 Pending 变为 Rejected),在异步操作失败时调用,并将异步操作报出的错误,作为参数传递出去。<br/>
Promise实例生成后,可以用then分别指定Resolved和Rejected的回调函数。
<code>JavaScript
promise.then(function(value) {<br/>
// success<br/>
}, function(error) {<br/>
// failure<br/>
});
</code>
then方法会接受两个参数:</li>
<li>第一个函数,Promise状态变更为Resolved时调用。</li>
<li>第二个函数,Promise状态变为Rejected时调用。可选的,可以不提供。</li>
</ul>
<p>下面是异步加载图片的例子:</p>
<pre><code class="language-javascript">function loadImageAsync(url) {
return new Promise(function(resolve, reject) {
var image = new Image();
image.onload = function() {
resolve(image);
};
image.onerror = function() {
reject(new Error(&#39;Could not load image at &#39; + url));
};
image.src = url;
});
}
</code></pre>
<p>下面是Promise实现的Ajax操作的例子:</p>
<pre><code class="language-javascript">var getJSON = function(url) {
var promise = new Promise(function(resolve, reject){
var client = new XMLHttpRequest();
client.open(&quot;GET&quot;, url);
client.onreadystatechange = handler;
client.responseType = &quot;json&quot;;
client.setRequestHeader(&quot;Accept&quot;, &quot;application/json&quot;);
client.send();
function handler() {
if (this.readyState !== 4) {
return;
}
if (this.status === 200) {
resolve(this.response);
} else {
reject(new Error(this.statusText));
}
};
});
return promise;
};
getJSON(&quot;/posts.json&quot;).then(function(json) {
console.log(&#39;Contents: &#39; + json);
}, function(error) {
console.error(&#39;出错了&#39;, error);
});
</code></pre>
<p><strong>注意:在getJSON内部,resolve函数和reject函数调用时,都带有参数!!</strong><br/><br/>
如果调用resolve函数和reject函数时带有参数,那么它们的参数会被传递给回调函数。</p>
<ul>
<li>reject函数的参数通常是Error对象的实例,表示抛出的错误</li>
<li>resolve函数的参数除了正常的值以外,还可能是另一个 Promise 实例,表示异步操作的结果有可能是一个值,也有可能是另一个异步操作</li>
</ul>
<pre><code class="language-javascript">var p1 = new Promise(function (resolve, reject) {
// ...
});
var p2 = new Promise(function (resolve, reject) {
// ...
resolve(p1);
})
</code></pre>
<p>上面👆,<code>p1</code><code>p2</code> 都是Promise,但是<code>p2</code>的resolve把<code>p1</code>作为返回值参数传出去了,即一个异步操作的返回结果是另一个异步操作。(类似于iOS开发中的自动布局库 <code>Masonry</code>,可以无限点语法取到对象)。<br/><br/>
<strong>注意:此时,p1的状态会传递p2.如果p1是Pending状态,那么p2会等待p1的结果。如果p1是Reject或者Resolve状态,那么p2的回调函数将会立即执行。</strong></p>
<p><strong>再看:</strong></p>
<pre><code class="language-javascript">var p1 = new Promise(function (resolve, reject) {
setTimeout(() =&gt; reject(new Error(&#39;fail&#39;)), 3000)
})
var p2 = new Promise(function (resolve, reject) {
setTimeout(() =&gt; resolve(p1), 1000)
})
p2.then(result =&gt; console.log(result))
.catch(error =&gt; console.log(error))
// Error: fail
</code></pre>
<ol>
<li><code>p1</code>会在3秒后抛出error。<br/></li>
<li><code>p2</code>会在1秒后改变状态。Resolv的返回值是<code>p1</code>.<br/></li>
<li>由于<code>p2</code>的返回值是一个Promise,导致<code>p2</code>自己的状态无效了,此时<code>p2</code>的状态取决于<code>p1</code>.<br/></li>
<li>所以,后面的then语句,都变成针对p1的了。<br/></li>
<li>又过了<code>2秒</code><code>p1</code>变为<code>reject</code>,导致触发<code>catch</code>方法。<br/></li>
</ol>
<h2 id="toc_5">3. Promise.prototype.then()</h2>
<p><strong>then方法是定义在原型对象Promise.prototype上的。</strong><br/>
作用:为Promise对象添加状态改变时的回调函数。第一个是Resolved,第二个是Rejected。<br/>
then方法返回的是一个新的Promise对象,不是之前的实例。因此 then方法后面还可以再写一个then方法,即链式调用。</p>
<pre><code class="language-javascript">getJSON(&quot;/posts.json&quot;).then(function(json) {
return json.post;
}).then(function(post) {
// ...
});
</code></pre>
<p>第一个回调函数完成以后,会将返回结果作为参数,传入第二个回调函数。</p>
<pre><code class="language-javascript">getJSON(&quot;/post/1.json&quot;).then(function(post) {
return getJSON(post.commentURL);
}).then(function funcA(comments) {
console.log(&quot;Resolved: &quot;, comments);
}, function funcB(err){
console.log(&quot;Rejected: &quot;, err);
});
</code></pre>
<p>第一个then函数返回的是一个新的Promise对象。于是才能继续调用then方法。<br/>
第二个then方法指定的回调函数,就会等待这个Promise对象状态发生变化,resolv会调用funcA,reject会调用funcB.</p>
<p>下面👇是箭头函数的实现,会更简洁:</p>
<pre><code class="language-javascript">getJSON(&quot;/post/1.json&quot;).then(
post =&gt; getJSON(post.commentURL)
).then(
comments =&gt; console.log(&quot;Resolved: &quot;, comments),
err =&gt; console.log(&quot;Rejected: &quot;, err)
);
</code></pre>
<h2 id="toc_6">4. Promise.prototype.catch()</h2>
<h3 id="toc_7">Promise.prototype.catch方法是.then(null, rejection)的别名,用于指定发生错误时的回调函数</h3>
<p><strong>Promise.prototype.catch方法是.then(null, rejection)的别名,用于指定发生错误时的回调函数.</strong> </p>
<pre><code class="language-javascript">getJSON(&#39;/posts.json&#39;).then(function(posts) {
// ...
}).catch(function(error) {
// 处理 getJSON 和 前一个回调函数运行时发生的错误
console.log(&#39;发生错误!&#39;, error);
});
</code></pre>
<p>getJSON()方法返回的是一个Promise对象。如果resolv,会调用then方法;如果reject则会调用catch方法。</p>
<h3 id="toc_8">then方法指定的回调函数,如果运行中抛出错误,也会被catch方法捕获</h3>
<p><strong>另外,then方法指定的回调函数,如果运行中抛出错误,也会被catch方法捕获</strong> </p>
<pre><code class="language-javascript">p.then((val) =&gt; console.log(&#39;fulfilled:&#39;, val))
.catch((err) =&gt; console.log(&#39;rejected&#39;, err));
// 等同于
p.then((val) =&gt; console.log(&#39;fulfilled:&#39;, val))
.then(null, (err) =&gt; console.log(&quot;rejected:&quot;, err));
</code></pre>
<pre><code class="language-text">var promise = new Promise(function(resolve, reject) {
throw new Error(&#39;test&#39;);
});
promise.catch(function(error) {
console.log(error);
});
// Error: test
</code></pre>
<p>Promise对象Resolved,但是Resolved指定的方法跑出错误。<br/>
Promise对象catch方法能捕获跑出的error。</p>
<h3 id="toc_9">reject方法等同于抛出错误</h3>
<p>上面的写法跟下面的两种写法是一样的:</p>
<pre><code class="language-text">// 写法一
var promise = new Promise(function(resolve, reject) {
try {
throw new Error(&#39;test&#39;);
} catch(e) {
reject(e);
}
});
promise.catch(function(error) {
console.log(error);
});
// 写法二
var promise = new Promise(function(resolve, reject) {
reject(new Error(&#39;test&#39;));
});
promise.catch(function(error) {
console.log(error);
});
</code></pre>
<p><strong>由此可见:reject方法等同于抛出错误。</strong></p>
<h3 id="toc_10">resolve之后在抛出错误,catch是捕获不到的不到的。</h3>
<pre><code class="language-text">var promise = new Promise(function(resolve, reject) {
resolve(&#39;ok&#39;);
throw new Error(&#39;test&#39;);
});
promise
.then(function(value) { console.log(value) })
.catch(function(error) { console.log(error) });
// ok
</code></pre>
<p><strong>resolve之后在抛出错误,catch是捕获不到的不到的。</strong></p>
<h3 id="toc_11">Promise 对象的错误具有“冒泡”性质</h3>
<p><strong>Promise 对象的错误具有“冒泡”性质,会一直向后传递,直到被捕获为止 ------ 错误总是会被下一个catch语句捕获</strong></p>
<blockquote>
<p>举个栗子:就像是Y染色体上受环境触发的遗传疾病,会不断的遗传给男性后代,任意一个男性都会被特殊的环境触发。</p>
</blockquote>
<pre><code class="language-text">getJSON(&#39;/post/1.json&#39;).then(function(post) {
return getJSON(post.commentURL);
}).then(function(comments) {
// some code
}).catch(function(error) {
// 处理前面三个Promise产生的错误
});
</code></pre>
<p>上述代码中有三个Promise,第一个由getJSON产生,后两个由then产生。他们之中的任何一个抛出错误,都会被catch捕获。</p>
<p>一般来讲,尽量不要定义Promise的reject状态的回调函数,最好总是使用catch函数,因为catch函数不仅能捕获到reject状态,还能捕获到resolve状态指定方法下抛出的异常。</p>
<h3 id="toc_12">Promise对象抛出的错误不会传递到外层代码</h3>
<p>如果没有使用catch方法指定错误处理的回调函数,Promise对象抛出的错误不会传递到外层代码,即不会有任何反应,这一点上跟传统的try/catch代码块不同的。</p>
<pre><code class="language-text">process.on(&#39;unhandledRejection&#39;, function (err, p) {
console.error(err.stack)
});
</code></pre>
<p>时间的监听函数‘unhandledRejection’,有两个参数:<br/>
第一个是错误对象<br/>
第二个是报错的Promise实例</p>
<p>catch方法返回的也是一个Promise实例,所以后面还是可以无限的调用then方法。<br/>
如果catch函数在几个then中间,二执行过程中都没有reject状态,那么会跳过这个中间的catch方法。</p>
<h3 id="toc_13">catch方法中也能抛出错误</h3>
<pre><code class="language-text">var someAsyncThing = function() {
return new Promise(function(resolve, reject) {
// 下面一行会报错,因为x没有声明
resolve(x + 2);
});
};
someAsyncThing().then(function() {
return someOtherAsyncThing();
}).catch(function(error) {
console.log(&#39;oh no&#39;, error);
// 下面一行会报错,因为y没有声明
y + 2;
}).then(function() {
console.log(&#39;carry on&#39;);
});
// oh no [ReferenceError: x is not defined]
</code></pre>
<p>如上:catch方法指定的函数依旧是可以抛出Error的,但是因为后面没有继续跟进catch方法,所以并没有被捕获。</p>
<h2 id="toc_14">5. Promise.all()</h2>
<p><strong>Promise.all方法用于将多个 Promise 实例,包装成一个新的 Promise 实例。</strong></p>
<pre><code class="language-text">var p = Promise.all([p1, p2, p3]);
</code></pre>
<p>Promise.all方法接受一个数组作为参数,p1、p2、p3都是 Promise 实例,如果不是,就会先调用下面讲到的Promise.resolve方法,将参数转为 Promise 实例,再进一步处理。<br/>
(Promise.all方法的参数可以不是数组,但必须具有 Iterator 接口,且返回的每个成员都是 Promise 实例。)</p>
<p>p的状态由p1、p2、p3决定,分成两种情况:</p>
<ul>
<li>只有p1、p2、p3的状态都变成fulfilled,p的状态才会变成fulfilled,此时p1、p2、p3的返回值组成一个数组,传递给p的回调函数</li>
<li>只要p1、p2、p3之中有一个被rejected,p的状态就变成rejected,此时第一个被reject的实例的返回值,会传递给p的回调函数</li>
</ul>
<p><strong>注意,如果作为参数的 Promise 实例,自己定义了catch方法,那么它一旦被rejected,并不会触发Promise.all()的catch方法。</strong></p>
<pre><code class="language-text">const p1 = new Promise((resolve, reject) =&gt; {
resolve(&#39;hello&#39;);
})
.then(result =&gt; result)
.catch(e =&gt; e);
const p2 = new Promise((resolve, reject) =&gt; {
throw new Error(&#39;报错了&#39;);
})
.then(result =&gt; result)
.catch(e =&gt; e);
Promise.all([p1, p2])
.then(result =&gt; console.log(result))
.catch(e =&gt; console.log(e));
// [&quot;hello&quot;, Error: 报错了]
</code></pre>
<p>p1会resolved,p2首先会rejected.<br/>
p2有自己的catch方法,并且执行了,那么就会返回一个新的Promise,并且这个Promise的状态会变成Resolved。<br/>
所以:Promise.all()的catch方法并不能捕获到这个error。<br/>
p2没有自己的catch方法,所以会调用Promise.all()的catch方法。</p>
<h2 id="toc_15">6. Promise.race()</h2>
<p>Promise.race方法同样是将多个Promise实例,包装成一个新的Promise实例。</p>
<pre><code class="language-text">var p = Promise.race([p1, p2, p3]);
</code></pre>
<p>p1/p2/p3中只要有一个率先改变状态,p的状态就会随着改变。那个率先改变状态的实例的返回值,就会传递给p的回调函数。</p>
<pre><code class="language-text">const p = Promise.race([
fetch(&#39;/resource-that-may-take-a-while&#39;),
new Promise(function (resolve, reject) {
setTimeout(() =&gt; reject(new Error(&#39;request timeout&#39;)), 5000)
})
]);
p.then(response =&gt; console.log(response));
p.catch(error =&gt; console.log(error));
</code></pre>
<p>5秒内无法返回请求结果,变量p的状态就会变为reject。这也算是竞速的一种应用场景。</p>
<h2 id="toc_16">7. Promise.resolve()</h2>
<p>有时需要将现有对象转为Promise对象,Promise.resolve方法就起到这个作用.</p>
<pre><code class="language-text">var jsPromise = Promise.resolve($.ajax(&#39;/whatever.json&#39;));
</code></pre>
<p>等价于下面的说法:</p>
<pre><code class="language-text">Promise.resolve(&#39;foo&#39;)
// 等价于
new Promise(resolve =&gt; resolve(&#39;foo&#39;))
</code></pre>
<p>Promise 的第一个参数是一个箭头函数,函数的传入参数是resolve(函数),函数体就是调用传入的函数resolve,resolve调用的时候,也需要一个参数,此时这个参数就是咱们需要转变成Promise对象的那个参数。</p>
<p>Promise.resolve的参数有四种情况:</p>
<ol>
<li>参数是一个Promise实例</li>
<li>参数是一个thenable对象(有then方法的实例)</li>
<li>参数是不具备then方法d的对象应该</li>
<li>不带参数,返回一个Resolved的返回状态。</li>
</ol>
<h2 id="toc_17">8、Promise.reject() 同上</h2>
<h2 id="toc_18">9、两个常用附加方法</h2>
<h3 id="toc_19">done()</h3>
<p>Promise的错误并不会冒泡到全局,所以我们可以提供一个done方法总是处于会吊链的尾端。</p>
<pre><code class="language-text">asyncFunc()
.then(f1)
.catch(r1)
.then(f2)
.done();
```
done方法的使用,可以像then方法那样用,提供Fulfilled和Rejected状态的回调函数,也可以不提供任何参数。但不管怎样,done都会捕捉到任何可能出现的错误,并向全局抛出.
### finally()
finally方法用于指定不管Promise对象最后状态如何,都会执行的操作。它与done方法的最大区别,它接受一个普通的回调函数作为参数,该函数不管怎样都必须执行。
</code></pre>
<p>Promise.prototype.finally = function (callback) {<br/>
let P = this.constructor;<br/>
return this.then(<br/>
value =&gt; P.resolve(callback()).then(() =&gt; value),<br/>
reason =&gt; P.resolve(callback()).then(() =&gt; { throw reason })<br/>
);<br/>
};</p>
<pre><code class="language-text">
### Promis.try()
</code></pre>
<p>try {<br/>
database.users.get({id: userId})<br/>
.then(...)<br/>
.catch(...)<br/>
} catch (e) {<br/>
// ...<br/>
}</p>
<pre><code class="language-text">
</code></pre>
<p>Promise.try(database.users.get({id: userId}))<br/>
.then(...)<br/>
.catch(...)</p>
<pre><code class="language-text">
Promise.try就是模拟try代码块,就像promise.catch模拟的是catch代码块.
</code></pre>
]]></content>
</entry>
<entry>
<title type="html"><![CDATA[ES6 笔记(Array)]]></title>
<link href="http://kaelinda.top/15137645005542.html"/>
<updated>2017-12-20T18:08:20+08:00</updated>
<id>http://kaelinda.top/15137645005542.html</id>
<content type="html"><![CDATA[
<h2 id="toc_0">array</h2>
<ol>
<li><p>Array.from<br/>
将类似数组的对象(array-like object)和可遍历(iterable)的对象 转换为数组。</p>
<ul>
<li>类数组:有 length属性的对象</li>
<li>可遍历:包含Set Map.</li>
</ul></li>
<li><p>Array.of<br/>
该方法用于将一组值,转换为数组。</p></li>
</ol>
<span id="more"></span><!-- more -->
<ol>
<li><p>copyWithin<br/>
在当前数组内部,将指定位置的成员复制到其他位置(会覆盖原有成员)。</p>
<ul>
<li> target(必需):从该位置开始替换数据。</li>
<li> start(可选):从该位置开始读取数据,默认为0。如果为负值,表示倒数。</li>
<li> end(可选):到该位置前停止读取数据,默认等于数组长度。如果为负值,表示倒数。</li>
</ul></li>
<li><p>数组实例的find()和findIndex()<br/>
用于找出第一个符合条件的数组成员。<br/>
用于找出第一个符合条件的数组成员的位置。</p></li>
<li><p>fill<br/>
方法使用给定值,填充一个数组。<br/>
[&#39;a&#39;, &#39;b&#39;, &#39;c&#39;].fill(7, 1, 2)<br/>
// [&#39;a&#39;, 7, &#39;c&#39;];// 左闭右开</p></li>
<li><p>数组实例的entries(),keys()和values()<br/>
keys()是对键名的遍历<br/>
values()是对键值的遍历<br/>
entries()是对键值对的遍历</p></li>
<li><p>Array.prototype.includes方法<br/>
返回一个布尔值,表示某个数组是否包含给定的值。<br/>
[1, 2, 3].includes(3, -1); // true<br/>
3:将要搜索的item<br/>
-1:搜索的起始位置 </p></li>
<li><p>数组的空位<br/>
数组的空位指,数组的某一个位置没有任何值。</p></li>
</ol>
<p>空位不是undefined,undefined是有值的。<br/>
空位是没有任何值。</p>
]]></content>
</entry>
</feed>
马建仓 AI 助手
尝试更多
代码解读
代码找茬
代码优化
1
https://gitee.com/kaelinda/kaelindaTop.git
git@gitee.com:kaelinda/kaelindaTop.git
kaelinda
kaelindaTop
kaelindaTop
master

搜索帮助

0d507c66 1850385 C8b1a773 1850385