minnsss blog

I was never there.


  • 首页

  • 标签

  • 分类

  • 归档

  • 关于

算法

发表于 2018-09-07 | 更新于 2018-09-08 | 分类于 前端

算法

排序

排序比较

冒泡排序

选择排序

Javascript算法——选择排序:
https://segmentfault.com/a/1190000009366805

插入排序

希尔排序

Javascript算法——希尔排序:

https://segmentfault.com/a/1190000009461832

归并排序

快速排序

Javascript算法——快速排序:

https://segmentfault.com/a/1190000009426421

堆排序

计数排序

桶排序

基数排序

堆栈 队列 链表

JavaScript 的数据结构与算法:

https://juejin.im/entry/58759e79128fe1006b48cdfd

递归

JavaScript中的递归:

https://segmentfault.com/a/1190000009857470

波兰式和逆波兰式

理论:

http://www.cnblogs.com/chenying99/p/3675876.html

源码:

https://github.com/Tairraos/rpn.js/blob/master/rpn.js

安全

发表于 2018-09-07 | 更新于 2018-09-08 | 分类于 前端

安全

CSRF

基本概念和缩写

cross-site request forgery

跨站请求伪造

攻击原理

在B网站引诱用户访问A网站(用户之前登陆过A网站,浏览器cookie缓存了身份验证信息),调用A网站的接口攻击A网站

某个接口存在漏洞

用户曾经登录过

eg: 新浪微博莫名增加关注和粉丝

防御措施

1.token验证:登陆成功后服务器下发token令牌存到用户本地,再次访问时要主动发送token,浏览器只能主动发cookie,做不到主动发token

2.referer验证:判断页面来源是否自己站点的页面,不是不执行请求

3.隐藏令牌:令牌放在http header头中,而不是链接中

XSS

基本概念和缩写

cross-site scripting

跨域脚本攻击

攻击原理

CSRF攻击原理
不需要登陆

页面注入js脚本

防御措施

令xss无法执行

两者区别

XSS 向页面注入JS允许,JS函数体做事

CSRF 利用本身漏洞,自动执行那些接口,依赖登录网站

通信

发表于 2018-09-06 | 分类于 前端

通信类

什么是同源策略及限制

从一个源加载的文档或脚本如何与来自另一个源的资源进行交互

这是一个用于隔离潜在恶意文件的关键的安全机制

源

协议

域名

端口 (默认80)

限制

Cookie LocalStorage IndexDB无法读取

DOM无法获得

Ajax请求不能发送/Ajax仅适用同源

前后端如何通信

Ajax

同源下的通信方式

WebSocket

不受同源策略的限制

CORS

既支持同源,也支持跨域

如何创建Ajax

XMLHttpRequest对象的工作流程

兼容性处理

事件的触发条件

事件的触发顺序

跨域通信的几种方式

JSONP

原理

使用script标签的异步加载实现。

即script标签src属性中的链接可以访问跨域的js脚本,利用这个特性,服务端不再返回JSON格式的数据,而是返回一段调用某个函数的js代码,在src中进行了调用,这样实现了跨域

前后端通信

实现

Hash

原理

hash的改变不会刷新页面

seach刷新页面

浏览器跨标签通信,可以跨域但不通过服务器

实现

postMessage

原理

H5新增

浏览器跨标签通信,可以跨域但不通过服务器

同源策略目标是限制跨域通信,在实际业务中又需要跨域通信

实现

WebSocket

原理

前后端通信

实现

CORS

原理

可理解为支持跨域通信的Ajax,是一个新的通信标准

浏览器会拦截Ajax请求,感觉如果是跨域的,会在http头中加一个original允许跨域通信

前后端通信

实现

fetch

源码

/source/mvvm/

jsonp.js

ajax.html

面向对象

发表于 2018-09-06 | 分类于 前端

面向对象

类与实例

类的声明

生成实例

类与继承

继承的本质就是原型链

如何实现继承

继承的几种方式

源码

oop.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="utf-8">
    <title>面向对象</title>
