关于前端面试技能点分析

楼主总结了一些关于前端面试时技能点的知识点:里面的知识都是从互联网上找到的。

1、熟练使用HTML/CSS,能够手写符合W3C标准的页面,能够兼容主流浏览器,可以精确还原设计图;

浏览器兼容问题:

浏览器兼容问题一:不同浏览器的标签默认的外补丁和内补丁不同

问题症状:随便写几个标签,不加样式控制的情况下,各自的margin 和padding差异较大。

碰到频率:100%

解决方案:CSS里 *{margin:0;padding:0;}

备注:这个是最常见的也是最易解决的一个浏览器兼容性问题,几乎所有的CSS文件开头都会用通配符*来设置各个标签的内外补丁是0。

浏览器兼容问题二:块属性标签float后,又有横行的margin情况下,在IE6显示margin比设置的大

问题症状:常见症状是IE6中后面的一块被顶到下一行

碰到频率:90%(稍微复杂点的页面都会碰到,float布局最常见的浏览器兼容问题)

解决方案:在float的标签样式控制中加入 display:inline;将其转化为行内属性

备注:我们最常用的就是div+CSS布局了,而div就是一个典型的块属性标签,横向布局的时候我们通常都是用div float实现的,横向的间距设置如果用margin实现,这就是一个必然会碰到的兼容性问题。

浏览器兼容问题三:设置较小高度标签(一般小于10px),在IE6,IE7,遨游中高度超出自己设置高度

问题症状:IE6、7和遨游里这个标签的高度不受控制,超出自己设置的高度

碰到频率:60%

解决方案:给超出高度的标签设置overflow:hidden;或者设置行高line-height 小于你设置的高度。

备注:这种情况一般出现在我们设置小圆角背景的标签里。出现这个问题的原因是IE8之前的浏览器都会给标签一个最小默认的行高的高度。即使你的标签是空的,这个标签的高度还是会达到默认的行高。

浏览器兼容问题四:行内属性标签,设置display:block后采用float布局,又有横行的margin的情况,IE6间距bug

问题症状:IE6里的间距比超过设置的间距

碰到几率:20%

解决方案:在display:block;后面加入display:inline;display:table;

备注:行内属性标签,为了设置宽高,我们需要设置display:block;(除了input标签比较特殊)。在用float布局并有横向的margin后,在IE6下,他就具有了块属性float后的横向margin的bug。不过因为它本身就是行内属性标签,所以我们再加上display:inline的话,它的高宽就不可设了。这时候我们还需要在display:inline后面加入display:talbe。

浏览器兼容问题五:图片默认有间距

问题症状:几个img标签放在一起的时候,有些浏览器会有默认的间距,加了问题一中提到的通配符也不起作用。

碰到几率:20%

解决方案:使用float属性为img布局

备注:因为img标签是行内属性标签,所以只要不超出容器宽度,img标签都会排在一行里,但是部分浏览器的img标签之间会有个间距。去掉这个间距使用float是正道。(我的一个学生使用负margin,虽然能解决,但负margin本身就是容易引起浏览器兼容问题的用法,所以我禁止他们使用)

浏览器兼容问题六:标签最低高度设置min-height不兼容

问题症状:因为min-height本身就是一个不兼容的CSS属性,所以设置min-height时不能很好的被各个浏览器兼容

碰到几率:5%

解决方案:如果我们要设置一个标签的最小高度200px,需要进行的设置为:{min-height:200px; height:auto !important; height:200px; overflow:visible;}

备注:在B/S系统前端开时,有很多情况下我们又这种需求。当内容小于一个值(如300px)时。容器的高度为300px;当内容高度大于这个值时,容器高度被撑高,而不是出现滚动条。这时候我们就会面临这个兼容性问题。

浏览器兼容问题七:透明度的兼容CSS设置

做兼容页面的方法是:每写一小段代码(布局中的一行或者一块)我们都要在不同的浏览器中看是否兼容,当然熟练到一定的程度就没这么麻烦了。建议经常会碰到兼容性问题的新手使用。很多兼容性问题都是因为浏览器对标签的默认属性解析不同造成的,只要我们稍加设置都能轻松地解决这些兼容问题。如果我们熟悉标签的默认属性的话,就能很好的理解为什么会出现兼容问题以及怎么去解决这些兼容问题。

  • /* CSS hack*/

