遇到的问题和解决方案

今后遇到的问题和解决方案都会在这里更新作为记录

5月1日

1.实现异步的方式

  • 回调函数
  • 事件监听
  • 发布/订阅
  • Promise对象

2.Promise与ES6 generator

promise是为了解决多个回调函数嵌套而提出的。不难想象,如果依次读取多个文件,就会出现多重嵌套。代码不是纵向发展,而是横向发展,很快就会乱成一团,无法管理。这种情况就称为"回调函数噩梦"(callback hell)。它不是新的语法功能,而是一种新的写法,允许将回调函数的横向加载,改成纵向加载。采用Promise,连续读取多个文件,写法如下。

var readFile = require('fs-readfile-promise');
readFile(fileA)
.then(function(data){
  console.log(data.toString());
})
.then(function(){
  return readFile(fileB);
})
.then(function(data){
  console.log(data.toString());
})
.catch(function(err) {
  console.log(err);
});

上面代码中,使用了 fs-readfile-promise 模块,它的作用就是返回一个 Promise 版本的 readFile 函数。Promise 提供 then 方法加载回调函数,catch方法捕捉执行过程中抛出的错误。

 

Generator 函数是协程在 ES6 的实现,最大特点就是可以交出函数的执行权(即暂停执行)。

function* gen(x){
  var y = yield x + 2;
  return y;
}

上面代码就是一个 Generator 函数。它不同于普通函数,是可以暂停执行的,所以函数名之前要加星号,以示区别。

整个 Generator 函数就是一个封装的异步任务,或者说是异步任务的容器。异步操作需要暂停的地方,都用 yield 语句注明。Generator 函数的执行方法如下。

var g = gen(1);
g.next() // { value: 3, done: false }
g.next() // { value: undefined, done: true }

上面代码中,调用 Generator 函数,会返回一个内部指针(即遍历器 )g 。这是 Generator 函数不同于普通函数的另一个地方,即执行它不会返回结果,返回的是指针对象。调用指针 g 的 next 方法,会移动内部指针(即执行异步任务的第一段),指向第一个遇到的 yield 语句,上例是执行到 x + 2 为止。

换言之,next 方法的作用是分阶段执行 Generator 函数。每次调用 next 方法,会返回一个对象,表示当前阶段的信息( value 属性和 done 属性)。value 属性是 yield 语句后面表达式的值,表示当前阶段的值;done 属性是一个布尔值,表示 Generator 函数是否执行完毕,即是否还有下一个阶段。

 


 

5月2日

1.JS异步任务的执行机制

(1)所有同步任务都在主线程上执行,形成一个执行栈(execution context stack)。

(2)主线程之外,还存在一个"任务队列"(task queue)。只要异步任务有了运行结果,就在"任务队列"之中放置一个事件。

(3)一旦"执行栈"中的所有同步任务执行完毕,系统就会读取"任务队列",看看里面有哪些事件。那些对应的异步任务,于是结束等待状态,进入执行栈,开始执行。

(4)主线程不断重复上面的第三步。

2.定时器的执行机制

定时器功能主要由setTimeout()和setInterval()这两个函数来完成,它们的内部运行机制完全一样,区别在于前者指定的代码是一次性执行,后者则为反复执行。以下主要讨论setTimeout()。

setTimeout()接受两个参数,第一个是回调函数,第二个是推迟执行的毫秒数。

console.log(1);
setTimeout(function(){console.log(2);},1000);
console.log(3);

上面代码的执行结果是1,3,2,因为setTimeout()将第二行推迟到1000毫秒之后执行。

如果将setTimeout()的第二个参数设为0,就表示当前代码执行完(执行栈清空)以后,立即执行(0毫秒间隔)指定的回调函数。

setTimeout(function(){console.log(1);}, 0);
console.log(2);

上面代码的执行结果总是2,1,因为只有在执行完第二行以后,系统才会去执行"任务队列"中的回调函数。

总之,setTimeout(fn,0)的含义是,指定某个任务在主线程最早可得的空闲时间执行,也就是说,尽可能早得执行。它在"任务队列"的尾部添加一个事件,因此要等到同步任务和"任务队列"现有的事件都处理完,才会得到执行。

