-
Notifications
You must be signed in to change notification settings - Fork 0
/
search.xml
490 lines (490 loc) · 125 KB
/
search.xml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
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
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
<?xml version="1.0" encoding="utf-8"?>
<search>
<entry>
<title><![CDATA[js-常用工具01]]></title>
<url>%2Fliuyang996.github.io%2F2018%2F12%2F29%2Fjs-util1%2F</url>
<content type="text"><![CDATA[数组 打乱数组排序:应用场景(随机系列) //随机得到最小数和最大数之间的数 function getRandomInt(min,max) { return Math.floor(Math.random() * (max-min +1) + min) } //打乱顺序 function shuffle(arr) { let _arr = arr.slice(); for(let i =0;i<_arr.length;i++) { let j = getRandomInt(0,i); let t = _arr[i]; _arr[i] = _arr[j]; _arr[j] = t; } return _arr } 原理:getRandomInt函数随机的最小数和最大数之间的数。其中 +1的作用是未了避免为0,+min的作用是保证值在min和max之间。通过getRandomInt函数获得0-i之间(包含i)的随机数j,用做下标,和当前项的值交换。通过arr.slice()方法返回一个新数组,不改变原数组。 js-transform兼容 在vue中,css3兼容有css-loader去处理。我们一般不用去管。比如有时候我们需要在js中去使用transform。这时候就需要去处理一下。 let elementStyle = document.createElement('div').style let vendor = (() => { let transformNames = { webkit: 'webkitTransform', Moz: 'MozTransform', O: 'OTransform', ms: 'msTransform', standard: 'transform' } for(let key in transformNames) { if (elementStyle[transformNames[key]] !== undefined) { return key } } return false })() export function prefixStyle(style) { if (vendor === false) { return false } if (vendor === 'strandard') { return style } return vendor + style.charAt(0).toUpperCase() + style.substr(1) } 引入方式: import {prefixStyle} from 'common/js/dom' const transform = prefixStyle('transform') this.$refs.cdWrapper.style[transform] = '';]]></content>
<categories>
<category>javascript</category>
</categories>
<tags>
<tag>javascript</tag>
</tags>
</entry>
<entry>
<title><![CDATA[js-防抖、节流]]></title>
<url>%2Fliuyang996.github.io%2F2018%2F12%2F24%2Fjs-debounce%2F</url>
<content type="text"><![CDATA[防抖 函数防抖(debounce):当持续触发事件时,一定时间段内没有再触发事件,事件处理函数才会执行一次,如果设定的时间到来之前,又一次触发了事件,就重新开始延时。 一个简单的debouncefunction debounce(fn, wait) { var timeout = null; return function () { if (timeout !== null) { clearTimeout(timeout); } timeout = setTimeout(fn, wait); } } //处理函数 function handle() { console.log(Math.random()); } // 滚动事件 window.addEventListener('scroll', debounce(handle, 1000)); 节流 函数节流:当持续触发事件时,保证一定时间段内只调用一次事件处理函数。 函数节流主要有两种实现方法:时间戳和定时器。节流(时间戳)var throttle = function(func, delay) { let prev = Date.now(); return function() { let context = this; let args = arguments; let now = Date.now(); if (now - prev >= delay) { func.apply(context, args); prev = now; } } } function handle() { console.log(Math.random()); } window.addEventListener('scroll', throttle(handle, 1000)); 当高频事件触发时,第一次会立即执行(因为给scroll函数绑定函数与真正触发事件的间隔一般大于delay)。之后会根据当前时间戳减上一次时间戳如果小于设定的delay则,事件不会被执行了。这里用了闭包的方法把prev封闭在作用域内。 节流(定时器)var throttle = function(func,delay) { let timer = null; return function() { let context = this; let args = arguments; if(!timer) { timer = setTimeout(function(){ func.apply(context,args); timer = null; },delay) } } } function handle() { console.log(Math.random()); } window.addEventListener('scroll',throttle(handle,1000)); 当触发事件的时候,我们设置一个定时器,再次触发事件的时候,如果定时器存在,就不执行,直到delay时间后,定时器执行函数,并且清空定时器,这样就可以设置下个定时器。 总结函数防抖:原理是维护一个定时器,规定在delay时间后触发函数,但是再delay时间内再次触发的话,就会取消之前的计时器而重新设置。这样一来,只有最后一次操作能被触发。 函数节流:在一定时间内只触发一次函数。原理是通过判断是否达到一定时间来触发函数。 区别:函数节流不管事件触发有多频繁,都会保证在规定时间内一定会执行一次真正的事件处理函数,而函数防抖只是在最后一次事件后才触发一次函数。 比如在页面的无限加载场景下,我们需要用户在滚动页面时,每隔一段时间发一次 Ajax 请求,而不是在用户停下滚动页面操作时才去请求数据。这样的场景,就适合用节流技术来实现。]]></content>
<categories>
<category>javascript</category>
</categories>
<tags>
<tag>javascript</tag>
</tags>
</entry>
<entry>
<title><![CDATA[vue-仿通讯录功能开发]]></title>
<url>%2Fliuyang996.github.io%2F2018%2F11%2F28%2Fvue-tel%2F</url>
<content type="text"><![CDATA[实现的功能是一个歌手详情页面,和通讯录页面逻辑布局基本一样。 效果截图: 实现功能: 滑动歌手列表,右侧的快速入口会对应当前歌手首字母高亮 滑动歌手列表,歌手标题会置顶,且有被顶上去的样式 点击右侧的快速入口选项,歌手列表会滚动到该类上。 滑动右侧的快速入口选项,歌手列表会滚动到该类上。 实现思路 左右联动效果,做侧或右侧滑动,会影响对方。所以需要知道实时滚动位置。 根据滚动位置,知道落在哪一个高度区间。 知道落在高度区间,可以知道右侧索引高亮。 具体实现页面布局这个页面中,我们会在滚动时做一些操作。所以我使用better-scroll插件,且把它封装好了。具体封装代码,请看另外一篇 滚动插件-better-scroll封装 。 <template> <scroll class="listview" :data="data" ref="listview" :listenScroll="listenScroll" :probeType="probeType" @scroll="scroll"> <ul> <li class="list-group" v-for="(group,gindex) in data" :key="gindex" ref="listGroup"> <h2 class="list-group-title">{{group.title}}</h2> <ul> <li class="list-group-item" v-for="(item,index) in group.items" :key="index"> <img v-lazy="item.avatar" class="avatar" > <span class="name">{{item.name}}</span> </li> </ul> </li> </ul> <div class="list-shortcut" @touchstart.stop.prevent="onShortcutTouchStart" @touchmove.stop.prevent="onShortcutTouchMove" @touchend.stop> <ul> <li class="item" v-for="item,index in shortcutList" :key="index" :data-index="index" :class="{'current':currentIndex === index}">{{item}}</li> </ul> </div> <div class="list-fixed" ref="fixed" v-show="fixedTitle"> <h1 class="fixed-title">{{fixedTitle}}</h1> </div> </scroll> </template> 点击右侧快速入口,歌手滚动到该区域区间 给右侧入口添加点击事件。这里没有给li添加点击事件,而是给外层div添加点击事件。目的是为了之后的滑动事件获取点击的pageY值。 onShortcutTouchStart(e) { let anchorIndex = getData(e.target,'index'); let firstTouch = e.touches[0]; this.touch.y1 = firstTouch.pageY; this.touch.anchorIndex = anchorIndex; this._scrollTo(anchorIndex); } 说明:1.getData函数用来获取点击的子元素索引,拿到索引后,让scroll滚动到当前的位置。2.获取点击的pageY值,存放到touch对象里,在计算移动距离的时候会用到。 _scrollTo(index) { if (!index && index !== 0) { return } if(index<0) { index = 0; }else if (index > this.listHeight.length -2) { index = this.listHeight.length-2; } this.scrollY = -this.listHeight[index]; this.$refs.listview.scrollToElement(this.$refs.listGroup[index],0); }, _scrollTo 方法是用于滚动到指定位置。里面做了边界处理。]]></content>
<categories>
<category>vue</category>
</categories>
<tags>
<tag>vue-通讯录</tag>
</tags>
</entry>
<entry>
<title><![CDATA[滚动插件-better-scroll封装]]></title>
<url>%2Fliuyang996.github.io%2F2018%2F11%2F28%2Fvue-batterScroll%2F</url>
<content type="text"><![CDATA[在开发vue移动端项目时,经常都会出现滚动。对滚动场景需求时,我们可以借助第三方插件来实现需求。目前用的比较多的就是 btter-scroll 插件。 安装npm install better-scroll --save 创建better-scroll组件 新建一个scroll文件夹,在里面新建scroll.vue 引入 better-scroll import BScroll from 'better-scroll' scroll.vue:html:<div ref="wrapper"> <slot></slot> </div> html部分使用了slot插槽,让组件里的标签不被替换。 script:props: { probeType: { //滚动位置,参数为:1、2、3。具体内容可查better-scroll文档,以下也是。 type: Number, default: 1, }, click: { // 是否派发点击事件 type: Boolean, default: true }, data: { //数据,用来重新计算better-scorll。 type: Array, default: null }, listenScroll: { //是否监听scroll事件 type:Boolean, default:false, } }, watch: { data() { setTimeout(()=> { this.refresh(); },20) } }, mounted() { setTimeout(()=> { console.log('初始化'); this._initScroll(); },20) }, methods: { _initScroll() { if(! this.$refs.wrapper) { return; } this.scroll = new BScroll(this.$refs.wrapper, { probeType: this.probeType, click: this.click }) if(this.listenScroll){ let me = this; this.scroll.on('scroll', (pos) => { me.$emit('scroll',pos); }) } }, enable() { this.scroll && this.scroll.enable(); }, disable() { this.scroll && this.scroll.disable(); }, scrollTo() { this.scroll && this.scroll.scrollTo.apply(this.scroll, arguments) }, scrollToElement() { this.scroll && this.scroll.scrollToElement.apply(this.scroll, arguments) }, refresh() { this.scroll && this.scroll.refresh(); } } props: props里默认接收上面几个参数(根据实际需求可继续添加或减小),并设置默认值(设置值属性,可参数官方文档)。 watch: 监听data数据的变化,变化后,调用refresh()函数重新渲染better-scroll。 这里的 : setTimeout(()=> { this.refresh(); },20) 等同于: this.$nextTick(() => { this.refresh(); }) _initScroll: _initScroll函数里初始化了better-scroll,并根据props里接收的值,进行了配置。在mounted里初始化。 还有其他方法可以在各种情况下直接调用,来实现各种需求。 在其他组件引用import scroll from 'base/scroll/scroll components:{ // scroll: () => import('base/scroll/scroll') scroll } <scroll :data="data" class="listview"> <ul> <li></li> ... </ul> </scroll> 在引入的时候建议不要使用懒加载的方法。可能会出现加载顺序有误造成报错。根据实际需要传入相关配置属性,data是数据,必须要传。哪个数据结构需要使用到better-scroll,就传哪个数据。 父级容器一定要设置高度和 overflow: hidden;否则可能无法滚动。]]></content>
<categories>
<category>vue</category>
</categories>
<tags>
<tag>vue</tag>
</tags>
</entry>
<entry>
<title><![CDATA[vue常用插件]]></title>
<url>%2Fliuyang996.github.io%2F2018%2F11%2F21%2Fvue-music%2F</url>
<content type="text"><![CDATA[fastclick 处理移动端click事件300毫秒延迟npm install fastclick -S 之后,在main.js中引入,并绑定到body import FastClick from 'fastclick' FastClick.attach(document.body); babel-runtime 和babel-polyfill babel-polyfill:当运行环境中并没有实现的一些方法,babel-polyfill 会给其做兼容。babel-runtime: 不污染全局对象和内置的对象原型的情况下,使用新语法。 babel-polyfill 安装: npm install --save babel-polyfill import "babel-polyfill babel-runtime 安装: npm install --save-dev babel-plugin-transform-runtime npm install --save babel-runtime 写入 '.babelrc' { "plugins": ["transform-runtime"] } lib-flexible 移动端适配npm install lib-flexible --save 在项目的入口js文件中引入lib-flexible import 'lib-flexible' 使用px2rem-loader自动将css中的px转换成rem npm install px2rem-loader --save-dev 配置px2rem-loader 打开build/utils.js文件,找到exports.cssLoaders方法,在里面添加如下代码 const px2remLoader = { loader: 'px2rem-loader', options: { remUint: 75 } } 修改generateLoaders方法中的loaders const loaders = options.usePostCSS ? [cssLoader, postcssLoader,px2remLoader] : [cssLoader,px2remLoader] index.html文件的mete标签修改为: <meta name="viewport" content="width=device-width,initial-scale=1.0"> 注意: 1.此方法只能将.vue文件style标签中的px转成rem,不能将script标签和元素style里面定义的px转成rem 2.如果在.vue文件style中的某一行代码不希望被转成rem,只要在后面写上注释 / no/就可以了]]></content>
<categories>
<category>vue</category>
</categories>
<tags>
<tag>vue</tag>
</tags>
</entry>
<entry>
<title><![CDATA[node-koa]]></title>
<url>%2Fliuyang996.github.io%2F2018%2F11%2F19%2Fnode-koa%2F</url>
<content type="text"><![CDATA[koa是Express的下一代基于Node.js的web框架,目前有1.x和2.0两个版本。这里使用的是2.0 安装koa2npm install [email protected] 这里要有package.json文件 或者自己在目录下创建一个package.json。 { "name": "hello-koa2", "version": "1.0.0", "description": "Hello Koa 2 example with async", "main": "app.js", "scripts": { "start": "node app.js" }, "keywords": [ "koa", "async" ], "author": "Michael Liao", "license": "Apache-2.0", "repository": { "type": "git", "url": "https://github.com/michaelliao/learn-javascript.git" }, "dependencies": { "koa": "2.0.0" } } 其中,dependencies描述了我们的工程依赖的包以及版本号。其他字段均用来描述项目信息,可任意填写。 然后执行 npm install 实现一个 hello,koa2//导入koa,和koa1.x不同,在koa2中,我们导入的是一个class,因此用大写的koa表示。 const Koa = require('koa'); // 创建一个koa对象,表示webapp本身; const app = new Koa(); //对于任何请求,app将调用该异步函数处理请求; app.use(async (ctx,next) => { await next(); ctx.response.type = 'text/html'; ctx.response.body = '<h1>Hello,Koa2</h1>'; }) app.listen(3000); console.log('app stared at port 3000') koa middlewarekoa把很多async函数组成一个处理链,每个async函数都可以做一些自己的事情,然后用await next()来调用下一个async函数,把每个async函数称为middleware。 middleware的顺序很重要,也就是调用app.use()的顺序决定了middleware的顺序。 如果一个middleware没有调用await next(),后续的middleware将不再执行了。 处理URL处理url,我们需要引入koa-router这个middleware,让它处理URL映射 在 package.json 中添加依赖项: "koa-router": "7.0.0" 然后用 npm install 安装 get// 注意require('koa-router')返回的是函数: const router = require('koa-router')(); const app = new Koa(); // add url-route: router.get('/hello/:name', async (ctx, next) => { var name = ctx.params.name; ctx.response.body = `<h1>Hello, ${name}!</h1>`; }); // add router middleware: app.use(router.routes() post使用Post请求处理url时,需要引入另一个middleware来解析原始request请求 在 package.json 中添加依赖项: "koa-bodyparser": "3.2.0" 然后用 npm install 安装 引入 const bodyParser = require('koa-bodyparser'); 在router被注册之前使用 app.use(bodyParser()); 一个简单的登录表单 : router.get('/', async (ctx, next) => { ctx.response.body = `<h1>Index</h1> <form action="/signin" method="post"> <p>Name: <input name="name" value="koa"></p> <p>Password: <input name="password" type="password"></p> <p><input type="submit" value="Submit"></p> </form>`; }); router.post('/signin', async (ctx, next) => { var name = ctx.request.body.name || '', password = ctx.request.body.password || ''; console.log(`signin with name: ${name}, password: ${password}`); if (name === 'koa' && password === '12345') { ctx.response.body = `<h1>Welcome, ${name}!</h1>`; } else { ctx.response.body = `<h1>Login failed!</h1> <p><a href="/">Try again</a></p>`; } });]]></content>
<categories>
<category>Node.js</category>
</categories>
<tags>
<tag>Node.js</tag>
</tags>
</entry>
<entry>
<title><![CDATA[node-http]]></title>
<url>%2Fliuyang996.github.io%2F2018%2F11%2F16%2Fnode-http%2F</url>
<content type="text"><![CDATA[开发HTTP服务器程序,需要使用到Node.js的http模块。 request 对象封装了HTTP请求,我们调用request对象的属性和方法就可以拿到所有HTTP请求的信息。 response 对象封装了HTTP响应,我们操作response对象的方法,就可以把HTTP响应返回给浏览器。 实现一个最简单的Web程序hello.js,它对于所有请求,都返回hello world!'use strict' //导入http模块 var http = require('http'); //创建http server 并传入回调函数 var server = http.createServer(function(request,response){ // 回调函数接口request,response对象 //获取http请求的method,url, console.log(request.method+' : ' + request.url); //将HTTP响应200写入response,同时设置Content-Type:text/html; response.writeHead(200,{'Content-Type':'text/html'}); //将HTTP响应内容写入response; response.end('<h1>Hello,world!</h1>') }) server.listen('8088'); console.log('Server is running at http:127.0.0.1:8088'); 文件服务器我们可以设定一个目录,然后让web程序变成一个文件服务器。 解析request.url中的路径,然后在本地找到对应的文件,把文件内容发送出去。 解析URL需要用到Node.js提供的url模块,用过parse()将一个字符串解析为一个url对象 'use strict'; var url = require('url'); console.log(url.parse('http://user:[email protected]:8080/path/to/file?query=string#hash')); 结果如下: Url { protocol: 'http:', slashes: true, auth: 'user:pass', host: 'host.com:8080', port: '8080', hostname: 'host.com', hash: '#hash', search: '?query=string', query: 'query=string', pathname: '/path/to/file', path: '/path/to/file?query=string', href: 'http://user:[email protected]:8080/path/to/file?query=string#hash' } 处理本地文件目录需要使用Node.js提供的path模块 ,它可以方便地构造目录: 'use strict'; var path = require('path'); // 解析当前目录: var workDir = path.resolve('.'); // 自己文件当前的本地路径 // 组合完整的文件路径:当前目录+'pub'+'index.html': var filePath = path.join(workDir, 'pub', 'index.html'); // 自己文件当前的本地路径/pub/index.html 使用path模块可以正确处理操作系统相关的文件路径。在window系统下,返回的路径类似于C:\Users\michael\static\index.html,这样,我们都就不用关心怎么拼接路径了。 实现一个文件服务器var http = require('http'); var path = require('path'); var fs = require('fs'); var url = require('url'); //从命令行参数获取root目录,默认是当前目录: var root = path.resolve(process.argv[2] || '.'); console.log('Static root dir:' + root); //创建服务器 var server = http.createServer(function(request,response) { //获取URL的path,类似'/css/bootstrap.css' console.log(request.url); var pathname = url.parse(request.url).pathname; //获取对应的本地路径,类似 '/srv/www/css/bootstrap.css' var filepath = path.join(root,pathname); console.log('root= '+root); console.log('pathname= '+pathname); console.log('filepath= '+filepath); //获取文件状态 fs.stat(filepath,function(err,stat) { if(!err && stat.isFile()){ //判断没有出错,且文件存在 console.log('200 '+ request.url); //发送200响应 response.writeHead(200); //将文件流导入response fs.createReadStream(filepath).pipe(response); } else { //出错了或文件不存在 console.log('404'); response.writeHead(404); response.end('404 Not Found'); } }) }) server.listen(8089); console.log('Server is running at http://127.0.0.1:8089/');]]></content>
<categories>
<category>Node.js</category>
</categories>
<tags>
<tag>Node.js</tag>
</tags>
</entry>
<entry>
<title><![CDATA[node-stream]]></title>
<url>%2Fliuyang996.github.io%2F2018%2F11%2F14%2Fnode-stream%2F</url>
<content type="text"><![CDATA[stream 模块,支持“流”这种数据模块 在Node.js中,流也是一个对象,我们只需要响应流的事件就可以了:data事件表示流的数据已经可以读取了,end事件表示这个流已经到末尾了,没有数据可以读取了,error事件表示出错了。 从文件流读取文本内容示例: 'use strict'; var fs = require('fs'); // 打开一个流: var rs = fs.createReadStream('sample.txt', 'utf-8'); rs.on('data', function (chunk) { console.log('DATA:') console.log(chunk); }); rs.on('end', function () { console.log('END'); }); rs.on('error', function (err) { console.log('ERROR: ' + err); }); 注意: data 事件可能会有多次,每次传递的 chunk 是流的一部分数据。 要以流的形式写入文件,只需要不断调用 write() 方法,最后以 end()结束 : 'use strict'; var fs = require('fs'); var ws1 = fs.createWriteStream('output1.txt', 'utf-8'); ws1.write('使用Stream写入文本数据...\n'); ws1.write('END.'); ws1.end(); var ws2 = fs.createWriteStream('output2.txt'); ws2.write(new Buffer('使用Stream写入二进制数据...\n', 'utf-8')); ws2.write(new Buffer('END.', 'utf-8')); ws2.end(); 所有可以读取数据的流都继承自stream.Readable,所有可以写入的流都继承自stream.Writable。 pipe就像可以把两个水管串成一个更长的水管一样,两个流也可以串起来。一个Readable和一个Writable流串起来后,所有的数据自动从Readable流进入Writable流,这种操作叫pipe。 在Node.js中,Readable流有一个pipe()方法。 我们可以用pipe()把一个文件流和另一个文件流串起来,这样源文件的所有数据就自动写入到目标文件里了,所以,这实际上是一个复制文件的程序: 'use strict'; var fs = require('fs'); var rs = fs.createReadStream('sample.txt'); var ws = fs.createWriteStream('copied.txt'); rs.pipe(ws); 默认情况下, 当Readable流的数据读取完毕,end事件触发后,将自动关闭Writable流,如果我们不希望自动关闭Writable流,需要传入参数 rs.pipe(ws,{end:false});]]></content>
<categories>
<category>Node.js</category>
</categories>
<tags>
<tag>Node.js</tag>
</tags>
</entry>
<entry>
<title><![CDATA[理解Object.defineProperty的作用]]></title>
<url>%2Fliuyang996.github.io%2F2018%2F11%2F14%2Fjs3%2F</url>
<content type="text"><![CDATA[使用Object.defineProperty定义新属性或修改原有的属性。 语法: Object.defineProperty(obj,prop,descriptor) 参数说明: obj:必须。目标对象。 prop:必须。需定义或修改的属性的名字。 descriptor:必须。目标属性所拥有的特性。 返回值: 传入函数的对象。即第一个参数obj 针对属性,我们可以给这个属性设置一些特性,比如是否只读不可以写,是否可以被 for..in或Object.keys()遍历。 给对象的属性添加特性描述,目前提供两个形式:数据描述和存取器描述。 数据描述当修改或定义对象的某个属性的时候,给这个属性添加一些特性: var obj = { test:"hello" } //对象已有的属性添加特性描述 Object.defineProperty(obj,'test',{ configurable:true | false, enumerable: true | false, value: 任意类型的值, writable: true | false }); //对象新添加的属性的特性描述 Object.defineProperty(obj,"newkey",{ configurable: true | false, enumerable: true | false, value:任意类型的值, writable: true | false }) value :属性对应的值,可以是任意类型的值,默认为undefinedwritable :属性的值是否可以被重写。设置为true可以被重写;设置为false,不能被重写。默认为false。 var obj = {} //第一种情况:writable设置为false,不能重写。 Object.defineProperty(obj,"newKey",{ value:"hello", writable:false }); //更改newKey的值 obj.newKey = "change value"; console.log( obj.newKey ); //hello //第二种情况:writable设置为true,可以重写 Object.defineProperty(obj,"newKey",{ value:"hello", writable:true }); //更改newKey的值 obj.newKey = "change value"; console.log( obj.newKey ); //change value enumerable 此属性是否可以被枚举(使用for..in或Object.keys())。设置为true可以被枚举;设置为false,不能被枚举。默认为 false。 configurable 是否可以删除目标属性或是否可以再次修改属性的特性(writable,configurable,enumerable)。设置为true可以被删除或可以重新设置特性;设置为false,不能被删除或不可以重新设置特性。默认为false。 这个属性起到两个作用: 目标属性是否可以使用delete删除 目标属性是否可以再次设置特性 //-----------------测试目标属性是否能被删除------------------------ var obj = {} //第一种情况:configurable设置为false,不能被删除。 Object.defineProperty(obj,"newKey",{ value:"hello", writable:false, enumerable:false, configurable:false }); //删除属性 delete obj.newKey; console.log( obj.newKey ); //hello //第二种情况:configurable设置为true,可以被删除。 Object.defineProperty(obj,"newKey",{ value:"hello", writable:false, enumerable:false, configurable:true }); //删除属性 delete obj.newKey; console.log( obj.newKey ); //undefined //-----------------测试是否可以再次修改特性------------------------ var obj = {} //第一种情况:configurable设置为false,不能再次修改特性。 Object.defineProperty(obj,"newKey",{ value:"hello", writable:false, enumerable:false, configurable:false }); //重新修改特性 Object.defineProperty(obj,"newKey",{ value:"hello", writable:true, enumerable:true, configurable:true }); console.log( obj.newKey ); //报错:Uncaught TypeError: Cannot redefine property: newKey //第二种情况:configurable设置为true,可以再次修改特性。 Object.defineProperty(obj,"newKey",{ value:"hello", writable:false, enumerable:false, configurable:true }); //重新修改特性 Object.defineProperty(obj,"newKey",{ value:"hello", writable:true, enumerable:true, configurable:true }); console.log( obj.newKey ); //hello 定义对象的时候添加的属性,是可删除、可重写、可枚举的。 一旦使用Object.definePropery给对象添加属性,那么如果不设置属性的话,configurable、enumerable、writable这些值都为默认的false。这就导致了nekyey这个是不能重写、不能枚举、不能再次设置特性。 设置的特性总结: value : 设置属性的值writable: 值是否可以重写。 true | falseenumerable: 目标属性是否可以被枚举。 true | falseconfigurable: 目标属性是否可以被删除或是否可以再次修改特性 true | false 存取器描述当使用存取器描述属性的特性的时候,允许设置以下特性属性: var obj = {}; Object.defineProperty(obj,"newKey",{ get:function (){} | undefined, set:function (value){} | undefined, configurable: true | false, enumerable: true | false, }) 注意:当使用了getter和setter方法,不允许使用writable和value这两个属性 getter/setter当设置或获取对象的某个属性的值的时候,可以提供getter/setter方法。 getter 是一种获得属性值的方法。 setter 是一种设置属性值的方法。 在特性中使用get/set属性来定义对应方法。 var obj = {}; var initVlue = 'hello'; Object.defineProperty(obj,'newKey',{ get: function (){ //当获取值的时候调用此函数 return initVlue; }, set: function (value){ initVlue = value; } }); //获取值 console.log(obj.newKey); //设置值 obj.newKey = 'world'; console.log(obj.newKey); 注意:get或set不是必须成对出现,认写其一就可以。如果不设置,则set/get的默认值为undefined。 configurable 和 enumerable和上面用法一样。]]></content>
<categories>
<category>javascript</category>
</categories>
<tags>
<tag>javascript</tag>
</tags>
</entry>
<entry>
<title><![CDATA[node-fs 文件系统模块]]></title>
<url>%2Fliuyang996.github.io%2F2018%2F11%2F14%2Fnode-fs%2F</url>
<content type="text"><![CDATA[Node.js - fs Node.js内置的fs模块就是文件系统模块,负责读写文件。 fs模块同时提供了异步和同步的方法。 异步读文件'use strict'; var fs = require('fs'); fs.readFile('sample.txt', 'utf-8', function (err, data) { if (err) { console.log(err); } else { console.log(data); } }); 注意 sample.txt文件路径和文件编码。 异步读取时,传入的回调函数接收两个参数,err和data,第一个参数为err表示出错,第二个参数为data,表示结果。 当读取二进制文件时,不传入文件编码时,data将返回一个Buffer对象。在Node.js中,Buffer对象就是一个包含零个或任意个字节的数组(和Array不同) 同步读文件同步读取的函数和异步函数相比,多了一个Sync后缀,并且不接受回调函数,函数直接返回结果。 'use strict'; var fs = require('fs'); var data = fs.readFileSync('sample.txt', 'utf-8'); console.log(data); 如果同步读取文件发生错误,需要用try…catch捕获该错误 : try { var data = fs.readFileSync('sample.txt','uft-8'); console.log(data); } catch (err) { //出错了 } 写文件 将数据写入文件是通过fs.writeFile()实现的: 'use strict' var fs = require('fs'); var data = 'hello , Node.js'; //写文件 fs.writeFile('output.txt',data,function (err) { if(err){ console.log(err); } else { console.log('ok'); } }) writeFile()的参数依次为文件名、数据和回调函数。如果传入的数据是String,默认按utf-8编码写入文件,如果传入的参数是Buffer,则写入的是二进制文件。回调函数只关心是否成功,所以只需要传入一个err参数。 写文件的同步方法,为 writeFileSync(); stat如果我们要获取文件大小,创建时间等信息,可以使用fs.stat(),它返回一个Stat对象,能告诉我们文件或目录的详细信息: 'use strict'; var fs = require('fs'); fs.stat('sample.txt', function (err, stat) { if (err) { console.log(err); } else { // 是否是文件: console.log('isFile: ' + stat.isFile()); // 是否是目录: console.log('isDirectory: ' + stat.isDirectory()); if (stat.isFile()) { // 文件大小: console.log('size: ' + stat.size); // 创建时间, Date对象: console.log('birth time: ' + stat.birthtime); // 修改时间, Date对象: console.log('modified time: ' + stat.mtime); } } }); 运行结果如下: isFile:true isDirectoryfalse size :30 birth time :Wed Nov 14 2018 14:00:32 GMT+0800 (中国标准时间) modified timeWed Nov 14 2018 14:07:15 GMT+0800 (中国标准时间) stat()也有一个对应的同步函数 statSync(). 异步 vs 同步 由于Node环境执行的JavaScript代码是服务器端代码,所以,绝大部分需要在服务器运行期间反复执行业务逻辑的代码,必须使用异步代码,否则,同步代码在执行期间,服务器将停止响应。因为JavaScript只有一个执行线程。 服务器启动时如果需要读取配置文件,或者结束时需要写入到状态文件时,可以使用同步代码,因为这些代码只在启动和结束时执行一次,不影响服务器正常运行时的异步执行。]]></content>
<categories>
<category>Node.js</category>
</categories>
<tags>
<tag>Node.js</tag>
</tags>
</entry>
<entry>
<title><![CDATA[node.js]]></title>
<url>%2Fliuyang996.github.io%2F2018%2F11%2F10%2Fnode1%2F</url>
<content type="text"><![CDATA[Node.js学习module.exports vs exports在Node环境中,有两种方法可以在一个模块中输出变量: module.exports = { one:one, greet:greet } exports.one = one; exports.greet = greet; Node加载机制 1.首先,Node会先准备一个对象module: //准备module对象 var module = { id:'hello', exports: {} } Node会把整个待加载的js文件(如hello.js),放入一个包装函数load中执行。 var load = function (module) { // hello.js文件内容 //load函数返回 return module.exports; } var exported = load(module); save(module,exported); 3.load()函数最终返回module.exports 基本模块global 在Node环境中,唯一的全局对象,叫global,这个对象的属性和方法和浏览器环境的window不同。 进入Node.js交互环境,输入: global.console 可以查看方法。 > global.console Console { log: [Function: bound ], info: [Function: bound ], warn: [Function: bound ], error: [Function: bound ], dir: [Function: bound ], time: [Function: bound ], timeEnd: [Function: bound ], trace: [Function: bound trace], assert: [Function: bound ], Console: [Function: Console] } process process 也是Node.js提供的一个对象,它代表当前Node.js进程。通过process对象可以拿到许多有用信息。 JavaScript程序是由事件驱动执行的单线程模型,Node.js也不例外。Node.js不断执行响应事件的JavaScript函数,直到没有任何响应事件的函数可以执行时,Node.js就退出了。 如果我们想要在下一次事件响应中执行代码,可以调用process.nextTick(): // test.js // process.nextTick()将在下一轮事件循环中调用: process.nextTick(function () { console.log('nextTick callback!'); }); console.log('nextTick was set!'); Node.js进程本身的事件就由process对象来处理。如果我们响应exit事件,就可以在程序即将退出时执行某个回调函数。 // 程序即将退出时的回调函数: process.on('exit', function (code) { console.log('about to exit with code: ' + code); }); 判断JavaScript执行环境if(typeof(window) === 'undefined') { console.log('node.js'); } else { console.log('browser') }]]></content>
<categories>
<category>Node.js</category>
</categories>
<tags>
<tag>Node.js</tag>
</tags>
</entry>
<entry>
<title><![CDATA[热门技术参考文档]]></title>
<url>%2Fliuyang996.github.io%2F2018%2F10%2F31%2Fremenjishu%2F</url>
<content type="text"><![CDATA[小程序篇vant Weapp UI组件库 地址:https://youzan.github.io/vant-weapp/#/intro markdownPad2 语法博客地址:https://www.jianshu.com/p/e9840793d8c2 vue篇1 vue UI框架· iView · VUX 2 vue相关博客·vue2.0做移动端开发用到的相关插件和经验总结01 ·vue2.0做移动端开发用到的相关插件和经验总结02 涉及内容: 1 vue-lazyload :一个简单易用的 Vue 图片延迟加载插件; 2 vuex:vue状态管理工具详细入门; 3 async/await:异步神器来封装接口请求文件fetch.js 4 vue 项目中的迭代判断技巧; 5 vue 项目中常用的图片引入方式; 6 微信api在vue项目中的使用: 7 vue2实现微信分享坑点和经验 ; 8 百度地图api在vue项目中的使用: 9 cssrem:一个CSS值转REM的VSCode插件; 10 lib-flexible:移动端弹性布局适配解决方案; 11 vue-touch:移动端相关点击,滑动,拖动,多点触控等事件封装; 12 vee-validate:适用于vue项目中表单验证插件; 13 better-scroll :可能是目前最好用的移动端滚动插件; 14 fastclick:解决移动端click 300ms延迟; 15 vConsole:手机前端开发调试利器; 16 webpack之proxyTable设置跨域; · 学习不易,用vue写了一个入门项目——知乎日报 · vue中Axios的封装和API接口的管理]]></content>
<tags>
<tag>热门技术参考文档</tag>
</tags>
</entry>
<entry>
<title><![CDATA[javaScript的常用高阶函数使用]]></title>
<url>%2Fliuyang996.github.io%2F2018%2F10%2F22%2Fjs2%2F</url>
<content type="text"><![CDATA[map,reduce,filter等高阶函数 一个函数可以接收另一个函数作为参数,这种函数就称之为高阶函数 map 让数组通过某种计算产生一个新数组 var arr = [1,2,3,4,5,6]; var newArr = arr.map(function(item,index){ return item*2; }) newArr =>[2,4,6,8,10,12]; reduce 让数组中的前项和后项做某种计算,并累计最终值 var result = arr.reduce(function(prev,next){ return prev+next; }) filter 筛选出数组中符合条件的项,组成新的数组,和map()不同的是,filter()把传入的函数依次作用于每个元素,然后根据每个值是true还是false决定保留还是丢弃该元素。 var newArr = arr.filter(function(item,index){ return item>3; }) 扁平化(flatten) 数组 扁平化就是将嵌套的数组变成一堆一维数组的过程。 var array = [[1,2,3],4,5,6,[[7]],[]] var result = flatten(array) 我们可以通过reduce函数,非常简洁的实现flatten function flatten(arr) { return arr.reduce((flat, toFlatten) => { return flat.concat(Array.isArray(toFlatten) ? flatten(toFlatten) : toFlatten); }, []); } some some() 方法用于检测数组中的元素是否满足指定条件. 如果有一个元素满足条件,则表达式返回true,剩下的元素不会再执行。 如果没有满足条件的元素,则返回false. function isBigEnough(element, index, array) { return (element >= 10); } var passed = [2, 5, 8, 1, 4].some(isBigEnough); findIndex findIndex() 方法返回传入一个符合条件的数组第一个元素位置。 当数组有符合条件的元素时,返回索引位置 如果没有符合条件的元素返回-1 不会改变数组的原始值。]]></content>
<categories>
<category>javascript</category>
</categories>
<tags>
<tag>javascript</tag>
</tags>
</entry>
<entry>
<title><![CDATA[热门技术参考文档]]></title>
<url>%2Fliuyang996.github.io%2F2018%2F09%2F18%2Fblog%2F</url>
<content type="text"><![CDATA[小程序篇vant Weapp UI组件库 地址:https://youzan.github.io/vant-weapp/#/intro markdownPad2 语法博客地址:https://www.jianshu.com/p/e9840793d8c2 vue篇1 vue UI框架· iView · VUX 2 vue相关博客·vue2.0做移动端开发用到的相关插件和经验总结01 ·vue2.0做移动端开发用到的相关插件和经验总结02 涉及内容: 1 vue-lazyload :一个简单易用的 Vue 图片延迟加载插件; 2 vuex:vue状态管理工具详细入门; 3 async/await:异步神器来封装接口请求文件fetch.js 4 vue 项目中的迭代判断技巧; 5 vue 项目中常用的图片引入方式; 6 微信api在vue项目中的使用: 7 vue2实现微信分享坑点和经验 ; 8 百度地图api在vue项目中的使用: 9 cssrem:一个CSS值转REM的VSCode插件; 10 lib-flexible:移动端弹性布局适配解决方案; 11 vue-touch:移动端相关点击,滑动,拖动,多点触控等事件封装; 12 vee-validate:适用于vue项目中表单验证插件; 13 better-scroll :可能是目前最好用的移动端滚动插件; 14 fastclick:解决移动端click 300ms延迟; 15 vConsole:手机前端开发调试利器; 16 webpack之proxyTable设置跨域; · 学习不易,用vue写了一个入门项目——知乎日报 · vue中Axios的封装和API接口的管理]]></content>
<categories>
<category>热门技术参考文档</category>
</categories>
<tags>
<tag>热门技术参考文档</tag>
</tags>
</entry>
<entry>
<title><![CDATA[微信小程序-promise的用法]]></title>
<url>%2Fliuyang996.github.io%2F2018%2F08%2F29%2Fxiaochengxu4%2F</url>
<content type="text"><![CDATA[在写业务逻辑的时候,经常会碰到在一个接口里需要回调另外一个接口,或者更多,这样代码看起来非常冗长,而且不易维护。用promise可以很好的解决这个问题。 在util.js文件加入如下代码function wxPromisify(fn) { return function (obj = {}) { return new Promise((resolve, reject) => { obj.success = function (res) { resolve(res) } obj.fail = function (res) { reject(res) } fn(obj) }) } } module.exports = { wxPromisify: wxPromisify } 使用方法: 在需要的文件中引入 var util = require('../../utils/util') var Wxrequest = util.wxPromisify(wx.request); Wxrequest({ url: 'test.php', //仅为示例,并非真实的接口地址 data: { x: '' , y: '' }, header: { 'content-type': 'application/json' }, }) .then(function(res){ console.log(res); }) PS:其他的API也可以适用; 提示:在编写业务代码时,尽量把能共用的方法,提取出来,这样会减少很多代码量。一遍在修改维护的时候更好的阅读代码。]]></content>
<categories>
<category>微信小程序</category>
</categories>
<tags>
<tag>微信小程序</tag>
</tags>
</entry>
<entry>
<title><![CDATA[git使用教程]]></title>
<url>%2Fliuyang996.github.io%2F2018%2F08%2F13%2Fgit%2F</url>
<content type="text"><![CDATA[分布式版本控制系统 在windows 上安装Git,可以从Git官网直接下载安装完成后,在开始菜单里找到“Git”->“Git Bash”,蹦出一个类似命令行窗口的东西,就说明Git安装成功! 安装完成后,还需要最后一步设置,在命令行输入: $ git config --global user.name "Your Name" $ git config --global user.email "[email protected]" 创建版本库版本库可以理解为一个目录,目录里的文件都可以被Git管理。每个文件的修改、删除,Git都能跟踪,以便任何时刻都可以追踪历史,或者在将来某个时刻可以“还原”。 先在一个合适的地方创建一个空目录。(目录名不要包含中文,包括父级)通过git init 命令把这个目录变成Git可以管理的仓库。$ git init 建好后,当前目录会多一个.git的目录,不要随意修改这个目录,可能会把Git仓库弄乱。(如果没有看到.git目录,是因为这个目录默认是隐藏的。) 在windows系统下不要使用自带的记事本编辑文件文件。可以使用别的。如Notepad++ 把需要上传的文件放到Git目录下,然后 用命令 git add 告诉Git,把文件添加到仓库:$ git add readme.txt PS:readme.txt是我放的文件 用命令 git commit 告诉Git,把文件提交到仓库:$ git commit -m 'wrote a readme file' -m 后面输入的是提交的说明。 git commit命令执行成功后会告诉你,1 file changed:1个文件被改动(我们新添加的readme.txt文件);2 insertions:插入了两行内容(readme.txt有两行内容)。 时光机穿梭git status 命令可以让我们时刻掌握仓库当前的状态。 我改了readme.txt里的内容后使用命令,会出现上面这个截图。告诉我们,readme.txt被修改过了,但还没有准备提交的修改。 git diff 查看difference,看看文件做了什么修改,然后在提交提交还是用 git add ‘’ git commit -m ‘’ 版本回退git log 命令显示从最近到最远的提交日志。–hard HEAD^git reset --hard HEAD^ 使用 –hard HEAD^可以回退到上一个版本,上上一个版本就是HEAD^^如果回退100个版本,可以写成HEAD~100 回退后,之前的版本就看不到了。可以使用git log查看。 如果想要再回到之前的版本肿么办呢。只要这个命令窗口还没有被关掉,就可以顺着往上找,找到那个 commit ID,就可以返回到指定版本 git reset --hard bf30 版本号不需要写全,前几位就可以了。 如果回退到了某个版本,关掉了电脑,第二天又后悔了,想恢复到新版本怎么办?找不到新版本的commit id 怎么办 ?当你用 git reset –hard HEAD^ 回退到add distributed 版本时,再想恢复到新版本。Git提供了一个命令,git reflog 用来记录你的每一次命令。可以 从命令输出里查看版本的commit id,然后回到指定版本 $ git reflog e475afc HEAD@{1}: reset: moving to HEAD^ 1094adb (HEAD -> master) HEAD@{2}: commit: append GPL e475afc HEAD@{3}: commit: add distributed eaadf4e HEAD@{4}: commit (initial): wrote a readme file 工作区和暂存区工作区: 平时看到的目录了就是工作区。版本库: 工作区有一个隐藏目录.git,这个是Git的版本库。 Git的版本库里存了很多东西,其中最重要的就是称为stage(或者叫index)的暂存区,还有Git为我们自动创建的第一个分支master,以及指向master的一个指针叫做HEAD. 我们把文件往Git版本库里添加的时候,是分两步执行的: 第一步是用 git add把文件添加进去,实际上就是把文件修改添加到暂存区。 第二部是用 git commit提交更改,实际上就是把暂存区的所有内容提交到当前分支。 实际上就是把需要提交的文件修改通通放到暂存区,然后,一次性提交暂存区的所有修改。 管理修改Git管理的是修改,每次修改后 使用 git add 文件 把修改放入暂存区,如果修改后没有使用 git add 话,那么在使用git commit 提交的时候,便不会把这个修改的内容提交。 我可以使用 git diff HEAD – readme.txt ,命令可以查看工作区和版本库里面最新版本的区别。 撤销修改$ git checkout -- readme.txt 命令git checkout – readme.txt意思就是,把readme.txt文件在工作区的修改全部撤销: 一种是readme.txt自修改后还没有被放到暂存区,现在,撤销修改就回到和版本库一模一样的状态 一种是readme.txt已经添加到暂存区后,又作了修改,现在,撤销修改就回到添加到暂存区后的状态。 注意 git checkout – file 命令中的 – 。 小结:场景1:当你改乱了工作区某个文件的内容,想直接丢弃工作区的修改时,用命令git checkout – file。 场景2:当你不但改乱了工作区某个文件的内容,还添加到了暂存区时,想丢弃修改,分两步,第一步用命令git reset HEAD ,就回到了场景1,第二步按场景1操作。 场景3:已经提交了不合适的修改到版本库时,想要撤销本次提交,参考版本回退,不过前提是没有推送到远程库。]]></content>
<tags>
<tag>Git</tag>
</tags>
</entry>
<entry>
<title><![CDATA[css常用布局]]></title>
<url>%2Fliuyang996.github.io%2F2018%2F07%2F16%2Fcssbuju%2F</url>
<content type="text"><![CDATA[flex弹性布局兼容性 常见布局 .wrapper{ display: -webkit-flex; /* Safari */ display: flex; } .item{ flex:1; } flex实现1行指定div个数布局方式html: <div class="community-list"> <div class="community-item"> content.... </div> ... </div> css: .community-list{ display: flex; flex-wrap: wrap; .... } .community-item{ flex: 0 0 25%; } PS:我这里一行指定4个,根据需要改变 flex: 0 0 (百分比) 的值即可。 flex实现左侧固定宽度,右侧自适应宽度<div class="wrapper"> <div class="sideBar"></div> <div class="content"></div> </div> css样式 html,body,wrapper{ width:100%; height:100%; } .wrapper{ display:flex; } .sideBar{ flex: 0 0 80px //设置固定宽度为80px } .content{ flex:1 } grid网格布局兼容性 CSS Grid布局由两个核心组件wrapper(父元素)和items(子元素)。wrapper是实际的grid(网格),items是grid(网格)内的内容。 HTML代码: <div class="wrapper"> <div class="items1">1</div> <div class="items2">2</div> <div class="items3">3</div> <div class="items4">4</div> <div class="items5">5</div> <div class="items6">6</div> </div> css: .wrapper { display: grid; grid-template-columns: 200px 50px 100px; grid-template-rows: 100px 30px; } .items1{ grid-column-start: 1; grid-column-end: 4; grid-row-start: 2; grid-row-end: 4; } 样式说明: 父元素 display: grid; 把wrapper 元素变成一个 grid(网格)。 grid-template-columns; 设置网格内的子元素有几列,每1列的宽度是多少。如上是有3列,第1列200px,第二列50px,第三列100px。 grid-template-rows; 设置网格内的子元素有几行,每1行的高度是多少。如上是有2行,第1行100px,第二列30px。 子元素 grid-column-start; 列的网格线开始。 grid-column-end; 列的网格线开始。 grid-row-start; 行的网格线开始。 grid-row-end; 行的网格线开始。 Sticky footer布局作用:在实际开发中,我们经常会遇到这样一个需求:如果页面小于一屏时,页脚块需要固定在页面底部,如果页面超过一屏时,页脚块向下推送。 <div class="wrapper clearfix"> <div class="content"> // 这里是页面内容 </div> </div> <div class="footer"> // 这里是footer的内容 </div> css代码: .wrapper { min-height: 100%; } .wrapper .content{ padding-bottom: 50px; /* footer区块的高度 */ } .footer { position: relative; margin-top: -50px; /* 使footer区块正好处于content的padding-bottom位置 */ height: 50px; clear: both; } .clearfix::after { display: block; content: "."; height: 0; clear: both; visibility: hidden; } 注意:content元素的padding-bottom、footer元素的高度以及footer元素的margin-top值必须要保持一致。]]></content>
<categories>
<category>CSS</category>
</categories>
<tags>
<tag>CSS Sprites</tag>
</tags>
</entry>
<entry>
<title><![CDATA[ionic3 关闭新增页面,跳转到原页面刷新数据(回显)]]></title>
<url>%2Fliuyang996.github.io%2F2018%2F07%2F05%2Fionic5%2F</url>
<content type="text"><![CDATA[问题描述在项目中,我们经常会遇见新增表单的情况,如登录注册、列表项新增,那么在这种情况下,如果我们用常用的push来跳转页面,在新增完后,如果跳转到新增前页面,就会有返回箭头,按手机返回键也会导致页面回到新增表单页,这样用户体验很不好,解决的办法是用,modal组件和ViewController组件来完成这种操作 解决办法1.跳转前页面 引入modal组件 import {ModalController} from 'ionic-angular'; constructor(public modalCtrl: ModalController){} 跳转到表单添加页面 gotoLeaveAddPage() { let modal = this.modalCtrl.create('LeaveAddComponent',{ leave:this.leave }); modal.onDidDismiss(data => { //核心功能,在这里刷新,即重新查一遍即可 console.log(data); }); modal.present(); } LeaveAddComponent是跳转页面路径leave是传输数据 这里的重点是onDidDismiss()方法,通过这个方法,可以拿到跳转后的页面传过来的数据,怎么传数据下面会讲。 2.跳转后页面 引入ViewController组件 import {ViewController} from 'ionic-angular'; constructor(public viewCtrl: ViewController){} 使用dismiss()方法关闭页面,并传输数据 this.viewCtrl.dismiss({ 'danyuan_id': this.danyuan_id, }) 数据传输后,通过跳转前页面的,onDidDismiss()方法接收数据,并且在该方法内重新加载一次接口即可刷新数据。这样按返回就不会跳到表单页。]]></content>
<categories>
<category>ionic</category>
</categories>
<tags>
<tag>ionic</tag>
</tags>
</entry>
<entry>
<title><![CDATA[ionic3 父子组件相互传值及调用子组件方法]]></title>
<url>%2Fliuyang996.github.io%2F2018%2F07%2F02%2Fionic4%2F</url>
<content type="text"><![CDATA[在开发中,对于创建的组件,一般都会涉及到传值,或者调用子组件的方法,这里介绍下我的用法。父组件向子组件传值 @Input() 子组件: 1.子组件中import {Input} from ‘@angular/core’ 2.子组件使用Input定义接收的值。 @Input() info:any; 父组件: 例如定义的子组件标签为: <child></child> 那么传值给子元素的方法为: <child [info]='childdata' ></child> 其中,[info]为子元素接收的值,与子元素Input定义的值一样。childdata为父元素传给子元素的数据。 PS:这里要注意生命周期执行顺序,例如如果传输的和接收的值都放在constructor作用域里,可以无法拿到数据。 子组件向父组件传值子组件: 1.子组件引入Output,EventEmitter import {Output,EventEmitter}from ‘@angular/core’ 2.子组件使用@Output定义传输的值。 @Output() private event:EventEmitter<Object> = new EventEmitter<Object>(); 这里定义的值为:event 3.使用 this.event.emit(‘传递的数据’)来触发 this.event.emit(this.fromDatas); 传递数据一般写在函数里。 父组件: 例如定义的子组件标签为: <child></child> 那么传值给父组件的方法为: <allform (event)='getForm($event)'></allform> 其中,event为子组件定义的值,getForm($event)为父组件定义的函数,子组件每次使用emit上传数据时都会调用此函数 getForm(event){ console.log(event); } PS:注意,getForm($event) 括号里的’$’不能省略。 父组件调用子组件的方法父组件: 1.在父组件控制器中声明一个由viewChild装饰器装饰的变量获得子组件的引用。 @ViewChild('formchild') child: AllFormComponent; 2.在组件中指定本地变量 <allform #formchild></allform> 3.调用子组件方法。 recordsForm(){ this.child.upward(); } PS:upward()函数为子组件定义的函数。recordsForm()函数为父组件里的函数。]]></content>
<categories>
<category>ionic</category>
</categories>
<tags>
<tag>ionic</tag>
</tags>
</entry>
<entry>
<title><![CDATA[ionic3 组件编写与使用]]></title>
<url>%2Fliuyang996.github.io%2F2018%2F06%2F22%2Fionic3%2F</url>
<content type="text"><![CDATA[1组件的创建ionic g component ion-products 成功之后可以看到目录会发生变化: 2组件的数据交互通过@Input()来实现数据交互,ion-products.ts完整代码如下: 3组件的html,scss编码... 3组件的使用组建创建成功时候,可以看到默认有一个components.module.ts,说明此component建默认是支持懒加载的。 components.modules.ts: 3.1导入component在home.module.ts中导入components.module.ts home.module.ts 3.2使用component]]></content>
<categories>
<category>ionic</category>
</categories>
<tags>
<tag>ionic</tag>
</tags>
</entry>
<entry>
<title><![CDATA[ionic3 相机和相册获取图片]]></title>
<url>%2Fliuyang996.github.io%2F2018%2F06%2F11%2Fionic2%2F</url>
<content type="text"><![CDATA[相机拍照和相册是 App 从手机获取图片的两种主要方式。在 App 业务需求中,经常会使用到图片获取的功能,最为常见的有用户头像设置等。插件介绍cordova-plugin-camera 相机插件: 安装方法: ionic cordova plugin add cordova-plugin-camera npm install --save @ionic-native/camera 作用:调用手机照相头,进行拍照获取图片、从相册获取单张图片。 cordova-plugin-image-picker 图片获取插件: 安装方法: // 注意: // 这个 "your usage message" 可以自己修改 // 这是在向用户请求权限时显示的文字 ionic cordova plugin add cordova-plugin-telerik-imagepicker --variable PHOTO_LIBRARY_USAGE_DESCRIPTION="your usage message" npm install --save @ionic-native/image-picker 作用:调用手机图库,获取照片,可选择多张。 使用方法:先把插件添加到 app.module.ts 的 providers Camera import { Camera, CameraOptions } from '@ionic-native/camera'; constructor( ... private camera: Camera) { } // 设置选项 const options: CameraOptions = { quality: 100, sourceType: this.camera.PictureSourceType.CAMERA, destinationType: this.camera.DestinationType.DATA_URL, encodingType: this.camera.EncodingType.JPEG, mediaType: this.camera.MediaType.PICTURE } // 获取图片 this.camera.getPicture(options).then((imageData) => { // 获取成功 let base64Image = 'data:image/jpeg;base64,' + imageData; }, (err) => { console.log('获取图片失败'); }); 理解起来应该不难,详细解释一下 CameraOptions 重点说一下 sourceType,这个参数设置为 PHOTOLIBRARY 就会从相册取图,设置为 CAMERA 会拍照,设置为 SAVEDPHOTOALBUM 会保存图片。 ImagePicker import { ImagePicker, ImagePickerOptions } from '@ionic-native/image-picker'; constructor( ... private imagePicker: ImagePicker) { } // 设置选项 const options: ImagePickerOptions = { maximumImagesCount: 6, width: IMAGE_SIZE, height: IMAGE_SIZE, quality: QUALITY_SIZE }; // 获取图片 this.imagePicker.getPictures(options).then((results) => { for (var i = 0; i < results.length; i++) { console.log('Image URI: ' + results[i]); } }, (err) => { console.log('获取图片失败'); }); 跟上面那个差不多,详细解释一下 ImagePickerOptions 图片上传 如果是 base64 图片上传,直接把二进制字符串作为参数传就好。 注意事项 iOS 无法打开相册 再执行一遍 $ ionic cordova plugin add cordova-plugin-telerik-imagepicker --variable PHOTO_LIBRARY_USAGE_DESCRIPTION="your usage message" 我们执行过后,会有一个插件 com.synconset.imagepicker 生成到 package.json 中,这个会导致 npm install 运行失败,解决方法只能把它删除。所以你再次安装的时候就会少一个这个插件,导致无法获取相册权限。Android 上没有这个问题。]]></content>
<categories>
<category>ionic</category>
</categories>
<tags>
<tag>ionic</tag>
</tags>
</entry>
<entry>
<title><![CDATA[NVS node版本切换工具]]></title>
<url>%2Fliuyang996.github.io%2F2018%2F05%2F30%2Fnvs%2F</url>
<content type="text"><![CDATA[在项目中node的版本可能和现在电脑上的node版本不一致,导致项目无法运行,我在ionic的项目就碰到这种情况,我的项目是node 6.x版本的,但是电脑是node 8.x版本的。网上的解决方法是安装node的n模块,来切换版本,但是我电脑是windows系统,无法安装使用。 后来找到了NVS版本切换工具,成功切换版本,运行项目。下载地址:https://github.com/jasongin/nvs/releases github:https://github.com/jasongin/nvs 里面有使用文档 常用命令:添加最新版本的节点或指定版本 nvs add latest 或 nvs add [version] 查看本地节点版本 nvs ls 在当前sell中使用节点版本 nvs use [version]]]></content>
<categories>
<category>node版本切换工具</category>
</categories>
<tags>
<tag>node版本切换工具 NVS</tag>
</tags>
</entry>
<entry>
<title><![CDATA[微信小程序图片上传及全屏预览]]></title>
<url>%2Fliuyang996.github.io%2F2018%2F05%2F15%2Fxiaochengxu3%2F</url>
<content type="text"><![CDATA[在小程序项目中上传资料的时候一般都需要上传图片,这里介绍一个多图上传,及全屏预览。 ####1.wxml <image class='addimg' src='../../images/addpic.png' bindtap='upImg'></image> <view class='l-pic-list' wx:if="{{imgStatus}}"> <image src='{{item}}' wx:for="{{zhaopianImg}}" class='zhaopianImg' data-index="{{index}}" bindtap="previewImage"></image> </view> 这里是装图片的容器及路径。 2.jspictures: [], //预览图片array zhaopianImg: '', imgStatus: false 初始化3个变量 //调用上传图片组件 upImg:function(){ var that =this; //图片选择 wx.chooseImage({ count: 4, // 默认9 sizeType: ['original', 'compressed'], // 可以指定是原图还是压缩图,默认二者都有 sourceType: ['album'], // 可以指定来源是相册还是相机,默认二者都有 success: function (res) { // 返回选定照片的本地文件路径列表,tempFilePath可以作为img标签的src属性显示图片 var tempFilePaths = res.tempFilePaths that.setData({ zhaopianImg: tempFilePaths, pictures: tempFilePaths, imgStatus: true }) console.log(that.data.zhaopianImg); // wx.uploadFile({ // url: '', //仅为示例,非真实的接口地址 // filePath: tempFilePaths[0], // name: 'file', // formData: { // 'user': 'test' // }, // success: function () { // } // }) } }) }, //图片预览 previewImage: function (e) { var that = this, //获取当前图片的下表 index = e.currentTarget.dataset.index, //数据源 pictures = this.data.pictures; wx.previewImage({ //当前显示下表 current: pictures[index], //数据源 urls: pictures }) }, 3.wxss.addimg{ width: 64rpx; height: 64rpx; } .zhaopianImg{ width: 160rpx; height: 160rpx; margin-right: 10rpx; } .l-pic-list{ margin-top: 30rpx; } 以上代码可以直接拷贝使用。]]></content>
<categories>
<category>微信小程序</category>
</categories>
<tags>
<tag>微信小程序</tag>
</tags>
</entry>
<entry>
<title><![CDATA[webPack学习之路]]></title>
<url>%2Fliuyang996.github.io%2F2018%2F05%2F10%2FwebPack%2F</url>
<content type="text"><![CDATA[什么是webpack?WebPack可以看做是模块打包机:它做的事情是,分析你的项目结构,找到JavaScript模块以及其它的一些浏览器不能直接运行的拓展语言(Sass,TypeScript等),并将其转换和打包为合适的格式供浏览器使用。在3.0出现后,Webpack还肩负起了优化项目的责任。 1.打包:可以把多个Javascript文件打包成一个文件,减少服务器压力和下载带宽。2.转换: 拓展语言转换成为普通的JavaScript,让浏览器顺利运行。3.优化:前端变的越来越复杂后,性能也会遇到问题,而WebPack也开始肩负起了优化和提升性能的责任。 全局安装 npm install -g webpack 对项目进行安装 先切换至要安装的项目路径在命令行输入: npm init 会生成package.json文件 输入下面命令进行项目目录的安装: npm install --save-dev webpack 这里的参数-save是要保存到package.json中,dev是在开发时使用这个包,而生产环境中不使用。 开发环境and生产环境 1.开发环境:在开发时需要的环境,这里指在开发时需要依赖的包。 2.生产环境:程序开发完成,开始运行后的环境,这里指要使项目运行,所需要的依赖包。 查看webpack版本webpack -v src文件夹:用来存放我们编写的javascript代码,可以简单的理解为用JavaScript编写的模块。dist文件夹:用来存放供浏览器读取的文件,这个是webpack打包成的文件。 webpack打包webpack {entry file} {destination for bundled file} 1.{entry file}:入口文件的路径,src/2.{destination for bundled file}:填写打包后存放的路径,dist/注意:在命令行中不需要写{}。 配置文件webpack.config.jswebpack.config.js就是Webpack的配置文件,这个文件需要自己在项目根目录下手动建立。 const path = require('path'); module.exports = { //入口文件的配置 entry:{ // 里面的entery是可以随便写的 entry:'./src/entery.js' }, // 出口文件的配置 output:{ // 打包的路径文件夹 path:path.resolve(__dirname,'dist'), // 打包的文件名称 filename:'bundle.js' }, // 模块:例如解读CSS,图片如何转换,压缩。 module:{}, // 插件,用于生产模板和各项功能 plugins:[], // 配置webpack开发服务功能 devServer:{} } 1.entry:配置入口文件的地址,可以是单一入口,也可以是多入口。 2.output:配置文件的地址,在webpack2.X版本后,支持多出口配置。 3.resolve:模块相关配置 PS:path.resolve(__dirname,’dist’)就是获取了项目的绝对路径多入口、多出口配置 entry、output //入口文件的配置项 entry:{ entry:'./src/entry.js', //这里我们又引入了一个入口文件 entry2:'./src/entry2.js' }, //出口文件的配置项 output:{ //输出的路径,用了Node语法 path:path.resolve(__dirname,'dist'), //输出的文件名称 filename:'[name].js' }, 设置webpack-dev-servernpm install webpack-dev-server --save-dev devServer:{ //设置基本目录结构 contentBase:path.resolve(__dirname,'dist'), //服务器的IP地址,可以使用IP也可以使用localhost host:'localhost', //服务端压缩是否开启 compress:true, //配置服务端口号 port:1717 } contentBase:配置服务器基本运行路径,用于找到程序打包地址。host:服务运行地址,建议使用本机IPcompress:服务器端压缩选型,一般设置为开启port:服务运行端口,建议不使用80,很容易被占用,这里使用了1717. 模块:CSS文件打包LoadersLoaders是Webpack最重要的功能之一,他也是Webpack如此盛行的原因。通过使用不同的Loader,Webpack可以转换脚本和工具,从而对不同的文件格式进行特定处理。]]></content>
<categories>
<category>webpack</category>
</categories>
<tags>
<tag>webpack</tag>
</tags>
</entry>
<entry>
<title><![CDATA[vue知识储备]]></title>
<url>%2Fliuyang996.github.io%2F2018%2F05%2F09%2Fvue1%2F</url>
<content type="text"><![CDATA[vue基础知识vue-cli 一级文件介绍.bablerc: bable相关配置 es6转es5.edittorconfig:编辑器相关配置 如空格,编码等.eslintrc.js : eslint相关配置,可设置检查语法配置.gitignore:git提交项,忽视文件等如node_modules.postcssre.js:css相关规则设置.packages.json:整个文件的描述 重定向和别名router-link改变默认点击事件 用event属性 <router-link event="mouseover"></router-link> 重定向export default new Router({ routers:[ { path:'*', redirect:{path:'/About'} redirect:(to)=>{ //to 目标路由 return xx; } } ] }) redirect 可以写上path值,也可以写上name值,还可以使用箭头函数 嵌套路由的使用export default new Router([ { path:'/home', component:Home, children:[ { path:'', //记得加上默认的子路由 component:stady } ] } ]) 在router-link中默认路由标签会自带active样式,使用exact 属性取消默认样式,使用嵌套路由时,父路由的name属性要去掉。在 router-link中,默认路由的路径可以直接填写父路由的路径即可。 <router-link :to="{path:'/home'}" tag="li"><a>study</a></router-link> 命名视图配置多个视图 export default new Router([ { path:'/home', components:{ defualt:document, slider:slider }, } ]) 滚动行为记录浏览器前进后退、切换导航时,滚动条的位置。在路由配置中设置scrollBehavior(to,from,savePosition)函数 scrollBehavior(to,from,savePosition){ // 在点击浏览器的“前进/后退”,或者切换导航的时候触发。 console.log(to) // to:要进入的目标路由对象,到哪里去 console.log(from) // from:离开的路由对象,哪里来 console.log(savePosition) // savePosition:会记录滚动条的坐标,点击前进/后退的时候记录值{x:?,y:?} if(savePosition){ return savePosition; }else{ return {x:0,y:0}; } } 动态路径匹配到的所有路由,全都映射到同一个组件 路径 :/user/:userId? userId为动态路径参数 获取参数: 路由信息对象的params 监控$route路由信息对象 watch:{ $route(){ console.log(this.$route.params.userId); var id = this.$route.params.userId; this.getData(id); } }, query 字符串传参<router-link :to="{path:'',query:{info:'1',follow:'1'}}">他的爱好</router-link> 导航切换过渡动画transiton使用v-enter:进入时的开始状态v-enter-to:进入时的结束状态v-enter-active:进入时的持续时间v-leave:离开时开始状态v-leave-to:离开时结束状态v-leave-active:离开时的持续时间。 过渡模式 in-out:新元素先进行过渡,完成之后当前元素过渡离开。out-in:当前元素先进行过渡,完成之后新元素过渡进入。 动态设置name属性左右切换绑定name属性,可以动态设置动画样式,如页面左右切换,可以通过监听路由属性来实现。 路由元信息 在路由配置中meta可以配置一些数据,用在路由信息对象中访问meta中数据:$route.meta。 编程式导航借助于router的实例方法,通过编写代码来实现导航的切换。 back 回退一步forward 前进一步go 指定前进回退步数push 导航到不同url,向history栈添加一个新的记录replace 导航到不同url,替换history栈中当前记录 导航钩子函数导航发生变化时,导航钩子主要用来拦截导航,让它完成跳转或取消 执行钩子函数位置router全局 单个路由 组件中 钩子函数router实例上: beforeEach、afterEach单个路由中: beforeEnter组件内的钩子: beforeRouteEnter、beforeRouteUpdate、beforeRouteLeave (进入、更新、离开) 可以控制组件是否可以进入、更新、离开。 钩子函数接收的参数to: 要进入的目标路由的参数 到那里去from: 正要离开导航的路由对象 从哪里去next: 用来决定跳转或取消导航。 Vue插件的编写vue可以通过Vue实例的方式来添加全局属性 Vue.prototype.$custom = "这是自定义的属性" 也可以使用对象的方法来添加全局方法 let obj = { install:function(Vue,options){ Vue.prototype.$abc = "自定义" console.log(Vue) console.log(options) } } Vue.use(obj,{a:1}) vue的插件,用来获取和设置localStorage存储let local = { save(key,value){ localStorage.setItem(key,JSON.stringify(value)) }, fetch(key){ return JSON.parse(localStorage.getItem(key)) || {} } } export defualt { install: function (vm){ vm.prototype.$local = local } } 在main.js文件引入 Vue.use(xx) axios 转换请求数据配置创建 axios.create(config)配置let http = axios.create({ baseURL: 'http://192.168.0.110:8080/',//配置相对路径 timeout:1000, //配置请求超时时间 withCredentials: false, headers: { //配置请求头 'Content-Type': 'application/x-www-form-urlencoded;charset=utf-8' }, parmas:{ //查询字符串 book:'123' }, transformRequest: [function (data) { //只适合PUT POST 和PATCH let newData = ''; for (let k in data) { if (data.hasOwnProperty(k) === true) { newData += encodeURIComponent(k) + '=' + encodeURIComponent(data[k]) + '&'; } } return newData; }], transformResponse: [function (data) { return data; }], cancelToken:source.token }); axios 取消请求配置创建取消请求令牌 var CancelToken = axios.CancelToken; var source = CancelToken.source(); 配置 : cancelToken:source.token 捕获取消错误 if(axios.isCancel(error)){ console.log(error.message); } 调用取消 source.cancel('操作被用户取消'); $emit监听当前实例上的自定义事件。事件可以由vm.$emit触发。回调函数会接收所有传入事件触发函数的额外参数。 $on触发当前实例上的事件。附加参数都会传给监听器回调。 非父子组件(兄弟组件)通信 当非父子组件通信时,需要通过一个全局的vue实例或者说需要一个桥梁(媒介), EventBus.js import Vue from 'vue' export default new Vue(); 在需要通行的组件中引入 import Bus from '../../common/js/eventBus'; 触发事件 Bus.$emit('rating.select',type); 接收事件 Bus.$on('rating.select',selectType => { console.log('监听组件type值,'+selectType); }) ref、$refs$nextTick用法:在下次DOM更新循环结束之后执行延迟回调。在修改数据之后立即使用这个方法,获取更新后的DOM. Vue.set(target,key,value)target:要更改的数据key:数据的第几项value:更改后的数据 用法: 向响应式对象中添加一个属性,并确保这个新属性同样是响应式的,且触发视图更新。 使用better-scroll滚动插件时,阻止点击事件执行两次if(!event._constructed){ return; } PS:事件需传入$event对象]]></content>
<tags>
<tag>vue</tag>
</tags>
</entry>
<entry>
<title><![CDATA[vue-axios的使用]]></title>
<url>%2Fliuyang996.github.io%2F2018%2F04%2F28%2Faxios%2F</url>
<content type="text"><![CDATA[axios在vue中的简单配置与使用。安装axios npm install axios --save 封装axios可以新建一个api文件夹,新建http.js文件 import axios from 'axios' import qs from 'qs' axios.defaults.timeout = 5000; //响应时间 axios.defaults.headers.post['Content-Type'] = 'application/x-www-form-urlencoded; charset=UTF-8';//请求配置头 axios.defaults.baseURL = 'http://zh.hbneibao.com/admin' //配置接口地址 //POST传参序列化(添加请求拦截器) axios.interceptors.request.use((config) => { //在发送请求之前做某事 // if (store.state.token) { // 判断是否存在token,如果存在的话,则每个http header都加上token // config.headers.Authorization = `token ${store.state.token}`; // } if(config.method === 'post') { config.data = qs.stringify(config.data); } return config; },(error) =>{ alert('request-错误的传参'); return Promise.reject(error); }) //返回状态判断(添加响应拦截器) axios.interceptors.response.use((res) =>{ console.log(res); //对响应数据做些事 if(res.data.status != 200) { return Promise.reject(res); } return res; },(error) =>{ alert('response-错误的传参'); // if (error.response) { // switch (error.response.status) { // case 401: // // 返回 401 清除token信息并跳转到登录页面 // store.commit(types.LOGOUT); // router.replace({ // path: 'login', // query: {redirect: router.currentRoute.fullPath} // }) // } // } return Promise.reject(error); }) //返回一个Promise(发送post请求) export function fetchPost(url,params) { return new Promise((resolve,reject) => { axios.post(url,params) .then(response => { resolve(response.data); }) .catch((error) => { reject(error); }) }) } ////返回一个Promise(发送get请求) export function fetchGet(url, param) { return new Promise((resolve, reject) => { axios.get(url, {params: param}) .then(response => { resolve(response.data) }) .catch((error) => { reject(error) }) }) } 新建一个api.js,管理api接口import {fetchGet,fetchPost} from './http' //授权接口 export default{ Souquan } function Souquan(params) { return fetchPost('upxianshi/login',params); } 使用import Api from '@/api/api' Api.Souquan({ ... }).then(res=>{ console.log(res); });]]></content>
<categories>
<category>vue</category>
</categories>
<tags>
<tag>vue</tag>
<tag>axios</tag>
</tags>
</entry>
<entry>
<title><![CDATA[svg图片字体制作]]></title>
<url>%2Fliuyang996.github.io%2F2018%2F04%2F22%2Fsvg1%2F</url>
<content type="text"><![CDATA[在项目中我们可以会用到svg的图标,我这里使用的###icomoon.io 这个网站,网站里有许多可用图标,也可以使用本地的svg图标,选择好后点击页面下方的Generate Font 进入设置页面,可以对选择好的图标进行一个设置,设置fontName名称、class名称等。确认好后点击下方的Download即可下载 下载好后,把压缩包下的fonts里的文件和style.css移到项目下即可使用。]]></content>
<tags>
<tag>svg图标字体</tag>
</tags>
</entry>
<entry>
<title><![CDATA[搞定项目图标iconfont]]></title>
<url>%2Fliuyang996.github.io%2F2018%2F04%2F20%2Ficonfont%2F</url>
<content type="text"><![CDATA[在开发中经常会遇到小图标的使用问题,小图标的使用可以让程序更美观和增加可用性。这里我使用IconFont,这是阿里巴巴的矢量图标库。Iconfont中有很多图标,我们可以像在超市逛街一样,挑选自己喜欢的商品,然后放入购物车。 挑选图标的过程(共6步) 1.进入网站:Iconfont网址:http://www.iconfont.cn2.点击网站上方的“官方图标库”,选择自己喜欢的图标。3.选择好自己喜欢的图标,你可以有两个选择,下载代码 和 添加至项目。4.我这里选择添加至项目,然后新建项目,并输入名称。5.项目添加好后,会自动给我们转入到我们项目库中。点击查看在线链接,点击生成。(记得先选中Font class) //at.alicdn.com/t/font_636144_fi67t0dxpkkb7qfr.css 完整link <link rel="stylesheet" type="text/css" href="http://at.alicdn.com/t/font_1021785_a49704a49th.css"/> 6.生产css引入的代码,生成后就可以在项目首页index.html引入了。 <i class="iconfont icon-hanbao"></i> 添加更多图标: 1.去Iconfont网站继续挑选,把相中的图标加入购物车中。 2.把购物车中的图标加入到项目中。 3.重新生成在线链接。(这部很重要) 4.在项目主页中(index.html),更换css引入链接。]]></content>
<categories>
<category>icon图标</category>
</categories>
<tags>
<tag>icon</tag>
<tag>图标库</tag>
</tags>
</entry>
<entry>
<title><![CDATA[vuex的简单介绍及使用方法]]></title>
<url>%2Fliuyang996.github.io%2F2018%2F04%2F19%2Fvuex%2F</url>
<content type="text"><![CDATA[vuex是一个专门为vue.js设计的集中式状态管理架构。状态理解为在data中的属性需要共享给其他vue组件使用的部分,就叫做状态。简单的说就是data中需要共用的属性。####例如:我们有几个页面要显示用户名称和用户等级,或者显示用户的地理位置。如果我们不把这些属性设置为状态,那每个页面遇到后,都会到服务器进行查找计算,返回后再显示。 1.引入vuex(1)利用npm包管理工具,进行安装vuex.在控制命令行中输入 npm install vuex --save 需要注意的是这里一定要加上 –save,因为这个包我们在生产环境中是要使用的。 (2)新建一个vuex文件夹(这个不是必须的),并在文件夹下新建store.js文件,文件中引入我们的vue和vuex。 import Vue from 'vue'; import Vuex from 'vuex'; Vue.use(Vuex); 通过这三步的操作,vuex就算引用成功了 用export default封装代码,让外部可以引用 export default new Vuex.Store({ state }) 在.vue文件下使用store.js的代码 (1)引入store.js文件 import store from '@/vuex/store' export default{ data(){ return{ msg:'hello vueX' } }, store } PS:data下面加上store (2)使用store.js的代码 {{$store.state.count}} 2.state访问状态对象(1)通过computed的计算属性直接赋值computed属性可以在输出前,对data中的值进行改变。 computed:{ count(){ return this.$store.state.count; } } 这里需要注意的是return this.$store.state.count这一句,一定要写this,要不你会找不到$store的。这种写法很好理解,但是写起来是比较麻烦的, (2)mapState 辅助函数 首先要用import引入mapState import {mapState} from 'vuex'; 然后还在computed计算属性里写如下代码: computed:mapState({ count:state=>state.count }) 这里我们使用ES6的箭头函数来给count赋值。 当映射的计算属性的名称与 state 的子节点名称相同时,我们也可以给 mapState 传一个字符串数组。 computed:mapState(['count']) (3)对象展开运算符 computed: { ...mapState({ //... }) } 3.Mutations修改状态$store.commit()Vuex提供了commit方法来修改状态 .vue文件: <button @click="$store.commit('add')">+</button> <button @click="$store.commit('reduce')">-</button> store.js文件: const mutations={ add(state){ state.count++; }, reduce(state){ state.count--; } } 传值:在项目中我们常常要在修改状态时传值,就需要再mutations里再加上一个参数,并在commit的时候传递就可以了。 store.js文件: const mutations={ add(state,n){ state.count+=n; }, reduce(state){ state.count--; } } .vue文件: <button @click="$store.commit('add',10)">+</button> <button @click="$store.commit('reduce')">-</button> 模板获取mutations方法在实际开发中我们也不喜欢看到$store.commit()这样的方法出现,我们希望和调用模板里的方法以一样。 例如:@click=”reduce” 就和没饮用vuex插件一样。使用这种写法:(1).在模板count.vue里用import引入我们的mapMutations. import { mapState,mapMutations } from 'vuex'; (2).在模板的<’script’>标签里添加methods属性,并加入mapMutations methods:mapMutations([ 'add','reduce' ]), 修改后使用方法: <button @click="add(10)">+</button> <button @click="reduce">-</button> 4.getters计算过滤操作getters从表面是获得的意思,可以把他看作在获取数据之前进行的一种再编辑,相当于对数据的一个过滤和加工。可以看作store.js的计算属性。 首先要在store.js里用const声明getters属性 const getters:{ count:function(state){ return state.count +=100; } } 通过属性访问store.getters.count // count+100; mapGetters简化模板写法:首先用import引入我们的mapGetters import { mapState,mapMutations,mapGetters } from 'vuex'; 在computed属性中加入mapGetters ...mapGetters(["count"]) 5.actions异步修改状态actions和Mutations功能基本一样,不同的是,actions是异步的改变state状态,而Mutations是同步改变状态。 在store.js中声明actions,actions是可以调用Mutations里的方法的, const actions ={ addAction(context){ context.commit('add',10) }, reduceAction({commit}){ commit('reduce') } } context: 上下文对象,这里可以理解称store本身。{commit}:直接把commit对象传递过来,可以让方法体逻辑和代码更清晰明了。 模板中的使用,mapActions 和上面的模板方法一样。]]></content>
<categories>
<category>vue</category>
</categories>
<tags>
<tag>vue</tag>
<tag>vuex</tag>
</tags>
</entry>
<entry>
<title><![CDATA[百度离线地图]]></title>
<url>%2Fliuyang996.github.io%2F2018%2F04%2F14%2Flixianditu1%2F</url>
<content type="text"><![CDATA[百度离线地图百度离线文件及详细使用说明已放在github上,可以下载使用 ‘https://github.com/liuyang996/lianxiCity’ 关于地图瓦片我使用的是太乐地图下载器。网上有资源可以自行下载。瓦片放的路径在图片已说明。]]></content>
<categories>
<category>百度离线地图</category>
</categories>
<tags>
<tag>百度离线地图</tag>
</tags>
</entry>
<entry>
<title><![CDATA[javascript- 浅拷贝与深拷贝]]></title>
<url>%2Fliuyang996.github.io%2F2018%2F04%2F12%2Fjs1%2F</url>
<content type="text"><![CDATA[浅拷贝与深拷贝 对象 浅拷贝:只复制指向某个对象的指针,而不复制对象本身,新旧对象共享一块内存;深拷贝:复制并创建一个一摸一样的对象,不共享内存,修改新对象,旧对象保持不变。 浅拷贝可以直接用原对象赋值给新对象 深拷贝的实现 1. object.assign()let foo = { a: 1, b: 2, c: { d: 1, } } let bar = {}; Object.assign(bar, foo) 只能对非嵌套对象进行深拷贝。如果对象中出现嵌套情况。那么嵌套对象的值就变为浅拷贝 2. 转成JSON (不仅可拷贝数组还能拷贝对象)var obj1 = { body: { a: 10 } }; var obj2 = JSON.parse(JSON.stringify(obj1)); 缺点是会破坏原型链,并且无法拷贝属性值为function的属性。 浅拷贝与深拷贝 数组 浅拷贝与对象类似 深拷贝的实现。 如果是普通的数组,则可以用 concat、slice方式返回一个新数组 var arr = ['1','2','3']; var arr2 = arr.slice(); arr2[1] = 'aaa'; console.log(arr); // ['1','2','3']; console.log(arr2); // ['1','aaa','3'];]]></content>
<categories>
<category>javascript</category>
</categories>
<tags>
<tag>javascript</tag>
</tags>
</entry>
<entry>
<title><![CDATA[快应用简单介绍及遇见问题总结]]></title>
<url>%2Fliuyang996.github.io%2F2018%2F04%2F11%2Fkuaiyingyong%2F</url>
<content type="text"><![CDATA[随着3月20号北京开发的快应用(quickapp)的发布,各大手机应用厂商加入了快应用这个行列,该应用模块以标准js语法+重组css标签+Flexbox布局+mvvm模式。类似于微信小程序的依附在微信中,而快应用依附在各大应用市场,可搜索直接打开,无需安装的便捷操作方式。 环境搭建(window平台)1.安装nodejs2.安装hap-toolkit(打开cmd->npm install -g hap-toolkit)3.安装完成输入命令(hap -V) 正确输出版本信息说明安装成功。例如(0.0.26) 所推荐使用的IDE推荐的ide为vscode+hap extension插件开发 初始化项目1.执行以下命令初始化项目 hap init (你的项目名称) 命令生成后,该目录的结构如下 ├── node_modules ├── sign rpk包签名模块 │ └── debug 调试环境 │ ├── certificate.pem 证书文件 │ └── private.pem 私钥文件 ├── src │ ├── Common 公用的资源文件和组件文件 │ │ └── logo.png manifest.json中配置的icon │ ├── Demo 页面目录 │ | └── index.ux 页面文件,文件名不必与父文件夹相同 │ ├── app.ux APP文件(用于包括公用资源) │ └── manifest.json 项目配置文件(如:应用描述、接口申明、页面路由等) └── package.json 定义项目需要的各种模块及配置信息,npm install根据这个配置文件,自动下载所需的运行和开发环境 编译项目先安装依赖,在项目根目录执行以下命令 npm install 待安装完成,使用以下命令编译打包生成rpk包 npm run build PS:(出现报错的话先执行一下 hap update –force,再build) hap update --force 编译打包成功后,项目根目录下会生成文件夹:build、dist 1.build:临时产出,包含编译后的页面js,图片等2.dist:最终产出,包含rpk文件。其实是将build目录下的资源打包压缩为一个文件,后缀名为rpk,这个rpk文件就是项目编译后的最终产出 使用以下命令可自动重新编译 npm run watch 开始开发开demo代码的时候,以为是跟vue差不多,但是在开发过程中发现,其实他并不是真正的html+css、很多html、css代码都不支持,视乎它只是模拟而已,因为会把它转为原生组件,暂时就没能全部支持,所以开发过程还是挺难受的,动不动就报错没有这个属性没有那个属性。 坑1:有很多样式是快应用是没有的。如果写上去没有生效,就编译下,cmd会有提示的。坑2:在设置图片路径的时候,怎么设都无效,设置自带的logo有效,尝试n久之后,原来要编译一下才能看到,因为以为开了watch就不需要编译了。坑3:在用标签写入内容的时候,在div里直接写文字不会渲染,要加个标签1.修改manifest.json配置信息{ "package": "cn.codebear.wanandroid", //应用包名 "name": "wanandroid", //应用名称 "versionName": "1.0.0", //版本名称 "versionCode": "1", //版本号 "minPlatformVersion": "101", //支持的最小平台版本号 "icon": "/Common/Image/logo.png", //应用logo "features": [ //接口列表 { "name": "system.prompt" }, { "name": "system.router" }, { "name": "system.shortcut" }, { "name": "system.fetch" }, { "name": "system.webview" }, { "name": "system.storage" } ], "permissions": [ { "origin": "*" } ], "config": { //系统配置信息 "logLevel": "debug" }, "router": { //路由信息 "entry": "Wanandroid", "pages": { "Wanandroid": { "component": "index" }, "Webview": { "component": "index" } } }, "display": { //UI显示相关配置 "titleBar": true, "titleBarBackgroundColor": "#24b9ff", "titleBarTextColor": "#ffffff", "titleBarText": "首页", "pages": { } } } 具体如何配置,官方文档写的挺详细。]]></content>
<categories>
<category>快应用</category>
</categories>
<tags>
<tag>快应用</tag>
<tag>quickapp</tag>
</tags>
</entry>
<entry>
<title><![CDATA[vue仿饿了么app项目]]></title>
<url>%2Fliuyang996.github.io%2F2018%2F03%2F24%2FvueSell%2F</url>
<content type="text"><![CDATA[记录vue饿了么app项目过程的一些参考点1.图标字图制作 icomoon.io 字图图标网站,可以在该网站使用svg图片做字体图标 2.项目目录 主要设置src文件下的目录, 1.src下新建一个common文件夹,这个文件夹是用来充当公用文件夹,里面新建fonts文件夹、js文件夹、stylus文件夹。 3.mock数据(模拟后台数据) 在项目build文件夹下的,webpack.dev.conf.js(以前是dev-server.js) 1.在const portfinder = require(‘portfinder’)后添加 //添加mock数据 const express = require('express') const app = express() var appData = require('../data.json'); var seller = appData.seller; var goods = appData.goods; var ratings = appData.ratings; var apiRoutes = express.Router(); app.use('/api',apiRoutes) 2.//然后找到devServer,在里面添加 before(app){ app.get('/api/seller',(req,res)=>{ res.json({ errno:0, data:seller }) }); app.get('/api/goods',(req,res)=>{ res.json({ errno:0, data:goods }) }); app.get('/api/ratings',(req,res)=>{ res.json({ errno:0, data:ratings }) }) } 3、然后npm run dev,一定要重启 一下就可以http:/localhost:8080/api/seller 访问了 4.截图 vue-loader依赖postcss搞定css兼容问题,所以不用再写css兼容样式 4.开发webapp用手机查看效果小技巧当我们在PC端上开发webapp时,有时候想用手机查看效果时,可以用这个办法实现。 1.先查看电脑的ip地址,命令行 ipconfig,查到后在地址栏把localhost换成你的IP地址,如果是vue的话,检查下,build-config-index.js文件,找打module.exports里的host,把localhost改为自己的IP地址。 2.使用草料二维码,把网址生成成一个二维码,用微信扫一下即可查看效果。 PS:保证电脑和手机在一个网段。 5.父组件向子组件通信父组件:<v-header :seller='seller'></v-header> data(){ return{ seller:{}, } }, 组件 “:seller” 为传递名称 ‘=’后的seller为传递值 子组件子组件通过props来接收数据: 方式1: props:['seller'] 方式2: props: { seller: Object } 方式3: props: { seller: { type: Object, default:{} } } 写的函数在vue作用域中可以相互调用 访问DOM方法 html: <div ref='wrapper'></div> js: this.$refs.wrapper 6 keep-alive是Vue的内置组件,能在组件切换过程中将状态保留在内存中,防止重复渲染DOM。 商品页总结1 背景模糊 <div class="background"> <img :src="seller.avatar" alt="" style="width:100%;height:100%;"> </div> .background{ position: absolute; left: 0; top: 0; width: 100%; height: 100%; filter: blur(10px); z-index: -1; } 参考点:用头像图片模糊来充当背景。2 Sticky footer布局<div class="wrapper clearfix"> <div class="content"> // 这里是页面内容 </div> </div> <div class="footer"> // 这里是footer的内容 </div> .wrapper { min-height: 100%; } .wrapper .content{ padding-bottom: 50px; /* footer区块的高度 */ } .footer { position: relative; margin-top: -50px; /* 使footer区块正好处于content的padding-bottom位置 */ height: 50px; clear: both; } .clearfix::after { display: block; content: "."; height: 0; clear: both; visibility: hidden; } 商品详情页总结1 商品详情页跳转方式商品详情页跳转方式不是用路由的方式跳转页面,而是直接在商品列表页引入组件,通过点击商品,来显示隐藏的组件。 参考点:1.给商品详情页加上过度动画模拟跳转页面。 2.使用ref $refs调用子组件的方法。 2 商品页头图设置<div class="image-header"> <img :src="food.image" /> </div> .image-header{ position: relative; width: 100%; height: 0; padding-top: 100%; img { position: absolute; left:0; top:0; width:100%; height: 100%; } } 参考点: 头图宽高相等而不固定,采用方式 img外层div的height设置为0,使用padding-top:100%, 当padding-top、bottom值为100%时,div高度会变为和设置的宽度一样。 3 加入购物车Vue.set(this.food,'count',1); 参考点:在给数组赋新值时,使用Vue.set修改数据,否则只会改变数据,不会更新视图。 4 split组件参考点:当遇见相同DOM结构时,也可使其做为组件,好处是统一样式。 5 select标签组件 ratingselectratings: { type:Array, default() { return []; } }, 参考点:1.根据组件关联数据,传入相关值:当前选中标签类型、商品评价数据、是否看有内容状态、评价标签名称。 2.根据评价状态字段,使用计算属性,取得每个标签的数量。filter遍历。 3.props获取父组件传过来的值不可直接修改,可以赋值给新的变量。(props里定义接收父组件数据的变量最好指定类型和默认值) 4.在子组件里改变的值用$emit触发,父组件可以通过$on事件来监听 5.非父子组件通信,需要一个新的vue实例充当一个桥梁。 评论页总结1 评价布局在iphone5下错位@media only screen and (max-width:320px) { flex: 0 0 120px; width: 120px; } 参考点:适当情况下可用媒体查询来解决样式问题]]></content>
<categories>
<category>vue</category>
</categories>
<tags>
<tag>vue饿了么app</tag>
</tags>
</entry>
<entry>
<title><![CDATA[微信小程序-短信倒计时效果]]></title>
<url>%2Fliuyang996.github.io%2F2018%2F03%2F20%2Fxiaochengxu2%2F</url>
<content type="text"><![CDATA[在项目中,经常会有注册功能,那么就会用到短信验证码,为了防止用户重复请求,造成的资源浪费,就可以使用短信倒计时的效果。 .wxml <view class='list'> <view class="list-tit">手机号</view> <view class="list-input"> <input type="digit" class="input" bindinput="tels" name="tel" value="{{ptel}}" ></input> </view> </view> <view class='list'> <view class="list-tit list-tit2">验证码</view> <view class="list-input list-input2"> <input type="digit" class="input" name="yzm" value="{{pyzm}}" ></input> </view> <view class='btn-yzm {{sendmsg}}' bindtap="sendmessg">{{getmsg}}</view> .js 初始化 data: { ptel:'', sendmsg: "sendmsg", getmsg: "获取短信验证码", pyzm:'', timer:1 }, 获取短信验证码 sendmessg: function (e) { var that = this console.log(e.detail.value) if (this.data.timer == 1) { if (this.data.ptel == "") { wx.showModal({ title: '提示', content: '请输入手机号' }) } else { console.log(that.data.ptel) //倒计时 var time = 60 that.setData({ sendmsg: "sendmsgafter", timer: 0 }) var inter = setInterval(function () { that.setData({ getmsg: time + "s后重新发送", }) time-- if (time < 0) { that.setData({ timer: 1, }) clearInterval(inter) that.setData({ sendmsg: "sendmsg", getmsg: "获取短信验证码", }) } }, 1000) wx.showToast({ title: "获取验证码成功" }) } } }, 思路:将点击后样式和内容设为变量,点击之后setData将其改变即可实现过程:函数执行先判断timer的值,这个值是用来让定时器不重复执行。默认为1表示可以执行。当为1时,进入执行流程,先判断输入框是否有内容,如果有,则设置倒计时的时间,然后改变timer的值,我这里设置为0,sendmsg字段用来动态改变文字样式。然后设置定时器,每秒动态改变getmsg的值,当time小于0时,停止停止器,修改timer的值为1。input输入框事件 tels: function (e) { // console.log(e.detail.value); this.setData({ ptel: e.detail.value }) }, 实时获取内容,并赋值给ptel字段]]></content>
<categories>
<category>微信小程序</category>
</categories>
<tags>
<tag>微信小程序</tag>
</tags>
</entry>
<entry>
<title><![CDATA[ES6-新增的数组知识]]></title>
<url>%2Fliuyang996.github.io%2F2018%2F03%2F16%2Fes6-5%2F</url>
<content type="text"><![CDATA[JSON数组格式转换Array.from(json) 数组的遍历这种形式比ES5的for循环要简单而且高效。 let arr=['html','css','js'] for(let item of arr){ console.log(item); } for…of数组索引:for (let index of arr.keys()){ console.log(index); } 同时输出数组的内容和索引:用entries()这个实例方法,配合我们的for…of循环就可以同时输出内容和索引了。 for (let [index,val] of arr.entries()){ console.log(index+':'+val); }]]></content>
<categories>
<category>ES6</category>
</categories>
<tags>
<tag>ES6</tag>
</tags>
</entry>
<entry>
<title><![CDATA[ES6-数字操作]]></title>
<url>%2Fliuyang996.github.io%2F2018%2F03%2F16%2Fes6-4%2F</url>
<content type="text"><![CDATA[数字判断和转换数字验证Number.isFinite( xx ),只要是数字,不论是浮点型还是整形都会返回true,其他时候会返回false。 let a= 11/4; console.log(Number.isFinite(a));//true console.log(Number.isFinite('xxx'));//false NaN验证 Number.isNaN()console.log(Number.isNaN(NaN)); //true 判断是否为整数Number.isInteger(xx)let a=123.1; console.log(Number.isInteger(a)); //false]]></content>
<categories>
<category>ES6</category>
</categories>
<tags>
<tag>ES6</tag>
</tags>
</entry>
<entry>
<title><![CDATA[ES6-字符串模板]]></title>
<url>%2Fliuyang996.github.io%2F2018%2F03%2F16%2Fes6-3%2F</url>
<content type="text"><![CDATA[字符串模板使用字符串模板可以比较方便的让我们拼接字符串 let york = '穿过繁华'; let blog = `这是我的博客,博客名字叫${york}`; 在拼接的时候,使用不是单引号或双引号,而是反引号(在tab键上面)变量用 ${} 符号来引入。 对运算的支持let a =1; let b =2; let add = `${a+b}`; 字符串查找(支持中文查找)查找是否存在:.includes() 返回布尔值let blog = '博客'; let jies = 'Hello 大家好,这是我的博客,欢迎大家瞧一瞧'; console.log(jies.includes(blog)); 判断开头是否存在 .startsWith() 返回布尔值console.log(jies.startsWith(blog)); 判断结尾是否存在 .endsWith() 返回布尔值console.log(jies.endsWith(blog)); 复制字符串 .repeat()document.write('blog'.repeat(3));]]></content>
<categories>
<category>ES6</category>
</categories>
<tags>
<tag>ES6</tag>
</tags>
</entry>
<entry>
<title><![CDATA[ES6-对象扩展运算符]]></title>
<url>%2Fliuyang996.github.io%2F2018%2F03%2F15%2Fes6-2%2F</url>
<content type="text"><![CDATA[对象扩展运算符(…)当编写一个方法时,我们允许它传入的参数是不确定的。这时候我们可以使用对象扩展运算符来做参数。 fuction ly(...arg){ console.log(arg[0]); console.log(arg[1]); console.log(arg[2]); console.log(arg[3]); } ly(1,2,3) 这时我们看到控制台输出了1,2,3,undefined,说明时可以传入多个值,并且就算方法引入多了也不会报错。 扩展运算符的用处我们声明两个数组arr1和arr2,然后我们把arr1赋值给arr2,然后在改变arr2的值,这时arr1的值也改变了,因为我们这是对内存堆栈的引用,而不是真正的赋值。 利用对象扩展运算符解决这个问题。 let arr1 = ['css3','html','js']; //let arr2 = arr1; let arr2 = [...arr1]; console.log(arr2); //['css3','html','js'] arr2.push('ES6'); console.log(arr2);//['css3','html','js','ES6'] console.log(arr1);//['css3','html','js']]]></content>
<categories>
<category>ES6</category>
</categories>
<tags>
<tag>ES6</tag>
</tags>
</entry>
<entry>
<title><![CDATA[ES6-变量的解构赋值]]></title>
<url>%2Fliuyang996.github.io%2F2018%2F03%2F15%2Fes6-1%2F</url>
<content type="text"><![CDATA[解构赋值ES6允许按照一定模式,从数组和对象那个中提取值,对变量进行赋值,这被称为解构。解构赋值在实际开发中可以大量减少我们的代码了,并且让我们的程序解构更清晰。 let [a,b,c]=[1,2,3]; 上面的代码表示,可以从数组中提取值,按照位置的对象关系对变量赋值。 解构的默认值解构赋值是允许使用默认值的 let [a,b='liuyang'] = ['web'] console.log(a+b); // 'webliuyang' 需要注意下undefined和null的区别,undefined相当于什么都没有,null有值,但为空。 对象的解构赋值let {foot,bar} = { foo:'liuyang',bar:'gggg'}; console.log(a+b); // 'liuyanggggg' 注意:对象的解构与数组有一个重要的不同。数组的元素是按次序排列的,变量的取值由它的位置决定;而对象的属性没有次序,变量必须与属性同名,才能取到正确的值。 字符串解构const [a,b,c,d,e,f]="liuyang";]]></content>
<categories>
<category>ES6</category>
</categories>
<tags>
<tag>ES6</tag>
</tags>
</entry>
<entry>
<title><![CDATA[微信小程序开发中遇到的问题及经常使用的代码]]></title>
<url>%2Fliuyang996.github.io%2F2018%2F03%2F02%2Fxiaochengxu1%2F</url>
<content type="text"><![CDATA[开发已上线小程序(在微信小程序可搜索以下名称)1.在线巡更2.在线培训学习3.智慧旅店 开发注意事项 1.在使用接口的时候必须使用https协议。2.openid返回40029。出现这个问题,可以是前后端的密钥不匹配,或者使用的是个人的appid3.在发布的时候,appid需要替换成正式appid,这时候记得要在正式开发账号(正式appid的账号),添加你为开发者,不然是无法创建项目的。4.在上线的时候,正式账号上,记得要配置域名,不然就无法调用接口。 开发问题1.在小程序中使用map地图的时候在页面中定义view等标签,在模拟器中可以显示,但是真机上是不显示的,因为,在真机上map的z-index层次是最高的,会覆盖其他的标签。 解决办法:使用map标签的controls属性,来设置地图上的按钮等元素。 设置controls后截图 1<map longitude="{{longitude}}" latitude="{{latitude}}" markers="{{markers}}" controls="{{controls}}" scale="20" polyline="{{polyline}}" circles="{{circles}}" bindcontroltap="controltap"></map> 说明:longitude属性表示中心经度;latitude属性表示中心纬度;markers属性表示地图的标注点;controls属性就是设置控件的如按钮等,格式为数组对象;scale表示缩放级别;polyline表示路线;circles表示以自己位置为中点的圆;bindcontroltap=”controltap”事件作用是对controls属性里的控件做回调事件可以通过对controls里的id值来判断对某个按钮做操作。 我们在初始化了map标签里的属性之后,在后面可能会修改他的值,我这里修改的方式是先修改需要改变的属性里的值,然后在用setData重新赋值,例如 that.data.controls[1].iconPath = "/images/xunluoJ.png"; this.setData({ controls: that.data.controls }) 2.获取用户坐标 wx.getLocation({ //type: 'wgs84', type: 'gcj02', //altitude:false, success: function (res) { that.globalData.latitude = res.latitude that.globalData.longitude = res.longitude //var speed = res.speed //var accuracy = res.accuracy } }) 参数说明 altitude 表示是否启用高精度定位,启用的话定位较准,但是会减慢接口返回速度 3.判断两个坐标之间的距离 var EARTH_RADIUS = 6378.137; //地球半径 function rad(d) { return d * Math.PI / 180.0; } function getDistance(lng1, lat1, lng2, lat2) { var radLat1 = rad(lat1); var radLat2 = rad(lat2); var a = radLat1 - radLat2; var b = rad(lng1) - rad(lng2); var s = 2 * Math.asin(Math.sqrt(Math.pow(Math.sin(a / 2), 2) + Math.cos(radLat1) * Math.cos(radLat2) * Math.pow(Math.sin(b / 2), 2))); s = s * EARTH_RADIUS; s = Math.round(s * 10000) / 10000; return s;//返回数值单位:公里 } 4.使用wx.setStorageSync保存全局变量值 wx.setStorageSync('我是给保存的变量取个名字', 我是要保存的变量) 5.使用wx.setStorageSync获取全局变量值 wx.getStorageSync('我是保存变量的名字'), 6.页面下拉刷新 设置页面的下拉刷新首先需要再app.json文件下的window对象里设置 "window":{ "enablePullDownRefresh":true } 然后在需要下拉刷新的页面中的.js文件下的 onPullDownRefresh 函数中写下拉操作 //下拉刷新 onPullDownRefresh:function() { wx.showNavigationBarLoading() //在标题栏中显示加载 //模拟加载 setTimeout(function() { // complete wx.hideNavigationBarLoading() //完成停止加载 wx.stopPullDownRefresh() //停止下拉刷新 },1500); }, 7.设置单个页面标题 在需要设置页面标题的.js文件中 wx.setNavigationBarTitle({ title: '标题', }) 8.请求接口 function sendRequest(path, data, callback) { wx.request({ url: path, data: data, header: { 'content-type': 'application/json' }, method: "POST", success: callback, fail:(res)=>{ console.log(res) } }) } 9.跳转页面常用方式 wx.navigateTo({ //保留当前页面 url: '' }) wx.redirectTo({ //关闭当前页面 url: '' }) wx.switchTab({ //跳转tabBar页面 url: '../b/b' }); PS:有些很基本的代码块放在这里是为了开发的时候直接Ctrl+C、V加快速度 (#^.^#)]]></content>
<categories>
<category>微信小程序</category>
</categories>
<tags>
<tag>微信小程序</tag>
</tags>
</entry>
<entry>
<title><![CDATA[ionic 常用命令]]></title>
<url>%2Fliuyang996.github.io%2F2018%2F03%2F02%2Fionic1%2F</url>
<content type="text"><![CDATA[环境搭建需要安装以下软件和插件 1.安装nodeJS(自带npm),建议安装版本不要太高。 2.配置cnpm(使用淘宝镜像取代npm) 配置npm国内镜像: 因为国内的网络环境原因,在用npm下载安装各种包的时候经常会遇到无法正常下载的情况。所以我们需要将npm指向淘宝镜像 。cmd中分步输入以下内容: (1)、注册模块镜像:npm set registry https://registry.npm.taobao.org/ (2)、编译依赖的node的源码镜像:npm set distury https://npm.taobao.org/dist (3)、清空缓存:npm cache clean 最后查看一下npm配置列表是否已经指向淘宝镜像:npm config list 安装JAVA JDK 安装Android SDK(在项目打包安卓app的时候会用到,前期在浏览器环境测试开发暂时用不到) ionic常用代码1.跳转页面 注入NavController //NavController就是用来管理和导航页面的一个controlle import { NavController } from 'ionic-angular'; constructor(public navCtrl: NavController) { } //通过代码的方式跳转 pushMorePage(){ console.log("代码方式跳转"); //跳转到指定页面 this.navCtrl.push(MorePage,{'参数名':'我是参数'}); } } 另一个页面获取参数 用NavParams来接收数据。 import { NavParams } from 'ionic-angular'; constructor(public params: NavParams) { //获取传递过来的参数 this.title=this.params.get('参数名'); } ionic npm/cordova相关命令 新建页面 ionic g page login 2.打包命令(run是使用数据线连接,直接安装到手机上,build是下载到目录里) ionic cordova build android --prod ionic cordova build android --prop ionic cordova build android --aot 3.查看插件安装情况 ionic cordova plugin list ionic cordova plugin --help 4.安装adnroid平台 cordova platform add android 5.安装/删除插件 ionic cordova plugin remove 插件名 //先根据上面的list列出插件,然后根据插件名卸载 ionic cordova plugin add 插件地址 //这个插件地址可以是github的项目地址,也可以是一个文件夹路径 6.查看项目版本信息 ionic info ionic3 常用指令使用1 点击事件 (click)="myClick()" 2 循环 *ngFor="let of items" 3 hidden隐藏 [hidden]=" " 4 ngif *ngIf="" 5 数据绑定 [(ngModel)]="" 6 ngClass // *ngFor="let items of communityList, let i =index" [ngClass]="{'txt':activeIndex==i}" input焦点事件 (ionBlur)="blurInput()" (ionFocus)="focusInput()" ionFocus为输入框获取焦点的属性 ionBlur为输入框失去焦点的属性 src绑定 [src]=”变量” ionic3 js调用ionic3框架自带组件实例方法1.使用ViewChild定义 @ViewChild('SelectT') select1: Select; 2.在html加入定义的Select1 <ion-select [(ngModel)]="loudongSelect" #SelectT></ion-select> 3.调用组件实例 this.select1.open();]]></content>
<categories>
<category>ionic</category>
</categories>
<tags>
<tag>ionic</tag>
</tags>
</entry>
<entry>
<title><![CDATA[css常用样式]]></title>
<url>%2Fliuyang996.github.io%2F2018%2F02%2F20%2Fcss%2F</url>
<content type="text"><![CDATA[/*公共样式--开始*/ html, body, div, ul, li, h1, h2, h3, h4, h5, h6, p, dl, dt, dd, ol, form, input, textarea, th, td, select { margin: 0; padding: 0; } *{box-sizing: border-box;} html, body { min-height: 100%; } body { font-family: "Microsoft YaHei"; font-size:14px; color:#333; } h1, h2, h3, h4, h5, h6{font-weight:normal;} ul,ol { list-style: none; } img { border: none; vertical-align: middle; } a { text-decoration: none; color: #232323; } table { border-collapse: collapse; table-layout: fixed; } input, textarea { outline: none; border: none; } textarea { resize: none; overflow: auto; } .clearfix { zoom: 1; } .clearfix:after { content: "."; width: 0; height: 0; visibility: hidden; display: block; clear: both; overflow:hidden; } .fl { float: left } .fr { float: right } .tl { text-align: left; } .tc { text-align: center } .tr { text-align: right; } .ellipse { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; } .inline{ display: inline-block; *display: inline; *zoom: 1; } 自定义模态弹窗<div class="dialog-overlay"></div> <div class="dialog-box"> <div class="dialog-content"> </div> <div class="close">x</div> </div> css: /* 弹框样式 */ .dialog-overlay{ width:100%; height:100%; filter:alpha(opacity=50); -moz-opacity:0.5; -khtml-opacity: 0.5; opacity: 0.5; position:absolute; background:#000; top:0; left:0; z-index:999; display:block; } .dialog-box{ /* -webkit-box-shadow: 0px 0px 10px rgba(0, 0, 0, 0.5); -moz-box-shadow: 0px 0px 10px rgba(0, 0, 0, 0.5); -moz-border-radius: 5px; -webkit-border-radius: 5px; */ box-shadow: 0px 0px 10px rgba(0, 0, 0, 0.5); border-radius: 5px; background:#fbf9fe; position:absolute; z-index:1000; display:block; left: 50%; top: 50%; transform: translate(-50%, -50%); } dialog-content{ text-align:left; padding:20rpx; color:#666; font-family:arial; font-size:24rpx; position: relative; } .dialog-box .close{ padding: 0; position: absolute; right: -20rpx; top: -20rpx; z-index: 1099; background-color: #e33100; display: block; width:50rpx; height:50rpx; line-height: 44rpx; border-radius: 50%; color: #fff; text-decoration: none; font-weight: bold; text-align:center; text-shadow: 0 -1px 1px rgba(0,0,0,0.25); border-bottom: 1px solid rgba(0,0,0,0.25); cursor: pointer; } 单行或多行文字实现垂直居中父元素: display:table 子元素: display:table-cell 背景模拟效果html: <div class='wrap'> <div class='background'> <img src="images/ex4.jpg" alt="" style="width: 100%;height: 100%;"> </div> </div> css: .wrap{ position:relative } .background{ position: absolute; left: 0; top: 0; width: 100%; height: 100%; -webkit-filter: blur(10px); /* Chrome, Opera */ -moz-filter: blur(10px); -ms-filter: blur(10px); filter: blur(10px); z-index: -1; }]]></content>
<categories>
<category>css</category>
</categories>
<tags>
<tag>css</tag>
</tags>
</entry>
<entry>
<title><![CDATA[krpano360全景漫游常用代码及使用说明整理]]></title>
<url>%2Fliuyang996.github.io%2F2018%2F02%2F03%2Fkrpano1%2F</url>
<content type="text"><![CDATA[前言在一次项目中,有个需求是希望能够全景展示社区里的面貌和管理,智能化的体现“智慧小区”的概念,最开始在网上找的一个js的插件,发现效果并不好,不好修改源码。然后一直找一直找(#^.^#),找到了这个,krpano全景展示工具,还是比较好用的。 krpano特点(1)兼容HTML5和Flash,支持Webgl下的WebVR展示。(2)使用专用的krpano xml代码编写全景漫游,可开发出高定制化的项目。(3)支持多种类型的全景图已及全景视频和环物全景tip:全景图拍摄、拼接的教程<a href=”http://bbs.720yun.com/forum.php?mod=viewthread&tid=211&extra=page%3D1"target="_blank">720云新手全景摄影入门教程<a href=”https://hao.chinavr.net/index.php/"target="_blank">全景VR资源网站导航 krpano常用设置PS:常用设置一般都是在.xml文件下设置的 1.小行星开场littleplanetintro="true" 2.自动循环浏览<autorotate enabled="true" waittime="2.0" speed="-10.0" horizon="0.0" /> <events name="onautorotateevents" keep="true" onautorotateoneround="nextscene()"/> 3.添加场景<scene></scene> 注:可以使用.bat文件在别处生成一个场景,然后把生成的.xml文件里的scene标签拷过来,还要拷panos文件夹里的文件。 4.添加热点<hotspot name="spot4" style="skin_hotspotstyle" ath="82.688" atv="44.260" linkedscene="scene_otc3" /> 注:ath、atv是热点的坐标,可以通过krpano的图形界面软件点选生成热点。linkedscene是跳转场景,值是跳转场景的title 5.热点添加图片<hotspot name="spot4" url="new_spotd7_gif.png" /> 注:我这里的图片路径和tour.xml文件为同一路径,可根据需要更改 6.热点图片,文字样式。我们可能会需要图片带有一闪一闪的动效,这样会提示用户去点,还有图片的颜色等<!-- 定义热点风格 - 白色热点 --> <style name="hotspot_ani_white" crop="0|0|128|128" framewidth="128" frameheight="128" frame="0" lastframe="19" onloaded="hotspot_animate();add_all_the_time_tooltip();" /> <!-- 热点动画action,每隔0.03秒改变crop的内容,从而实现动画效果, inc是一个每次递增指定数值的方法,这里是让frame这个变量每次增加1, 当到达19时,则从0又开始递增。mul是乘法运算,将高度乘以当前帧序号, 得到crop中y的位置。txtadd对crop的内容进行了设定。因为每一次ypos 的值都会发生变化,所以crop中所显示的内容也发生变化。 最后是0.03秒后再次执行自身。 --> <action name="hotspot_animate"> inc(frame,1,get(lastframe),0); mul(ypos,frame,frameheight); txtadd(crop,'0|',get(ypos),'|',get(framewidth),'|',get(frameheight)); delayedcall(0.03, if(loaded, hotspot_animate() ) ); </action> <!--热点文字提示--> <action name="add_all_the_time_tooltip"> txtadd(tooltipname, 'tooltip_', get(name)); addplugin(get(tooltipname)); txtadd(plugin[get(tooltipname)].parent, 'hotspot[', get(name), ']'); set(plugin[get(tooltipname)].url,'%SWFPATH%/plugins/textfield.swf'); set(plugin[get(tooltipname)].align,top); set(plugin[get(tooltipname)].edge,bottom); set(plugin[get(tooltipname)].x,0); set(plugin[get(tooltipname)].y,0); set(plugin[get(tooltipname)].autowidth,true); set(plugin[get(tooltipname)].autowidth,true); set(plugin[get(tooltipname)].background,true); set(plugin[get(tooltipname)].backgroundcolor,0x000000); set(plugin[get(tooltipname)].roundedge,5); set(plugin[get(tooltipname)].backgroundalpha,0.65); set(plugin[get(tooltipname)].padding,5); set(plugin[get(tooltipname)].border,false); set(plugin[get(tooltipname)].glow,0); set(plugin[get(tooltipname)].glowcolor,0xFFFFFF); set(plugin[get(tooltipname)].css,'text-align:center; color:#FFFFFF; font-family:MicrosoftYahei; font-size:14px;'); if(device.mobile,set(plugin[get(tooltipname)].css,'text-align:center; color:#FFFFFF; font-family:MicrosoftYahei; font-weight:bold; font-size:22px;'); set(plugin[get(tooltipname)].y,0);); set(plugin[get(tooltipname)].textshadow,0); set(plugin[get(tooltipname)].textshadowrange,6.0); set(plugin[get(tooltipname)].textshadowangle,90); copy(plugin[get(tooltipname)].html,hotspot[get(name)].tooltip); <!--设置hotspot命名为tooltip标签--> set(plugin[get(tooltipname)].enabled,false); </action> <!--热点动态模式--> <action name="do_crop_animation_onclick"> if(hotspot[get(name)].animated === null OR hotspot[get(name)].animated == false, set(hotspot[get(name)].animated,true); setinterval(calc('crop_anim_' + name), calc(1.0 / %3), inc(frame); if(frame GE frames, if(onlastframe !== null, onlastframe() ); set(frame,0); ); mod(xpos, frame, xframes); div(ypos, frame, xframes); Math.floor(ypos); mul(xpos, %1); mul(ypos, %2); calc(crop, xpos + '|' + ypos + '|%1|%2'); ); , set(hotspot[get(name)].animated,false); clearinterval(calc('crop_anim_' + name)); set(crop, '0|0|%1|%2'); ); PS:我这里把热点标签hotspot的命名方式改成了tooltip属性,在给hotspot命名时只需要设置它的tooltip属性就可以了。 原始为: <!--设置hotspot命名为scene标签的title属性--> <!--copy(plugin[get(tooltipname)].html,scene[get(linkedscene)].title);--> 上面是对热点设置的一系列属性,直接都拷贝过去用就可以了。 7.热点命名上面已经说了,可以看看6 8.热点添加点击js事件<hotspot onclick="js(Aqu())" /> 注:这里要注意下函数名外面要套一个js(),负责不会生效的。 页面效果截图展示]]></content>
<categories>
<category>krpano</category>
</categories>
<tags>
<tag>krpano</tag>
</tags>
</entry>
<entry>
<title><![CDATA[ECharts常用代码及说明整理]]></title>
<url>%2Fliuyang996.github.io%2F2017%2F11%2F10%2Fecharts1%2F</url>
<content type="text"><![CDATA[在开发可视化分析或者大数据展示的时候,经常会用到echarts图表,有许多经常会用的参数,这里给大家列举一下,以方便在需要的时候直接使用即可。1.引入echarts.js这个网上下一个或者用cdn。2.html加一个放图表的容器<div id="main" style="width:400px;height:400px"></div> 3.找到这个标签var myChart = echarts.init(document.getElementById('main')) 4.放入需要的option数据(一般直接在echarts官网选好了复制即可)5.为echarts对象加载数据myChart.setOption(option); PS:建议3、4、5步用函数封装起来,这样图表多的时候也好找些。 myChart(); function myChart(){ var myChart = echarts.init(document.getElementById('main')) option ={...} myChart.setOption(option); } 图表X轴内容全部显示有时候我们X轴的文字会很长,多个的话就会挤到一起,这时候我们需要这样设置,在xAxis对象里加: axisLabel:{ interval:0, //横轴信息全部显示 rotate:-30, // -30度角倾斜显示 } 图表图例字体颜色,大小, 在legend对象里加:textStyle:{ //图例文字的样式 color:'#fff', fontSize:12 } 图表数据颜色,在series对象里加itemStyle:{ normal:{ color:'#ceee61' } }, 图表字体颜色设置(在xAxis或yAxis里加)axisLabel: { show: true, textStyle: { color: '#fff' } } 调整图表在div中的大小和位置grid:[ { x: '2%', y: '2%', width: '80%', height: '80%' } ], 设置图表背景颜色(和title、tooltip等同级)backgroundColor: ['#02204a'], 设置饼图数据在圈内在series数组里设置,注意,label和data数组统计,不要把label放在itemStyle里面。 label: { normal: { position: 'inner', formatter: '{b} : {c} ({d}%)', textStyle: { color: '#fff', fontWeight: 'bold', fontSize: 14 } } },]]></content>
<categories>
<category>ECharts</category>
</categories>
<tags>
<tag>ECharts</tag>
</tags>
</entry>
<entry>
<title><![CDATA[HTML、CSS中雪碧图的使用]]></title>
<url>%2Fliuyang996.github.io%2F2017%2F06%2F30%2Fcss2%2F</url>
<content type="text"><![CDATA[雪碧图:多个图片集成在一个图片中的图。使用雪碧图可以减少网络请求的次数,加快运行的速度。 需用方法,主要用到background-position属性 推荐一个在线生产雪碧图的网站,只需要上传小图标即可 https://www.toptal.com/developers/css/sprite-generator]]></content>
<categories>
<category>CSS</category>
</categories>
<tags>
<tag>CSS Sprites</tag>
</tags>
</entry>
</search>