</head>
<body>
<script type="text/javascript">

    //类的声明
    function Animal(){
        this.name = 'name';
    }

    //ES6中的class声明
    class Animal2{
        constructor() {
            this.name = name;
        }
    }

    //实例化一个类的对象
    console.log(new Animal(), new Animal2());

    //类的继承

    //1.借助构造函数实现继承:原型链没有被继承,仅实现部分继承
    function Parent1() {
        this.name = 'parent1';
    }

    //Parent1.prototype.say = function() {};没有被继承
    function Child1() {
        Parent1.call(this);//apply 将父级的构造函数this的指向子级构造函数的实例,实现继承
        this.type = 'child1';
    }

    console.log(new Child1());

    //2.原型链实现
    function Parent2(){
        this.name = 'parent2';
        this.play = [1,2,3];
    }
    function Child2() {
        this.type = 'child2';
    }
    Child2.prototype = new Parent2();//函数具有prototype属性 ,是一个对象 可任意赋值 -父级的实例
    console.log(new Child2());

    var S1 = new Child2();
    var S2 = new Child2();
    console.log(S1.play, S2.play);//
    S1.play.push(4);//缺点:原型链中的原型对象是共用的,所以实例改变其值,其他实例对应的属性也会变

    //3.组合方式继承 缺点:父级的构造函数执行了两次,并把父类的constructor也继承了
    function Parent3() {
        this.name = 'parent3';
        this.play = [1,2,3];
    }
    function Child3() {
        Parent3.call(this);
        this.type = 'child3';
    }

    Child3.prototype = new Parent3();
    var S3 = new Child3();
    var S4 = new Child3();
    S3.play.push(4);
    console.log(S3.play, S4.play);

    //组合继承优化1 缺点:把父类的constructor也继承了
    function Parent4() {
        this.name = 'parent4';
        this.play = [1,2,3];
    }
    function Child4() {
        Parent4.call(this);
        this.type = 'child4';
    }

    Child4.prototype = Parent4.prototype;//引用同一个对象
    var S5 = new Child4();
    var S6 = new Child4();
    console.log(S5, S6);

    console.log(S5 instanceof Child4, S5 instanceof Parent4);
    console.log(S5.constructor); //Parent4

    //组合继承优化2 原理是通过Object.create方法创建一个中间对象,参数是该对象的原型对象,然后把子类的构造函数赋值为该子类
    function Parent5() {
        this.name = 'parent5';
        this.play = [1,2,3];
    }
    function Child5() {
        Parent5.call(this);
        this.type = 'child5';
    }

    Child5.prototype = Object.create(Parent5.prototype);//达到了父类和子类的隔离 .__proto__ 

    Child5.prototype.constructor = Child5;

    var S7 = new Child5();
    console.log(S7 instanceof Child5, S7 instanceof Parent5);
    console.log(S7.constructor);

</script>
</body>
</html>

原型链

发表于 2018-09-06 | 分类于 前端

原型链

创建对象有几种方法

3种方法

字面量对象

var o1 = {name:'o1'};
var o11 = new Object({name: 'o11'});

显式构造函数

var M = function(){
        this.name = 'o2'}
var o2 = new M();

Object.create()方法

使用原型链连接,与前两种方法不太一样

var P = {name:'o3'};
var o3 = Object.create(P);

原型 构造函数 对象实例 原型链

原型链的原理

原型链关系

从一个实例对象往上找构造这个实例的相关联的对象,这个相关联的对象往上找又有创造他的上一级的原型对象,以此类推,一直到object.prototype终止

原型链是js实现类与继承的基石

原型链和类与继承的关系

原型对象 构造函数 实例的关系

  1. 只有函数才有prototype, 对象没有(函数也是对象)

  2. 只有实例对象有__proto__,函数也有__proto__,因为函数也是对象xx.__proto__ = Function.prototype

  3. 修改了实例也就修改了实例上一级的原型对象

instanceof的原理

instanceof原理

判断函数属性是否是实例原型对象(constructor更严谨)

new运算符

1.一个新对象被创建。它继承自foo.prototype

2.构造函数foo被执行。执行的时候,相应的传参会被传入,同时上下文(this)会被指定为这个新实例。new foo等同于 new foo(),只能用在不传递任何参数的情况下。

3.如果构造函数返回一个对象,那么这个对象会取代整个new出来的结果。如果构造函数没有返回对象,那么new出来的结果为步骤1创建的对象

源码

