hcc226


  • Home

  • Archives

Mobile pages that I have worked on

Posted on 2023-09-01

Douyin’s movie ticket project

This is a preview of the seat selection page




You can click the play button to see the detail.








This is the theater list page




Douyin’s book comment project




You can click the play button to see the detail.







Kesong’s mobile app pages

Personal infomation

Personal information page






User’s follower and following list page



Search

App’s search tab



Search history and search word recommendation



Search auto complete




H5

H5 reflow page






Mobile app’s feedback center



Hello World

Posted on 2019-06-28

Welcome to Hexo! This is your very first post. Check documentation for more info. If you get any problems when using Hexo, you can find the answer in troubleshooting or you can ask me on GitHub.

Quick Start

Create a new post

1
$ hexo new "My New Post"

More info: Writing

Run server

1
$ hexo server

More info: Server

Generate static files

1
$ hexo generate

More info: Generating

Deploy to remote sites

1
$ hexo deploy

More info: Deployment

Object.defineProperty及seal freeze相关函数总结

Posted on 2018-11-01

Object.defineProperty用法

语法

Object.defineProperty(obj, prop, descriptor)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
//对象已有的属性添加特性描述
Object.defineProperty(obj,"test",{
get:function (){} | undefined,
set:function (value){} | undefined,
configurable:true | false,
enumerable:true | false,
value:任意类型的值,
writable:true | false
});
//对象新添加的属性的特性描述
Object.defineProperty(obj,"newKey",{
get:function (){} | undefined,
set:function (value){} | undefined,
configurable:true | false,
enumerable:true | false,
value:任意类型的值,
writable:true | false
});

参数含义

value:属性对应的值
writable:属性的值是否可以被重写
enumerable:属性是否可以被枚举(for…in 或者Object.keys())
configurable:是否可以删除目标属性或是否可以再次修改属性的特性(writable,configurable,enumerable)
get/set:

1
2
3
4
5
6
7
8
9
10
Object.defineProperty(obj,"newKey",{
get:function (){
//当获取值的时候触发的函数
return initValue;
},
set:function (value){
//当设置值的时候触发的函数,设置的新值通过参数value拿到
initValue = value;
}
});

Object.preventExtensions()

阻止对象扩展,让一个对象永远不能再添加新的属性

1
Object.preventExtensions(obj)

Object.isExtensible()

判断一个对象是否可扩展,返回true/false

Object.seal()

不能添加新的属性
不能删除已有属性
不能修改已有属性的enumerable,configurable,writable,但可以修改已有属性的值

返回被密封后的对象

Object.isSealed()

判断是否被密封

Object.freeze()

在seal的基础上不能修改属性的值

Object.isFrozen()

判断一个对象是否被冻结

vue.js中计算属性computed与methods的区别

Posted on 2018-06-14

先来看两段代码
第一段,使用methods方法来计算返回值
avatar
第二段代码,使用计算属性computed返回值
avatar
二者使用上的区别是使用methods需要调用now()和后者直接使用now
效果上 使用methods每秒页面的时间会进行更新,而后者不会,一直保持初始值,刷新页面后时间才会改变
那么computed与methods究竟有什么区别呢?

computed适用情景

我们先来看看computed的使用情景

对绑定数据进行处理,如果使用在html中使用表达式返回结果的话,当计算过程较为复杂时不能满足需求,基于使用computed,当绑定数据更新时,会调用computed

计算属性还可以依赖多个Vue的数据,其中有一个数据发生变化,计算属性便会重新执行

计算属性是依赖缓存的。当计算属性所依赖的数据发生变化时,它才会重新取值。

Date.now()不是响应式依赖,所以不会更新

而对于methods来说,它不依赖缓存,只要重新渲染,他就会被调用,因此函数也会被执行。

因此,使用计算属性还是methods取决于你是否需要缓存,当遍历大数组和大量计算时,应该使用计算属性。不需要缓存时使用methods

newcoder problems

Posted on 2018-06-12

斐波那契数列

1
2
3
4
5
function fibonacci(n) {
if(n === 2) return 1;
if( n === 1) return 1;
return fibonacci(n-1)+fibonacci(n-2)
}

数组去重

1
2
3
Array.prototype.uniq = function () {
return Array.from(new Set(this));
}

获取url参数

问题描述

获取 url 中的参数

  1. 指定参数名称,返回该参数的值 或者 空字符串
  2. 不指定参数名称,返回全部的参数对象 或者 {}
  3. 如果存在多个同名参数,则返回数组
    如输入http://www.nowcoder.com?key=1&key=2&key=3&test=4#hehe 输出[1,2,3]