我很少使用hacker的,可能是个人习惯吧,我不喜欢写的代码IE不兼容,然后用hack来解决。不过hacker还是非常好用的。使用hacker我可以把浏览器分为3类:IE6 ;IE7和遨游;其他(IE8 chrome ff safari opera等)

◆IE6认识的hacker 是下划线_ 和星号 *

◆IE7 遨游认识的hacker是星号 *

比如这样一个CSS设置:

  • height:300px;*height:200px;_height:100px;

IE6浏览器在读到height:300px的时候会认为高时300px;继续往下读,他也认识heihgt, 所以当IE6读到height:200px的时候会覆盖掉前一条的相冲突设置,认为高度是200px。继续往下读,IE6还认识_height,所以他又会覆盖掉200px高的设置,把高度设置为100px;

IE7和遨游也是一样的从高度300px的设置往下读。当它们读到*height200px的时候就停下了,因为它们不认识_height。所以它们会把高度解析为200px,剩下的浏览器只认识第一个height:300px;所以他们会把高度解析为300px。因为优先级相同且想冲突的属性设置后一个会覆盖掉前一个,所以书写的次序是很重要的。

关于透明度兼容:
function setAlphaOpacity(elm,value){
elm=typeof elm=="string"?document.getElementById(elm):elm;
if(document.all){ //IE
elm.style.filter='alpha(opacity='+value+')';
}else{ //FF
elm.style.opacity=value/100;
}
}
浏览器引擎前缀(Vendor Prefix)有哪些?

-moz- /* 火狐等使用Mozilla浏览器引擎的浏览器 /
-webkit- /
Safari, 谷歌浏览器等使用Webkit引擎的浏览器 /
-o- /
Opera浏览器(早期) /
-ms- /
Internet Explorer (不一定) */

2、深入理解JavaScript高级特性(如OOP、继承、原型链、闭包等),了解ES6新特性

OOP:面向对象是一种编程思想,用一句话来说,就是抽象封装继承多态。

继承:有四种:
1、原型链继承
2、构造函数继承
3、组合继承
4、冒充对象继承

原型链:
有限的实例对象和原型之间组成有限链,就是用来实现共享属性和继承的

闭包:
1、有权访问另一个函数作用域内变量的函数都是闭包
2、闭包的作用:
(1)、形成隔离的封闭空间
(2)、延长变量的生命周期(正常情况下,函数调用结束之后,那么函数内部的变量都会被销毁)
(3)、缓存数据
3、缺点:
(1)消耗内存
(2)内存泄漏:闭包,全局变量,没有清理的DOM元素引用,被遗忘的定时器回调

ES6新特性:
(1)块级作用域
(2)关键字
(3)变量解构赋值
(4)字符串的扩展
(5)数组扩展
(6)函数扩展

3、熟练使用Ajax进行前后台数据交互,熟练使用JSONP解决浏览器常见的跨域请求问题
var xhr =null;//创建对象
if(window.XMLHttpRequest){
 xhr = new XMLHttpRequest();
}else{
 xhr = new ActiveXObject("Microsoft.XMLHTTP");
}
 xhr.open(“方式”,”地址”,”标志位”);//初始化请求
 xhr.setRequestHeader(“”,””);//设置http头信息
 xhr.onreadystatechange =function(){}//指定回调函数
 xhr.send();//发送请求

Ajax原生代码:
// 1.实例化对象
var xhr = new XMLHttpRequest();

// 2.设置请求行(请求方式,请求地址)  要使用open方法来设置
// false代表不是异步 是同步  已经被弃用
xhr.open('post','./anync.php',true);

// 3.设置请求头(post请求必须写这样的请求头)
xhr.setRequestHeader('Content-Type','application/x-www-form-urlencoded');
// 4.设置请求正文 格式:key=value&key=value  

xhr.send('username=wanlum&password=1314520');

// 5.监听并处理响应
// xhr.onreadystatechange=function(){
//   if(xhr.readyState == 4 && xhr.status== 200){
//     // document.querySelector('p').innerHTML +=xhr.responseText;
//     console.log(xhr.responseText);
//   }
  1. 创建XMLHttpRequest对象,也就是创建一个异步调用对象
  2. 创建一个新的HTTP请求,并指定该HTTP请求的方法、URL及验证信息
  3. 设置响应HTTP请求状态变化的函数
  4. 发送HTTP请求
  5. 获取异步调用返回的数据
  6. 使用JavaScript和DOM实现局部刷新
    优点:
    Ajax可以实现异步通信效果,实现页面局部刷新,带来更好的用户体验;按需获取数据,节约带宽资源;
    缺点:
    1、ajax不支持浏览器back按钮。
    2、安全问题 AJAX暴露了与服务器交互的细节。
    3、对搜索引擎的支持比较弱。
    4、破坏了程序的异常机制。
    get和post(ajax版本)