HTML5标准规定了setTimeout()的第二个参数的最小值(最短间隔),不得低于4毫秒,如果低于这个值,就会自动增加。在此之前,老版本的浏览器都将最短间隔设为10毫秒。另外,对于那些DOM的变动(尤其是涉及页面重新渲染的部分),通常不会立即执行,而是每16毫秒执行一次。这时使用requestAnimationFrame()的效果要好于setTimeout()。

需要注意的是,setTimeout()只是将事件插入了"任务队列",必须等到当前代码(执行栈)执行完,主线程才会去执行它指定的回调函数。要是当前代码耗时很长,有可能要等很久,所以并没有办法保证,回调函数一定会在setTimeout()指定的时间执行。

3.替换元素和非替换元素

替换元素是浏览器根据其标签的元素与属性来判断显示具体的内容。img、input、textarea、select、object 等都是替换元素。这些元素都没有实际的内容。替换元素可以增加行框高度,但不增加line-height,内容区高度值 = padding-top + padding-bottom +margin-top + margin-bottom + height。要想替换元素居中,可以设置line-height = height, vertral-align = middle。

大多数元素是不可替换元素,他们将内容直接告诉浏览器,将其显示出来。比如 p的内容、label的内容;浏览器将把这段内容直接显示出来。非替换元素添加padding-top或padding-bottom,不影响行框高度,但内容区高度会变化,margin-top,margin-bottom对行框没有任何影响。

非替换行内元素的行框高由line-height确定,替换行内元素的行框高由height,margin,padding,border决定

4.CSS3的可继承属性和不可继承属性

不可继承的:display、margin、border、padding、background、height、min-height、max-height、width、min-width、max-width、overflow、position、left、right、top、bottom、z-index、float、clear、table-layoutvertical-alignpage-break-after、page-bread-before和unicode-bidi。

所有元素可继承:visibility和cursor。

内联元素可继承:letter-spacingword-spacingwhite-spaceline-height、color、font、font-family、font-size、font-style、font-variant、font-weighttext-decoration、text-transform、direction。

终端块状元素可继承:text-indent和text-align。

列表元素可继承:list-style、list-style-type、list-style-position、list-style-image。

5.margin:0 auto与text-align:center的区别

1.text-align:center 设置文本或img标签等一些内联对象(或与之类似的元素)的居中

2.margin:0 auto 设置块元素(或与之类似的元素)的居中。

 

 


 


5月3日

1.Cookie的格式及组成

Set-Cookie: NAME=VALUE;Expires=DATE;Path=PATH;Domain=DOMAIN_NAME;SECURE

这是每一个Cookie均必须有的部分。NAME是该Cookie的名称,VALUE是该Cookie的值。在字符串“NAME=VALUE”中,不含分号、逗号和空格等字符。
  Expires=DATE:Expires变量是一个只写变量,它确定了Cookie有效终止日期。该属性值DATE必须以特定的格式来书写:星期几,DD-MM-YY HH:MM:SS GMT,GMT表示这是格林尼治时间。反之,不以这样的格式来书写,系统将无法识别。该变量可省,如果缺省时,则Cookie的属性值不会保存在用户的硬盘中,而仅仅保存在内存当中,Cookie文件将随着浏览器的关闭而自动消失。
  Domain=DOMAIN-NAME:Domain该变量是一个只写变量,它确定了哪些Internet域中的Web服务器可读取浏览器所存取的Cookie,即只有来自这个域的页面才可以使用Cookie中的信息。这项设置是可选的,如果缺省时,设置Cookie的属性值为该Web服务器的域名。
  Path=PATH:Path属性定义了Web服务器上哪些路径下的页面可获取服务器设置的Cookie。一般如果用户输入的URL中的路径部分从第一个字符开始包含Path属性所定义的字符串,浏览器就认为通过检查。如果Path属性的值为“/”,则Web服务器上所有的WWW资源均可读取该Cookie。同样该项设置是可选的,如果缺省时,则Path的属性值为Web服务器传给浏览器的资源的路径名。
  可以看出我们借助对Domain和Path两个变量的设置,即可有效地控制Cookie文件被访问的范围。
  Secure:在Cookie中标记该变量,表明只有当浏览器和Web Server之间的通信协议为加密认证协议时,浏览器才向服务器提交相应的Cookie。当前这种协议只有一种,即为HTTPS。

 



 

 


 5月7日

关于npm install

 