我的方法

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
function getUrlParam(sUrl, sKey) {
if(sKey){
var reg = new RegExp("[?&]"+sKey+"=(([^&#])+)","g")
var res = []
sUrl.replace(reg,function (match,s,index,str) {
console.log(match+" "+s+" "+index+" "+str)
res.push(s)
})
if(res.length=0)return "";
return res;
}
else {
var reg = new RegExp("[?&]([^&#]+)=([^&#]+)","g")
var res = {};
sUrl.replace(reg,function (match,s1,s2,index,str) {
console.log(match+" "+s1+" "+s2+" "+index+" "+str)
var t = res[s1]
if(res[s1]){
console.log(res[s1])
if(Array.isArray(res[s1])){
t.push(s2)
res[s1] = t;
}
else {
console.log("aaaaaaaaaaa")
res[s1] = new Array(t,s2)
console.log(res[s1])
}
}
else res[s1] = s2;
})
return res;
}
}

更简洁的方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
function getUrlParam(sUrl,sKey){
    var result = {};
    sUrl.replace(/\??(\w+)=(\w+)&?/g,function(a,k,v){
        if(result[k] !== void 0){
            var t = result[k];
            result[k] = [].concat(t,v);
        }else{
            result[k] = v;
        }
    });
    if(sKey === void 0){
        return result;
    }else{
        return result[sKey] || '';
    }
}

主要区别:
1.先将所有参数投提取出来,再根据sKey区分
2.正则表达式的区别
3.字符串与新字符串合并成数组的方法[].concat(t,v)

颜色字符串转换

问题描述

将 rgb 颜色字符串转换为十六进制的形式,如 rgb(255, 255, 255) 转为 #ffffff

  1. rgb 中每个 , 后面的空格数量不固定
  2. 十六进制表达式使用六位小写字母
  3. 如果输入不符合 rgb 格式,返回原始输入

输入rgb(255, 255,255) 输出#ffffff

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
var res = "#";
var reg = /^rgb\(([0-9]+),\s*([0-9]+),\s*([0-9]+)\)/g;
if(!reg.test(sRGB)) return sRGB;
var f = true;
sRGB.replace(reg,function (match,s1,s2,s3) {
s1 = Number(s1);
s2 = Number(s2);
s3 = Number(s3);
s1 = parseInt(s1);
s2 = parseInt(s2);
s3 = parseInt(s3);
//console.log(`${match} ${s1} ${s2} ${s3}`);
if(s1>255 || s2>255 || s3>255){
console.log("dd")
f = false;
return ;
}
var tmp = [s1,s2,s3].map(function (t) {
t = t.toString(16);
if(t.length==1){
return '0'.concat(t)
}
return t;
})
res += tmp[0]+tmp[1]+tmp[2];
})
if(f) return res;
return sRGB;

将字符串转换为驼峰格式

问题描述

css 中经常有类似 background-image 这种通过 - 连接的字符,通过 javascript 设置样式的时候需要将这种样式转换成 backgroundImage 驼峰格式,请完成此转换功能

  1. 以 - 为分隔符,将第二个起的非空单词首字母转为大写
  2. -webkit-border-image 转换后的结果为 webkitBorderImage
    输入‘font-size’输出’fontSize’
1
2
3
4
5
6
7
8
9
if(sName.indexOf('-') === -1 )return sName;
if(sName[0] =='-') sName = sName.slice(1);
var reg = /-([a-z]+)/g;
/*console.log(sName.match(reg))*/
var res = sName.replace(reg,function (match,s1,s2) {
console.log(`${match} ${s1} ${s2}`)
return s1[0].toUpperCase()+s1.slice(1)
})
return res;

dom节点查找

Posted on 2018-06-11

问题描述

查找两个节点的最近的一个共同父节点,可以包括节点自身

解题思路

jquery contains方法可以判断一个几个节点元素是否包含另一个节点元素
取任意一个节点1,依次往前取父节点,若这个父节点包含另外一个节点2,则此父节点则为满足要求的节点。
注意:节点本身是包含本身的即node1.contains(node1)为true

1
2
3
4
5
6
7
function commonParentNode(oNode1, oNode2) {
for(;oNode1;oNode1 = oNode1.parentNode){
if(oNode1.contains(oNode2)){
return oNode1
}
}
}

Leetcode53 Maximum Subarray

Posted on 2018-06-07

问题描述

给定一个整数数组,找到连续序列和最大的子序列(至少包括一个数字)
Example:
Input: [-2,1,-3,4,-1,2,1,-5,4],
Output: 6
Explanation: [4,-1,2,1] has the largest sum = 6.

解决方案