get一般用来进行查询操作,url地址有长度限制,请求的参数都暴露在url地址当中,如果传递中文参数,需要自己进行编码操作,安全性较低。
post请求方式主要用来提交数据,没有数据长度的限制,提交的数据内容存在于http请求体中,数据不会暴漏在url地址中。

JSONP:
 Jsonp并不是一种数据格式,而json是一种数据格式,jsonp是用来解决跨域获取数据的一种解决方案,具体是通过动态创建script标签,然后通过标签的src属性获取js文件中的js脚本,该脚本的内容是一个函数调用,参数就是服务器返回的数据,为了处理这些返回的数据,需要事先在页面定义好回调函数,本质上使用的并不是ajax技术

Ajax是全称是asynchronous JavaScript andXML,即异步JavaScript和xml,用于在Web页面中实现异步数据交互,实现页面局部刷新。
优点:可以使得页面不重载全部内容的情况下加载局部内容,降低数据传输量,避免用户不断刷新或者跳转页面,提高用户体验
缺点:对搜索引擎不友好;要实现ajax下的前后退功能成本较大;可能造成请求数的增加跨域问题限制;
JSON是一种轻量级的数据交换格式,ECMA的一个子集
优点:轻量级、易于人的阅读和编写,便于机器(JavaScript)解析,支持复合数据类型(数组、对象、字符串、数字)

原生代码:
function myJsonp(url,data,callback){

var fnName = "myJsonp_" + Math.random().toString().replace('.','');

window[fnName] = callback;

var querystring = '';

for(var attr in data){

    querystring += attr + '=' + data[attr] + '&'

}

var script = document.createElement('script');

script.src = url + '?' + querystring + 'callback='+ fnName;

script.onload = function(){

    document.body.removeChild(script);

}

document.body.appendChild(script);

}

4、熟悉流式布局和响应式布局原理,熟悉Bootstrap前端框架,能够开发响应式页面

模态框。分页。字体。遮罩层。下拉框。TAB栏

响应式布局是关于网页制作的过程中让不同的设备有不同的尺寸和不同的功能。响应式设计是让所有的人能在这些设备上让网站运行正常

5、对前端模块化有一定的了解,对less等预处理有一定的了解

模块化:
一个模块就是实现特定功能的文件,有了模块,我们就可以更方便地使用别人的代码,想要什么功能,就加载什么模块。

less和sass是动态的样式语言,是CSS预处理器,CSS上的一种抽象层。他们是一种特殊的语法/语言而编译成CSS。
变量符不一样,less是@,而Sass是$;
Sass支持条件语句,可以使用if{}else{},for{}循环等等。而Less不支持;
Sass是基于Ruby的,是在服务端处理的,而Less是需要引入less.js来处理Less代码输出Css到浏览器

Less 是一门 CSS 预处理语言,它扩充了 CSS 语言,增加了诸如变量、混合(mixin)、函数等功能,让 CSS 更易维护、方便制作主题、扩充。
6、熟悉主流模板引擎、并熟练操作arttemplate和xtemplate

客户端渲染路线:1. 请求一个html -> 2. 服务端返回一个html -> 3. 浏览器下载html里面的js/css文件 -> 4. 等待js文件下载完成 -> 5. 等待js加载并初始化完成 -> 6. js代码终于可以运行,由js代码向后端请求数据( ajax/fetch ) -> 7. 等待后端数据返回 -> 8. 客户端从无到完整地,把数据渲染为响应页面

服务端渲染路线:2. 请求一个html -> 2. 服务端请求数据( 内网请求快 ) -> 3. 服务器初始渲染(服务端性能好,较快) -> 4. 服务端返回已经有正确内容的页面 -> 5. 客户端请求js/css文件 -> 6. 等待js文件下载完成 -> 7. 等待js加载并初始化完成 -> 8. 客户端把剩下一部分渲染完成( 内容小,渲染快 )
7、使用git、gulp对代码进行管理和构建,npm、bower等依赖管理工具