proto.html

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <title>原型链</title>
</head>
<body>
    <script type="text/javascript">
        //第一种方式:字面量
        var o1 = {name: 'o1'};//o1 {name: "o1"}
        var o2 = new Object({name: 'o2'});//o2 {name: "o2"}

        //第二种方式:构造函数
        var M = function(name){
            this.name=name;
        };
        var o3 = new M('o3');//o3 M{name: "o3"}

        //第三种方式:Object.create 原型链连接
        var P = {name: 'p'};
        var o4 = Object.create(P);//o4 {}   o4.name "p"


        //原型链原理
        M.prototype.say = function(){
            console.log('say hi');
        }
        var o5 = new M('o5');


        //实现new运算符的效果 即工作原理
        var new2 = function(func) {
            var o = Object.create(func.prototype);//创建空对象,关联构造函数的原型对象
            var k = func.call(o);//执行构造函数
            if (typeof k === 'object')//判断构造函数的运行结果是否为对象类型
            {
                 return k
            }else{
                return o
            }
        }
    </script>

</body>
</html>

HTTP协议类

发表于 2018-09-04 | 更新于 2018-09-06 | 分类于 前端

HTTP协议类

HTTP协议的主要特点

简单快速 每个资源是固定的URI

灵活 通过一个HTTP协议可以完成不同的数据类型的传输

无连接 连接一次就会断开,不会保持连接

无状态 客户端和服务端是两种身份,一次连接后就断开,下次再连接,服务端无法区分两次是否由同一客户端发起的请求

HTTP报文的组成部分

请求报文

请求行 http方法、页面地址、http协议以及版本

请求头 key:value值 告诉服务端我要什么内容要注意什么 类型

空行 最后一个请求头之后是一个空行,发送回车符和换行符,通知服务器以下不再有请求头 不是请求头的部分了

请求体 空行是用来分隔请求头和请求体

响应报文

状态行

响应头

空行

响应体

HTTP方法

类别

GET获取资源

POST传输资源

PUT更新资源

DELETE删除资源

HEAD获取报文首部

post与get的区别

! get在浏览器回退时是无害的,post会再次提交

get产生的url地址可以被收藏,post不可以

! get请求自动被浏览器缓存,post不会,除非手动设置

get请求只能进行url编码,post支持多种

! get请求参数会被完整保留在浏览器历史记录里,post中的参数不会被保留

! get请求在url中传送的参数是长度限制的(2kb),post没有

对参数的数据类型,get只接受ascii码,post没有

get比post更不安全,因为参数直接暴露在url上

! get参数通过url传递,post放在Request body中

HTTP状态码

1xx 指示信息 表示请求已接收,继续处理

2xx 成功 表示请求已被成功接收

3xx 重定向 要完成请求必须进行更进一步的操作

4xx 客户端错误 请求有语法错误或者请求无法实现

5xx 服务器错误 服务器未能实现合法的请求

eg

200 OK

206 Partical OK

301 Moved Permanently 转移到新的url

302 Found 临时转移到新的url

304 Not Modified

400 Bad Request

401 Unauthorized

403 Forbidden

404 Not Found

500 Internal Server Error

503 Server Unavailble

持久连接

请求-应答模式

HTTP协议采用“请求-应答”模式,当使用普通模式时,每个请求/应答客户和服务器都要建立一个连接,完成之后立即断开连接

Keep-alive模式

使用“keep-alive”模式(持久连接/连接重用)时,keep-alive功能使客户端到服务器端的连接持续有效,当出现对服务器的后继请求时,Keep-alive功能避免了建立或者重新连接 1.1+支持

管线化

在使用持久连接的情况下,某个连接上消息的传递类似于:

请求1->响应1->请求2->响应2->请求3->响应3

某个连接上的消息变成了

请求1->请求2->请求3->响应1->响应2->响应3

特点

管线化机制通过持久连接完成,仅http/1.1支持

只有get和head请求可以进行管线化,post有所限制

初次创建连接时不应启动管线化机制,因为服务器不一定支持http/1.1版本的协议

管线化不会影响响应到来的顺序,响应返回的顺序并未改变

http/1.1要求服务端支持管线化,但并不要求服务器端也对响应进行管线化处理,只是要求对于管线化的请求不失败

chrome和firefox默认未开启管线化支持

数据类型转换

发表于 2018-09-04 | 更新于 2018-09-06 | 分类于 前端