npm install express
默认会安装express的最新版本,也可以通过在后面加版本号的方式安装指定版本,如npm install express@3.0.6npm install <name> -g 将包安装到全局环境中

 

但是代码中,直接通过require()的方式是没有办法调用全局安装的包的。全局的安装是供命令行使用的,就好像全局安装了vmarket后,就可以在命令行中直接运行vm命令npm install <name> --save 

安装的同时,将信息写入package.json中项目路径中如果有package.json文件时,直接使用npm install方法就可以根据dependencies配置安装所有的依赖包,这样代码提交到github时,就不用提交node_modules这个文件夹了。

 


5月8日

关于npm、spm、bower 这三个包管理器

npm属于node模块的管理器。而spm和bower是前端模块管理。这两者大的区别有两点:
  1. NPM针对node模块,原生支持commonJS,而前端模块除非该管理器自己定了,否则规范是无法统一的。即便规定了commonJS,那么必定会有配套工具打包来实现实际的运转。
  2. 处理依赖的方式不同。NPM针对的node模块,它的依赖是树状的。项目中用到的A,B,C三个模块,他们可以分别依赖不同版本的lodash,而互不影响。但是前端模块除非做了很好的模块隔离(如实现了commonJS,并能很好地进行打包,即便如此,前端环境的特殊性也无法忍受相同模块的不同版本并存。比如页面中引入两个版本的jQuery,代码数据传输X2),否则一般的依赖都是扁平的。

5月9日

关于onchange事件的触发时机

当焦点离开时才出发onchange事件

 5月11日

document.ready与window.onload区别

在Jquery里面,我们可以看到两种写法:$(function(){}) 和$(document).ready(function(){})这两个方法的效果都是一样的,都是在dom文档树加载完之后执行一个函数(注意,这里面的文档树加载完不代表全部文件加载完)。而window.onload是在dom文档树加载完和所有文件加载完之后执行一个函数。也就是说$(document).ready要比window.onload先执行。

 


5月18日

为什么JS是单线程

JavaScript的单线程,与它的用途有关。作为浏览器脚本语言,JavaScript的主要用途是与用户互动,以及操作DOM。这决定了它只能是单线程,否则会带来很复杂的同步问题。比如,假定JavaScript同时有两个线程,一个线程在某个DOM节点上添加内容,另一个线程删除了这个节点,这时浏览器应该以哪个线程为准?所以,为了避免复杂性,从一诞生,JavaScript就是单线程,这已经成了这门语言的核心特征,将来也不会改变。


5月19日

JQuery中deferred方法的总结

(1) $.Deferred() 生成一个deferred对象。

  (2) deferred.done() 指定操作成功时的回调函数

  (3) deferred.fail() 指定操作失败时的回调函数

  (4) deferred.promise() 没有参数时,返回一个新的deferred对象,该对象的运行状态无法被改变;接受参数时,作用为在参数对象上部署deferred接口。

  (5) deferred.resolve() 手动改变deferred对象的运行状态为"已完成",从而立即触发done()方法。

  (6)deferred.reject() 这个方法与deferred.resolve()正好相反,调用后将deferred对象的运行状态变为"已失败",从而立即触发fail()方法。

  (7) $.when() 为多个操作指定回调函数。

除了这些方法以外,deferred对象还有二个重要方法,上面的教程中没有涉及到。

  (8)deferred.then()

有时为了省事,可以把done()和fail()合在一起写,这就是then()方法。


5月28日

req.param,req.query,req.body的区别

req.param获取pathinfo中的参数/api/users/{id}

req.query获取查询参数/api/user?name=xky

req.body获取form中提交的参数


6月1日

Gulp和Grunt的区别

Gulp和Grunt的工作方式很不一样。Grunt不使用数据流,而是使用文件,对文件执行单个任务然后保存到新的文件中,每个任务都会重复执行所有进程,文件系统频繁的处理任务会导致Grunt的运行速度比Gulp慢。


6月4日

flexbox不定宽高的水平垂直居中