给远程仓库地址起一个别名
git remote add abc ../../hello.git
这个克隆的名字默认是origin。
克隆下的项目会自动建立跟踪分支(git push 或者 git pull)
git remote查看有哪些远程地址的别名
这时候如果为空则需要自己加
git remote add abc ../../hello.git
更新一下
git pull origin master
想要直接推
git push -u origin master这样就建立了关联。(-u的作用就是建立了跟踪分支,只需要第一次使用,以后可以直接git push)
git remote show origin看出每一个别名的地址是什么

8、熟练使用Angular,理解MVC、MVVM开发模式和SPA程序开发

MVC是一种开发模式,由模型(Model)、视图(View)、控制器(Controller)3部分构成,采用这种开发模式为合理组织代码提供了方便、降低了代码间的耦合度、功能结构清晰可见。

 模型(Model)一般用来处理数据(读取/设置),一般指操作数据库。
 视图(View)一般用来展示数据,比如通过HTML展示。
 控制器(Controller)一般用做连接模型和视图的桥梁。

单页面应用(SPA):
SPA(Single Page Application)指的是通单一页面展示所有功能,通过Ajax动态获取数据然后进行实时渲染,结合CSS3动画模仿原生App交互,然后再进行打包(使用工具把Web应用包一个壳,这个壳本质上是浏览器)变成一个“原生”应用。

在PC端也有广泛的应用,通常情况下使用Ajax异步请求数据,然后实现内容局部刷新,局部刷新的本质是动态生成DOM,新生成的DOM元素并没有真实存在于文档中,所以当再次刷新页面时新添加的DOM元素会“丢失”,通过单页面应可以很好的解决这个问题。

9、熟练使用前端基础类库,如jQuery

(1)事件操作
(2)DOM样式操作
(3)标签获取

10、对Web前端技术有强烈兴趣,对Node.js有一定的使用经验;

NodeJS
是一个运行环境,其使用了一个事件驱动、非阻塞式(异步) I/O的模型,使其轻量又高效

宿主环境
ECMAScript语法规则,需要不同版本实现。如果说ECMAScript运行在浏览器,称为javascript,简称JS。如果说ECMAScript运行flash环境,称为ActionScript,简称AS。如果ECMAScript运行在Node环境,称为Nodejs。这个环境就是宿主环境。必须依赖于某个环境,ECMAScript需要“寄生在某一宿主环境”。

11、熟练使用HTML5和CSS3相关技术开发移动端和PC端前端应用

H5 C3的新属性

HTML5: nav, footer, header, section, hgroup, video, time, canvas, audio...

CSS3: RGBA, opacity, text-shadow, box-shadow, border-radius, border-image,
border-color, transform...;
新增的元素有绘画 canvas ,用于媒介回放的 video 和 audio 元素,本地离线存储 localStorage 长期存储数据,浏览器关闭后数据不丢失,而sessionStorage的数据在浏览器关闭后自动删除,此外,还新增了以下的几大类元素。

内容元素,article、footer、header、nav、section。

表单控件,calendar、date、time、email、url、search。

控件元素,webworker, websockt, Geolocation。

移出的元素有下列这些:

显现层元素:basefont,big,center,font, s,strike,tt,u。

性能较差元素:frame,frameset,noframes。
css3:
gradient:gradient(linear,0% 0%,100% 0%,form(red),to(balck))
transform
Transition:property duration timing-function delay
animation

12、了解浏览器和服务器的交互