类型转换

JS没有严格的类型

数据类型

原始类型

Boolean Null Undefined Number String Symbol

对象

Object

显式类型转换

Number函数

原始类型转换

数值 转换后还是原来的值

字符串 如果可以被解析为数值,则转换为相应的数值,否则为NaN,空字符串为0

布尔值 true为1,false为0

undefined NaN

null 0

对象类型转换

先调用对象自身的valueOf方法若返回原始类型的值(数值、字符串、布尔),则使用Number方法,不再进行后续步骤

若返回复合类型,调用自身toString方法,若范围原始类型, 使用Number

若toString返回复合类型 报错

String函数

原始类型转换

数值 转为相应的字符串

字符串 转换为原来的值

布尔 true为’true’ false为’false’

null ‘null’

对象类型转换

先调用toString方法,如果toString方法返回原始类型的值,对该值使用String方法,不再进行以下步骤

如果返回复合类型,调用valueOf方法,如果valueOf返回原始类型的值,对该值使用Sring方法,不再进行以下步骤

如果valueOf返回复合类型,报错

Boolean函数

undifined null -0 +0 NaN ‘’ : false

隐式类型转换

四则运算

判断语句

Native调用

常见题目

[]+[]

[]+{}

{}+[]

{}+{}

true+true

1+{a:1}

chrome与firefox解释器不一样

DOM事件

发表于 2018-09-01 | 分类于 前端

DOM事件类

基本概念

DOM事件的级别

DOM0: element.onclick=function(){}

DOM2: element.addEventListener('click', function(){}, false)

DOM3: element.addEventListener('keyup', function(){}, false)

没有DOM1的原因:因为DOM1制定标准的时候没有设计跟事件相关的内容,但是不代表DOM1不存在

true:捕获时触发

false:冒泡时触发

DOM事件模型

捕获:从上至下

冒泡:从下至上

DOM事件流

捕获 -> 目标阶段 -> 冒泡

描述DOM事件流捕获的具体流程

捕获: window -> document -> html -> body -> … -> 目标元素

冒泡: 反序

JS获取html: document.documentElement

JS获取body: document.body

Event对象的常见应用

阻止默认事件: event.preventDefault()

阻止冒泡事件: event.stopProgagation()

按钮绑定2个click事件A、B,A点击后不触发B,在A的响应函数添加即可阻止B的执行: event.stopImmediatePropagation()

当前绑定的事件,父级元素: event.currentTarget

当前被点击的元素,IE早起没有: event.target

自定义事件

var eve = new Event('custome');
ev.addEventListener('custome', function(){
    console.log('custome')
});
ev.dispatchEvent(eve);

Event:只能指定事件名,不能添加数据;

CustomEvent:除了可以指定事件名,还可后面跟object来做指定自定义参数

源码

event.html

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Event</title>
</head>
<body>
<div id="ev">
    <style>
        #ev{
            width: 300px;
            height: 100px;
            background: red;
            color: #fff;
            text-align: center;
            line-height: 100px;
        }
    </style>
    目标元素
</div>
<script type="text/javascript">
    var ev=document.getElementById('ev');

    //响应顺序与定义顺序无关
    ev.addEventListener('click', function() {
        /* Act on the event */
        console.log('ev capture');
    }, true);

    window.addEventListener('click', function() {
        /* Act on the event */
        console.log('window capture');
    }, true);

    document.addEventListener('click', function() {
        /* Act on the event */
        console.log('document capture');
    }, true);

    document.documentElement.addEventListener('click', function() {
        /* Act on the event */
        console.log('html cature');
    }, true);

    document.body.addEventListener('click',function() {
        /* Act on the event */
        console.log('body cature');
    }, true);

    //自定义事件
    var eve = new Event('test');
    ev.addEventListener('test', function() {
        console.log('test dispatch');
    })

    //ev.dispatchEvent(eve);

    setTimeout(function() {
        ev.dispatchEvent(eve);
    }, 1000);//延时1秒后输出

</script>
</body>
</html>

CSS盒模型

发表于 2018-09-01 | 分类于 前端

CSS盒模型

题目:对CSS盒模型的认识

分析

基本概念

标准模型+IE模型

区别

标准模型(浏览器默认):width不计算padding和border

IE模型:width计算padding和border