.parent{
    justify-contentL:center  //子元素水平居中
    align-items:center        //子元素垂直居中
    display:webkit-flex

 


6月6日

伪元素与伪类的区别

CSS 伪类用于向某些选择器添加特殊的效果。

CSS 伪元素用于将特殊的效果添加到某些选择器。


6月7日

 使用负的 nth-child 选择项目

li { display: none; } /* select items 1 through 3 and display them */ li:nth-child(-n+3) { display: block; } 


6月11日

css3 box-sizing属性

box-sizing属性可以为三个值之一:content-box(default),border-box,padding-box。

content-box,border和padding不计算入width之内

padding-box,padding计算入width内

border-box,border和padding计算入width之内,其实就是怪异模式了~


6月13日

 模糊文本

原文链接:http://caibaojian.com/useful-css-tips.html

简单但很漂亮的文本模糊效果,简单又好看!

//code from http://caibaojian.com/useful-css-tips.html
.blur {
   color: transparent;
   text-shadow: 0 0 5px rgba(0,0,0,0.5);
}

6月16日

实参和形参

var add = function (a,b) {
    console.log(arguments.length);//3,表示实参长度
    console.log(arguments.callee.length);//2,表示形参长度
};

add(1,2,3);

new function

var a = function () {};
console.log(typeof a);//function

var b = new function () {};
console.log(typeof b);//object

var c = new Function ();
console.log(typeof c);//function
new function 是一个JavaScript中用户自定义的对象
var obj = function (name) {
    this.name = name;
};
var b = new obj('xiaokunyu');
console.log(b.name);  

js中的false和true

除了false,null,undefined,空字符串'',数字0和NaN以外,其他所有值都被当做是真,包括true,字符串""里包含的值,以及所有对象。


 

6月22日

valueOf() 和 toString()

valueOf()和toString()方法是所有ECMAScript对象拥有的内置方法。操作对象时,valueOf()和toString()会被隐式的调用。

//valueOf()
console.log(Object.valueOf());//[Function: Object]
console.log(Object.prototype.valueOf());//{}

var boo = new Boolean(1);
console.log(boo.valueOf());//true

var bar = Boolean(0);
console.log(bar.valueOf());//false

var str = String("trigkit4");
console.log(str.valueOf());//trigkit4

console.log(null.valueOf());//TypeError
console.log(undefined.valueOf());//TypeError

//toString()
console.log(Object.prototype.toString());//[object Object]
console.log(Object.toString());//function Object() { [native code] }
Object.prototype.toString.call(null);//[object Null]
Object.prototype.toString.call(undefined);//[object Undefined]
{a: 'b'}.toString();//[object Object]
valueOf()方法的目的是将对象转换成最有意义的原始值([[PrimitiveValue]])。即ECMAScript的5种基本类型中的三种,布尔值、数字、字符串。

当valueOf方法被调用时,会调用内置的ToObject,并将this作为参数传进去。ToObject检测会根据参数类型进行数值的转换:

Undefined - 抛出TypeError异常
Null - 抛出TypeError异常
Boolean - 创建一个Boolean对象,调用ToBoolean生成[[PrimitiveValue]]
Number - 创建一个Number对象,调用ToNumber生成[[PrimitiveValue]]
String - 创建一个String对象,调用ToString生成[[PrimitiveValue]]
Object - 对象本身
ECMAScript对象的大多数操作的转换结果是字符串,这两个方法的结果是相同的。但是如果操作的对象为Number、Boolean或者Date,结果就不同了。

var foo = {
toString: function () {
return "foo";
},
valueOf: function () {
return 5;
}
};

console.log(foo + "bar"); // 5bar
console.log([foo, "bar"].join("")); // foobar
在这个上下文环境中,我们使用"+"操作符来使字符串连接,但是,foo并没有使用toString来转换成字符串,它使用valueOf转换成一个number,这并不是我们想要的,
但它是如何工作的,这是+运算符的算术和字符串连接超载的副作用。"+"操作符有一个明确的处理过程:

1.评估左手侧,并得到该值。
2.评估右手侧,并获得该值。
3.同时在左手和右手侧调用ToPrimitive(无提示)
4.如果任何原始值是一个字符串,然后跳到7。
5.在这两个值调用ToNumber。
6.返回值的总和。
7.在这两个值调用toString。
8.返回的值连接起来


6月23日

cookie的取值

cookie可以跨越一个域名下的多个网页,但不能跨越多个域名使用。

document.cookie = “user = 值;expires = 过期时间;path = 路径访问;
domain = 域名访问;secure = 安全的https限制通信"

cookie的创建方式

设置cookie我们一般都封装成一个函数:

function addCookie(sName,sValue,day) { var expireDate = new Date(); expireDate.setDate(expireDate.getDate()+day);; //设置失效时间 document.cookie = escape(sName) + '=' + escape(sValue) +'; expires=' + expireDate.toGMTString();6 //escape()汉字转成unicode编码,toGMTString() 把日期对象转成字符串 } 

删除cookie

为了删除一个cookie,可以将其过期时间设定为一个过去的时间,例如:

//获取当前时间
    var date=new Date(); //将date设置为过去的时间 date.setTime(date.getTime()-10000); //将userId这个cookie删除 document.cookie="userId=828; expires="+date.toGMTString(); 

给cookie设置终止日期

到现在为止,所有的cookie都是单会话cookie,即浏览器关闭后这些cookie将会丢失,事实上这些cookie仅仅是存储在内存中,而没有建立相应的硬盘文件。
在实际开发中,cookie常常需要长期保存,例如保存用户登录的状态。这可以用下面的选项来实现:

document.cookie="userId=828; expiress=GMT_String";

其中GMT_String是以GMT格式表示的时间字符串,这条语句就是将userId这个cookie设置为GMT_String表示的过期时间,超过这个时间,cookie将消失,不可访问。例如:如果要将cookie设置为10天后过期,可以这样实现:

<script language="JavaScript" type="text/javascript"> //获取当前时间 var date=new Date(); var expiresDays=10; //将date设置为10天以后的时间 date.setTime(date.getTime()+expiresDays*24*3600*1000); //将userId和userName两个cookie设置为10天后过期 document.cookie="userId=828; userName=hulk; expires="+date.toGMTString(); </script> 

对象和函数可以如数组一样,用属性名或方法名作为下标来访问:

6月29日

String 原型方法的扩展

    //公共正则表达式处理函数
    String.prototype.Regular = function(reg){ var result = true; if(this.length > 0){ if(!reg.test(this)){ result = false; } } return result; } //.trim()方法 String.prototype.trim = function () { return this.replace(/(^\s*)|(\s*$)/g,''); }; 

^表示字符串必须以后面的规则开头,而(^\s*) 表示的就是以0个空格或者多个空格开头,后面的(\s*$) 的意思就是, 以0个空格或者多个空格结尾。

 
    //判断输入内容是否为空
    String.prototype.isNull = function(){ return this.trim().length == 0 ? true : false; } //判断输入的字符是否为英文字母\数字\下划线 String.prototype.isVersion = function(){ var reg = /^([a-zA-Z_])([a-zA-Z0-9_.])*$/; return this.Regular(reg); } // 判断输入的字符串,不包括单引号 String.prototype.isString = function(){ var reg = /^[^']*$/; return this.Regular(reg); } //判断输入的字符是否为英文字母 String.prototype.isLetter = function(){ var reg = /^[a-zA-Z]+$/; return this.Regular(reg); } 

7月2日

tranform,transation,transate的区别


 

7月4日

重定向页面的方法

// 类似HTTP重定向的行为 
window.location.replace("http://stackoverflow.com");

// 类似点击一个链接的行为 
window.location.href = "http://stackoverflow.com";

7月7日

css3 box-sizing属性

box-sizing属性可以为三个值之一:content-box(default),border-box,padding-box。

content-box,border和padding不计算入width之内

padding-box,padding计算入width内

border-box,border和padding计算入width之内,其实就是怪异模式了~


 7月10日

array filter

function remove(arr, item) {
    return arr.filter(function(x) { return x !== item; });
}

关于eval

可以直接执行字符串中的JS


 

7月11日

数组清除重复项

这是另外一道题目,数组里有重复项,要怎么清除。一查我再掩面而泣,原来js里就带了filter就可以干这活。代码如下:

myArray.filter(function(elem, pos,self){return self.indexOf(elem)== pos;})

filter是过滤的意思,filter通过一个函数的参数来选择什么项需要被filter掉,函数返回true保留,false干掉。

函数参数带三个参数,第一个elem是这一项元素,第二个pos是这一项所在的位置,第三个self指的是执行filter的数组。那么,你看,巧妙吗:self.indexOf(elem) 是指这个项目在数组中的位置,位置是第一个,也就是说同样的项目在第一位和第5位都出现了,他返回的是0,而此时pos还是4,所以通过self.indexOf(elem) == pos 能判断出这一项是不是重复出现的项,如果是(返回false),则干掉它。

Array map

map()对数组的每个元素进行一定操作(映射)后,会返回一个新的数组

 


 

7月12日

JS数组实现堆栈的方法

shift:从集合中把第一个元素删除,并返回这个元素的值。

unshift: 在集合开头添加一个或更多元素,并返回新的长度

push:在集合中添加元素,并返回新的长度

pop:从集合中把最后一个元素删除,并返回这个元素的值。


 

7月14日

如何用两个栈实现一个队列

入队时,将元素压入s1。

出队时,判断s2是否为空,如不为空,则直接弹出顶元素;如为空,则将s1的元素逐个“倒入”s2,把最后一个元素弹出并出队。

这个思路,避免了反复“倒”栈,仅在需要时才“倒”一次。


 

7月16日

JS的各种属性与方法

http://www.jb51.net/article/53960.htm

元素节点,属性节点和文本节点

http://www.cnblogs.com/dh616854836/archive/2011/08/14/2138038.html


7月19日

节点信息

每个节点都拥有包含着关于节点某些信息的属性。这些属性是:

  • nodeName(节点名称)
  • nodeValue(节点值)
  • nodeType(节点类型)

7月21日

git fetch和git pull的区别

git pull:相当于是从远程获取最新版本并merge到本地

git fetch:相当于是从远程获取最新版本到本地,不会自动merge

 

7月22日

响应式与自适应的区别

响应式与自适应的原理是相似的,都是检测设备,根据不同的设备采用不同的css,而且css都是采用的百分比的,而不是固定的宽度,不同点是响应式的模板在不同的设备上看上去是不一样的,会随着设备的改变而改变展示样式,而自适应不会,所有的设备看起来都是一套的模板,不过是长度或者图片变小了,不会根据设备采用不同的展示样式,流式就是采用了一些设置,当宽度大于多少时怎么展示,小于多少时怎么展示,而且展示的方式向水流一样,一部分一部分的加载,静态的就是采用固定宽度的了。


 

8月12日

getElementsByTagName()的返回值问题

返回值是DOM对象而不是数组。可以通过

Array.prototype.slice.call()

来转化为数组

function定义的对象有一个prototype属性,使用new生成的对象就没有这个prototype属性。

 


8月13日

关于this的指向

当函数作为方法调用时,this指向调用该方法的对象, 当函数作为嵌套函数调用时, this指向全局对象(非严格模式下)或者undefined(严格模式)而不是其外包函数的上下文

em和rem

em相对于父级font.rem相对于html跟元素的font

defer与async

原文链接:http://caibaojian.com/jsload.html
带有 defer 属性的<script>标签可以放置在文档的任何位置。对应的 JavaScript 文件将在页面解析到<script>标签时开始下载,但不会执行,直到 DOM 加载完成,即onload事件触发前才会被执行。当一个带有 defer 属性的 JavaScript 文件下载时,它不会阻塞浏览器的其他进程,因此这类文件可以与其他资源文件一起并行下载。

原文链接:http://caibaojian.com/jsload.html

数字转为数组:

'' + (Math.floor(Math.random() * width) + start)


,在有 async 的情况下,JavaScript 脚本一旦下载好了就会执行,所以很有可能不是按照原本的顺序来执行的。如果 JavaScript 脚本前后有依赖性,使用 async 就很有可能出现错误。


8月16日

通用判断类型的方法

Object.prototype.toString() 
在toString方法被调用时,会执行下面的操作步骤:
 
1. 获取this对象的[[Class]]属性的值。
 
2. 计算出三个字符串"[object ", 第一步的操作结果Result(1), 以及 "]"连接后的新字符串。
 
3. 返回第二步的操作结果Result(2)。

[[Class]]是一个内部属性,所有的对象(原生对象和宿主对象)都拥有该属性.在规范中,[[Class]]是这么定义的:
内部属性 描述
[[Class]] 一个字符串值,表明了该对象的类型。

其过程简单说来就是:1、获取对象的类名(对象类型)。2、然后将[object、获取的类名、]组合并返回。

8月20日

单页面应用

http://www.tuicool.com/articles/IvyYNb


 

转载于:https://www.cnblogs.com/Kygo4/p/5451902.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值