譬如一个http://danYoo网站,以indexhtml为主页,该主页使用index.manifest文件为manifest文件,在该文件中请求本地缓存index.html、hello.js、hello.jpg、hello2.jpg这几个资源文件。

  1. 首次访问http://danYoo网站时,它们的交互过程如下所示:
    ①浏览器请求访问http://danYoo
    ②服务器返回index.html网页
    ③浏览器解析index.html网页,请求页面上所有资源文件,包括HTML文件、图像文件、CSS文件、JavaScript脚本文件,以及manifest文件
    ④服务器返回所有资源文件
    ⑤浏览器处理manifest文件,请求manifest中所有要求本地缓存的文件,包括index.html页面本身,即使刚才已经请求过这些文件。如果你要求本地缓存所有文件,这将是一个比较大的重复的请求过程。
    ⑥服务器返回所有要求本地缓存的文件
    ⑦浏览器对本地缓存进行更新,存入包括页面本身在内的所有要求本地缓存的资源文件,并且触发一个事件,通知本地缓存被更新。
  2. 如果再次打开浏览器访问http://danYoo网站,而且manifest文件没有修改过
    ①浏览器再次请求访问http://danYoo
    ②浏览器发现这个网页被本地缓存,于是使用本地缓存中index.html页面
    ③浏览器解析index.html页面,使用所有本地缓存中的资源文件.
    ④浏览器向服务器请求manifest文件
    ⑤服务器返回一个304代码,通知浏览器manifest没有发生变化
    只要页面上的资源文件被本地缓存过,下次浏览器打开这个页面时,总是先使用本地缓存中的资源,然后请求manifest文件
  3. 如果再次打开浏览器时manifest文件已经被更新过了,那么浏览器与服务器之间的交互如下:
    ①浏览器再次请求访问http://danYoo
    ②浏览器发现这个页面被本地缓存,于是使用本地缓存中的index.html页面
    ③浏览器解析index.html页面,使用所有本地缓冲中的资源文件
    ④浏览器向服务器请求manifest文件
    ⑤服务器返回更新过的manifest文件
    ⑥浏览器处理manifest文件,发现该文件已被更新,于是请求所有要求进行本地缓存的资源文件,包括indexhtml页面本身
    ⑦浏览器返回要求进行本地缓存的资源文件
    ⑧浏览器对本地缓存进行更新,存入所以新的资源文件。并且触发一个事件,通知本地缓存被更新
    需要注意的是,即使资源文件被修改过了,在上面的第3中已经装入的资源文件是不会发生变化的,譬如图片不会突然变成新的图片,脚本文件也不会突然使用新的脚本文件,也就是说,这时更新过后的本地缓存中的内容还不能被使用,只有重新打开这个页面的时候才会使用更新过后的资源文件。另外,如果你不想修改manifest文件中对于资源文件的设置,但是你对服务器上请求缓存的资源文件进行了修改,那么你可以通过修改版本号的方式来让浏览器认为imanifest文件已经被更新过了,以便重新下载修改过的资源文件。

额外:
12、H5C3快速搭建页面布局

HTML5/CSS3响应式布局介绍及设计流程,利用css3的media query媒体查询功能。
确定需要兼容的设备类型、屏幕尺寸
专业技能整理1
制作线框原型
测试线框原型
视觉设计
前端实现

13、懒加载

1、大型的电商网站的一个页面上有大量的图片,加载很面。解决办法:
(1)图片懒加载,在页面的未可是区域添加一个滚动条事件。判断图片位置与浏览器顶端的距离与页面的距离,如果前者小于后者,有限加载
(2)如果为幻灯片、相册等,可以使用图片预加载技术,将当前展示图片的前一张和后一张优先下载。
(3)如果图片为css图片,可以使用CSSsprite、SVGsprite、Iconfont、Base64等技术。
(4)当图片过大,可以使用特殊编码的图片,加载时会先加载一张亚索的特别厉害的缩略图,以提高用户体验。
(5)如果图片展示区域小于图片的真实大小,则因在服务器端根据业务需要先行进行图片压缩,图片压缩后大小与展示一致。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,456评论 5 477
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,370评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,337评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,583评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,596评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,572评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,936评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,595评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,850评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,601评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,685评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,371评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,951评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,934评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,167评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 43,636评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,411评论 2 342

推荐阅读更多精彩内容

  • 问答题47 /72 常见浏览器兼容性问题与解决方案? 参考答案 (1)浏览器兼容问题一:不同浏览器的标签默认的外补...
    _Yfling阅读 13,725评论 1 92
  • Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智...
    卡卡罗2017阅读 134,585评论 18 139
  • <a name='html'>HTML</a> Doctype作用?标准模式与兼容模式各有什么区别? (1)、<...
    clark124阅读 3,455评论 1 19
  • 前端开发面试知识点大纲: HTML&CSS: 对Web标准的理解、浏览器内核差异、兼容性、hack、CSS基本功:...
    秀才JaneBook阅读 2,326评论 0 25
  • 听,风吹雨;听,你侬我侬;听,花月夜呢喃。听···叮铃铃 你有没有想过神奇的你,是怎么听到了美妙的声音呢? ...
    JHYHYHYY阅读 184评论 0 2