CSS如何设置这两种模型

标准模型: box-sizing: content-box;

IE模型: box-sizing: border-box;

JS如何设置获取盒模型对应的宽和高

只能获取内联高: dom.style.width/height

浏览器渲染之后的取值,仅IE支持: dom.currentStyle.height

浏览器渲染之后的取值,兼容性较好: window.getComputedStyle(dom).width/height

根据窗口视图获取宽高: dom.getBoundingClientRect().width/height/left/top

实例题(根据盒模型解释边距重叠)

边距重叠的三种情况:父子;兄弟;空元素(兄弟与空元素一样,取最大值)

BFC(边距重叠解决方案)

BFC基本概念

BFC:块级格式化上下文

IFC:内联元素格式化上下文

BFC原理/渲染规则

1.BFC的垂直方向发生重叠

2.BFC的区域不会与浮动元素发生边距重叠

3.BFC在页面上是独立的容器,外/里不会互相影响

4.浮动元素参与BFC计算高度

创建BFC

1.float值不为none

2.overflow的值不为visible

3.display的值为table-cell,table-caption,inline-block中的任何一个

4.position的值不为relative和static(position的默认值)

应用场景

解决垂直方向的边距重叠

清除浮动

不与浮动元素重叠

源码

box.html

<!DOCTYPE html>
<html lang="en">
<head>
   <meta charset="UTF-8">
   <title>CSS盒模型</title>
   <style media="screen">
   html *{
           padding: 0;
      margin: 0;
   }
    </style>
</head>
<body>

<!--overflow影响height-->
<section id="sec">
    <style media="screen">
        #sec{
            background: #f00;
            /*overflow影响height*/        
            /*overflow: hidden;*/
        }
        .child{
            height:100px;
            margin-top: 10px;
            background: yellow;
        }
    </style>
    <article class="child"></article>
</section>


<!--BFC垂直方向边距重叠-->
<section id="margin">
    <style>
        #margin{
            background: pink;
            overflow: hidden;
        }
        #margin>p{
            margin: 5px auto 25px;
            background: red;
        }        
    </style>
    <p>1</p>
    <div style="overflow:hidden">
        <p>2</p>
    </div>
    <p>3</p>
</section>

<!-- BFC不与float重叠 -->
<section id="layout">
    <style media="screen">
        #layout{
            background: red;
        }
        #layout .left{
            float: left;
            width: 100px;
            height: 100px;
            background: pink;
        }
        #layout .right{
            height: 110px;
            background: #ccc;
            overflow: auto;
        }
    </style>
    <div class="left"></div>
    <div class="right"></div>
</section>

<!-- BFC子元素即使是float,也会参与高度计算/清除浮动 -->
<section id="float">
    <style media="screen">
        #float{
            background: red;
            /*overflow: auto;*/
            float: left;
        }
        #float .float{
            float: left;
            font-size: 30px;
        }
    </style>
    <div class="float">我是浮动元素</div>
</section>

</body>
</html>

页面布局

发表于 2018-09-01 | 分类于 前端

页面布局

题目:假设高度已知,请写出三栏布局,其中左/右栏宽度各位300px,中间自适应。

分析:5种布局方案

  1. 浮动定位: float
  2. 绝对定位: position: absolute;
  3. 弹性/flex布局:(移动端开发)display: flex;
    http://www.ruanyifeng.com/blog/2015/07/flex-grammar.html
  4. 表格/table布局: display: table; -> display: table-cell;
  5. 网格/grid布局:(下一代css3)

延伸

1.5种方案的优缺点

浮动

缺点:脱离文档流,需要清理浮动以及出具好浮动周边的关系

优点:兼容性好

绝对

缺点:脱离文档流,可适用性较差

优点:快捷

flex

缺点:兼容性较差

优点:css3主要解决浮动和绝对两种布局的缺点,比较完美,用于移动端

table

缺点:操作繁琐,对seo不友好

优点:兼容性好,支持ie8,flex解决不了的可以用table布局

grid

优点:代码量少,新技术,使布局不再是模拟网格布局,可以做更多复杂的事情

2.未知高度下,这5种方案哪些方案不适用

flex和table布局适用

float

原理:遮挡,创建bfc

3.兼容性,最优的解决方案(从业务考虑)

源码