1
2
3
4
5
6
7
8
9
10
var maxSubArray = function(nums) {
var cur = nums[0];
var sum = nums[0];
for(var i = 1;i<nums.length;i++){
sum = sum + nums[i];
sum = sum>nums[i]?sum:nums[i];
cur = sum>cur?sum:cur;
}
return cur;
};

关键思路之Kadane Algorithm(子序列可以为空)

1
2
3
4
5
6
7
8
9
10
11
//Kadane Algorithm
var maxSubArray = function(nums) {
var cur = 0;
var sum = 0;
for(var i = 0;i<nums.length;i++){
sum = sum + nums[i];
sum = sum>0?sum:0;
cur = sum>cur?sum:cur;
}
return cur;
};

1.遍历数组,在遍历过程中,将遍历到的元素累加,当累加结果小于或等于0时,从下一个元素开始,重新开始累积
2.累加过程中,用一个变量记录cur当前最大值
3.一次遍历后,cur即为最大子片段的和值
注意:题目隐含设定是最大子片段可以为空,空片段的和值是0.
理解此算法的关键:
1.最大子片段中不可能包含求和值为负的前缀。因此当计算出一个负值时,要从当前值重新算起。
2.另一关键是所有出现过的最大值都会被记录

本题关键

1.子序列至少包含一个元素,与Kadane Algorithm不同
2.最大值可能为负,因此sum初始值不为0,sum应与当前元素大小比较,而非0

url匹配及repalce方法

Posted on 2018-06-04

问题描述

获取 url 中的参数

  1. 指定参数名称,返回该参数的值 或者 空字符串
  2. 不指定参数名称,返回全部的参数对象 或者 {}
  3. 如果存在多个同名参数,则返回数组

我的解决方案

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
function getUrlParam(sUrl, sKey) {
if(sKey){
var reg = new RegExp("[?&]"+sKey+"=([^&#])+","g")//[?&]sKey=([^&#]+)/g;
var res = sUrl.match(reg);
console.log(res)
if(!res) return "";
var r = res.map(function (t) {
console.log(t)
return (t.slice(t.indexOf("=")+1))
})
if(r.length===1) return r[0];
else return r;
}
else{
var reg = new RegExp("[?&]([^&#=])+=([^&#])+","g")//[?&]sKey=([^&#]+)/g;
var res = sUrl.match(reg);
var r = {}
res.forEach(function (t) {
console.log(t)
var index = t.indexOf("=");
if(r[t.slice(1,index)]){
var temp = r[t.slice(1,index)];
console.log(temp)
if(Array.isArray(r[t.slice(1,index)])){
r[t.slice(1,index)].push((t.slice(index+1)))
}
else{
var v = [temp,(t.slice(index+1))]
r[t.slice(1,index)] = v;
}
//r[t.slice(1,index)] = temp.split('').push(t.slice(index+1))
}
else
r[t.slice(1,index)] =(t.slice(index+1))
})
return r;
}
}

比较麻烦,讨论区有用到replace方法的,对此方法不太熟悉,因此先总结一下repalce用法

replace()用法

1.两个参数都是字符串,即普通意义上的替换
2.第一个参数是正则,第二个参数为字符串,则替换匹配到的字符串
3.第一个参数是正则,第二个参数是字符串包含捕获组,如$1,则是用捕获组替换匹配到的字符串
4.第一个参数是正则,第二个参数是函数,且第一个参数不包含子表达式

1
2
3
4
5
6
7
8
9
10
11
12
13
var text = 'cat, bat, sat, fat';
// 使用/at/g 匹配字符串中所有的at,并将其替换为ond,
// 函数的参数分别为:当前匹配的字符,当前匹配字符的位置,原始字符串
var result = text.replace(/(at)/g, function(match, pos, originalText) {
console.log(match + ' ' + pos+originalText);
return 'ond'
});
console.log(result);
//at 1cat, bat, sat, fat
//at 6cat, bat, sat, fat
//at 11cat, bat, sat, fat
//at 16cat, bat, sat, fat
//cond, bond, sond, fond

5.第一个参数是正则,第二个参数是函数,且第一个参数包含子表达式

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
var str5 = '这是一段原始文本,需要替换的内容"3=c这要替换4d"!';
var newStr = str5.replace( /([0-9])([a-z])/g,function (arg1,arg2,arg3,arg4,arg5){
// 当正则表达式中存在捕获组时,函数的参数一次为:模式匹配项,第一个捕获组的匹配项,第二个捕获组的匹配项...匹配项在字符串中的位置,原始字符串
console.log( arg1 );
console.log( arg2 );
console.log( arg3 );
console.log( arg4 );
console.log( arg5 );
} );
/*3c
3
c
17
这是一段原始文本,需要替换的内容"3c这要替换4d"!
4d
4
d
23
这是一段原始文本,需要替换的内容"3c这要替换4d"!*/