interview.html

<!DOCTYPE html>
<html lang="en">
<head>
   <meta charset="UTF-8">
   <title>Layout</title>
   <style media="screen">
   html *{
      padding: 0;
      margin: 0;
   }
   .layout{
      margin-top: 20px;
   }
   .layout article div{
      min-height: 100px;
   }
</style>
</head>
<body>

<!--浮动布局-->
<section class="layout float">
    <style media="screen">
        .layout.float .left{
            float: left;
            width: 300px;
            background: red;
        }
        .layout.float .right{
            float: right;
            width: 300px;
            background: blue;
        }
        .layout.float .center{
            background: yellow;
        }
    </style>
    <article class="left-right-center">
        <div class="left"></div>
        <div class="right"></div>
        <div class="center">
            <h2>浮动解决方案</h2>
            1.这是三栏布局中间部分
            2.这是三栏布局中间部分
        </div>
    </article>    
</section>

<!--flex布局-->
<section class="layout flexbox">
    <style media="screen">
        .layout.flexbox .left-center-right{
            display: flex;
        }
        .layout.flexbox .left{
            width: 300px;
            background: red;
        }
        .layout.flexbox .center{
            flex: 1;
            background: yellow;
        }
        .layout.flexbox .right{
            width: 300px;
            background: blue;
        }
    </style>
    <article class="left-center-right">
        <div class="left"></div>
        <div class="center">
            <h2>flexbox方案</h2>
            1.这是三栏布局flexbox中间部分
            2.这是三栏布局flexbox中间部分
        </div>
        <div class="right"></div>
    </article>
</section>

<!--table布局-->
<section class="layout table">
    <style media="screen">
        .layout.table .left-center-right{
            width: 100%;
            display: table;
            height: 100px;
        }
        .layout.table .left-center-right>div{
            display: table-cell;
        }
        .layout.table .left{
            width: 300px;
            background: red;
        }
        .layout.table .center{
            background: yellow;
        }
        .layout.table .right{
            width: 300px;
            background: blue;
        }
    </style>
    <article class="left-center-right">
        <div class="left"></div>
        <div class="center">
            <h2>表格布局方案</h2>
            1.这是三栏布局表格布局中间部分
            2.这是三栏布局表格布局中间部分
        </div>
        <div class="right"></div>
    </article>
</section>

<!--grid布局-->
<section class="layout grid">
    <style media="screen">
        .layout.grid .left-center-right{
            display: grid;
            width: 100%;
            grid-template-rows: 100px;
            grid-template-columns: 300px auto 300px;
        }
        .layout.grid .left{
            background: red;
        }
        .layout.grid .center{
            background: yellow;
        }
        .layout.grid .right{
            background: blue;
        }
    </style>
    <article class="left-center-right">
        <div class="left"></div>
        <div class="center">
            <h2>网格布局方案</h2>
            1.这是三栏布局网格布局中间部分
            2.这是三栏布局网格布局中间部分
        </div>
        <div class="right"></div>
    </article>
</section>

<!--绝对布局-->
<section class="layout absolute">
    <style media="screen">
        .layout.absolute .left-center-right>div{
            position: absolute;
        }
        .layout.absolute .left{
            left: 0;
            width: 300px;
            background: red;
        }
        .layout.absolute .right{
            right:0;
            width: 300px;
            background: blue;
        }
        .layout.absolute .center{
            left:300px;
            right: 300px;
            background: yellow;
        }
    </style>
    <article class="left-center-right">
        <div class="left"></div>
        <div class="center">
            <h2>绝对定位方案</h2>
            1.这是三栏布局绝对定位中间部分
            2.这是三栏布局绝对定位中间部分
        </div>
        <div class="right"></div>
    </article>
</section>

</body>
</html>

总结

语义化掌握到位

页面布局理解深刻

CSS基础知识扎实

思维灵活且积极上进

代码书写规范

举一反三

三栏布局

左右宽度固定,中间自适应

上下高度固定,中间自适应

两栏布局

左宽度固定,右自适应

右宽度固定,左自适应

上宽度固定,下自适应

下宽度固定,上自适应

123

minn

25 日志
1 分类
13 标签
© 2018 minn
由 Hexo 强力驱动 v3.7.1
|
主题 — NexT.Pisces v6.3.0