Promise

Posted on 2018-05-30

定义

MDN定义
1 Promise对象用作异步计算
2 一个Promise代表一个现在、将来或者永不可能可用的值
3 可将异步操作队列化,使其按照期望的额顺序执行,并返回符合预期的结果
4 可在对象直接传递和操作promise,帮助我们处理队列

Why Promise

异步操作常见语法
1 事件侦听与响应 addEventListener
2 回调 如ajax

###
1 回调地狱,调试不方便,不好维护
2 无法使用 try catch错误处理机制 throw return
3 无法正常检索堆栈信息,每一次回调都是在系统层面的调用
4 多个回调函数之前难以建立联系

Promise详解

new Promise(function(resove,reject){
//执行器函数
//一段耗时很长的异步操作
resolve();//数据处理完成
reject();//数据处理出错
//resolve reject会改变promise实例的状态,如果数据处理完成则调用then的第一个函数,出错则会调用then()的第二个响应函数
}).then(function(A){
//成功 下一步
},function(){
//失败
})

Promise三个状态
pending 初始状态
fulfilled 成功
rejected 失败
promise状态发生改变就会触发then promise状态一经改变不会发生改变

注意:如果在then中不直接返回promise实例对象,将会执行下一步操作,即使返回值为false,false将会作为返回值传递到相应的then函数中。

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
console.log("go!")
new Promise(resolve => {
setTimeout(() => {
resolve('hello')
},2000)
})
.then((a) => {
console.log(a);
(function () {
return new Promise(resolve =>{
setTimeout(()=>{
resolve('world')
console.log("merrry")
},2000)
})
}());
return false;
})
.then(a=>{
console.log(a+"yes")
})
//go!
//hello
//falseyes
//merrry 间隔2s

then()

接收两个函数作为参数分别代表 fulfilled rejected
then()可以返回一个新的promise实例,所以可以链式调用
当前面的promise状态改变时,then()根据其最终状,选择响应函数执行。

状态响应函数可以返回新的promise或者其他值
如果返回新的promise 那么下一级.then()会在新的promise状态改变之后执行
如果返回其他任何值,则会立即执行下一级then()

then()里面有then(),则外面的then会等里面的then()全部执行完才执行
then()如果参数不符合规范则会被忽略,执行后面的步骤

错误处理

promise会自动捕获内部异常,并交给reject执行

两种方法:
1 reject(‘error’) .then(null,message=>{})

1
2
3
4
5
6
new Promise((resolve,reject)=>{
reject('errr')
})
.then(null,message=>{
console.log(message)
})

2 throw new Error(‘error’) .catch(message=>{})

catch()也会产生一个promise实例
catch()可以与then()连用
建议在最后都加一个catch操作以便处理错误。

Promise.all()

接收一个数组,返回一个新的promise,数组里可以是promise对象,也可以是别的值,只有promise会等待状态改变
当所有子promise都完成,返回值是全部promise返回值的组成的数组
当有任何一个结果失败,则该promise失败,返回值是第一个失败的子promise的结果

Promise.race()

接收一个数组,当任一个promise完成则状态改变

Promise一旦创建立刻执行

Promise.resolve()

1 参数为空,返回一个状态为fulfilled的promise实例
2 参数是一个跟promise无关的值,则同上,但是fulfilled函数为接收到这个参数
3 若参数为promise实例,则返回该实例,不做任何修改。
4 若参数为thenable则立即执行

Promise.reject

类似Promise.resolve返回一个状态为rejected的promise实例

canvas性能优化

Posted on 2018-05-29

1.将渲染阶段的开销转嫁到计算阶段之上
2.使用多个分层的canvas绘制复杂场景
3.避免频繁设置绘制上下文的font属性 如linewidth等,调整绘制顺序,linewidth一致的放在一起绘制.
因为设置linewidth,font,shadow,text,fillstyle这些属性花费的时间较多
4.不在动画中使用putImageData方法。这种操作导致性能下降
5.通过计算和判断,避免视野之外元素的绘制。
6.离屏绘制。将固定的内容预先绘制在离屏canvas上以提高性能。例如,将待绘制的内容先裁剪好,保存起来。
先将对象绘制在一个未插入页面的canvas中,然后每一帧使用这个canvas绘制。
7.使用worker和拆分任务的方法避免复杂算法阻塞动画运行。避免渲染一帧的时间超过16ms

12

hcc226

make me different

19 posts
4 tags
© 2023 hcc226
Powered by Hexo
|
Theme — NexT.Pisces v5.1.4