前端入门者,请~

本文是结合《Before Coding》(来自:Gitbook)读书总结和自己的小Demo整合而成。


0. 概述

本文的架构是由“D-D-P”三个部分组成——开发(Develop),设计(Design),产品(Product)。

开发部分主要从语言、平台、工具这三个层面进行讲解。

语言:强类型(Java、Swift、Python 类)、弱类型(JavaScript 类);
平台:平台会讲解时下比较火的四大平台的开发流程——Android应用、iOS应用、Web开发(HTML5/Web App)、微信开发。
工具:一些IDE、开发工具、代码管理工具等。 (工欲善其事必先利其器

1. HTML & CSS

工具推荐 (Tools):

Sublime TextAtomVisual Studio CodeEditPlusNodepad++WebStormDreamWeaver。其中,前面5款是轻量级的,只有几M大小,后面两款是IDE级的。

  • **Sublime Text ** 具有漂亮的用户界面和强大的功能,例如代码缩略图,Python的插件,代码段等。还可自定义键绑定,菜单和工具栏。Sublime Text 的主要功能包括:拼写检查,书签,完整的 Python API , Goto 功能,即时项目切换,多选择,多窗口等等。Sublime Text 是一个跨平台的编辑器,同时支持Windows、Linux、Mac OS X等操作系统。
    最最关键的是,它是免费的!而且拥有强大的插件库。
    下载地址:https://www.sublimetext.com/3
    Sublime Text 有哪些使用技巧? - 知乎
    Sublime Text

HTML:以下表格列出了 HTML head 元素下的所有标签和功能:

标签 描述
<head> 定义了文档的信息
<title> 定义了文档的标题
<base> 定义了页面链接标签的默认链接地址
<link> 定义了一个文档和外部资源之间的关系
<meta> 定义了HTML文档中的元数据
<script> 定义了客户端的脚本文件
<style> 定义了HTML文档的样式文件

CSS :

CSS 是编写页面样式的一种语言。用 HTML 写好后的各个元素长什么样子,都是用 CSS 来完成的。比如:大小,边框,背景,颜色,透明度,定位等等。

  • 使用CSS有三种方式
  • 内联样式
<div style="width:100px; height:100px; border:1px solid lightblue;">I am a DIV</div>
  • 内部引入
<head>
    .divStyle{
       width:100px;
       height:100px;
       border:1px solid lightblue;
}
</head>
<body>
       <div class = "divStyle">I am a DIV</div>
</body>
  • 外部引入
<head>
        <link rel="stylesheet" href="style.css">
</head>
<body>
        <div class = "divStyle">I am a DIV</div>
</body>
/*在style.css中定义样式*/
.divStyle{
       width:100px;
       height:100px;
       border:1px solid lightblue;
}
  • CSS 的优先级
    css 是存在优先级的,当我们给一个元素定义多个css样式时怎么办?这时浏览器就会按照最高优先级的css进行渲染。

三种方式中,内联是最高级别的,而内部引入外部引入是平级的,平级的css样式,后边的覆盖前边的。当然,还可以人为强制给最高优先级,这时就需要加 !important 来实现了。

  • 推荐一个好玩的网站

禅意花园:一个很棒的Css参考网站,1个HTML文件,用几百个Css文件渲染,从而展示出不同的风格,也证明了Css的强大。

2. 计算机网络了解

当你在浏览器里请求一个网址时会发生什么?(以去商店购物为例)

  1. 浏览器在域名系统服务器上找出存放网页的服务器的实际地址(找出商店的位置)。
  2. 浏览器发送 HTTP 请求信息到服务器来请拷贝一份网页到客户端(你走到商店并下订单)。这条消息,包括其他所有在客户端和服务器之间传递的数据都是通过互联网使用 TCP/IP 协议传输的。
  3. 服务器同意客户端的请求后,会返回一个“200 OK”信息,意味着“你可以查看这个网页,给你~”,然后开始将网页的文件以数据包的形式传输到浏览器(商店给你商品,你将商品带回家)。
  4. 浏览器将数据包聚集成完整的网页然后将网页呈现给你(商品到了你的门口 —— 新东西,好棒!)。

URI、URL与URN

  • URI:Uniform Resource Identifier,统一资源标识符;
  • *** URL:Uniform Resource Locator,统一资源定位符***;
  • URN:Uniform Resource Name,统一资源名称。

URL 与 URN 是 URI 的子集,它们之间的关系如下图。


URI、URL与URN
  • 协议(Protocol): http: 是协议部分,表示浏览器使用 HTTP 协议对 URL 进行处理。
    当然还有其他的协议,如mailto:// 代表的是使用邮件客户端打开,ftp:// 则是使用 FTP 协议
  • 域名(Domain Name): www.example.com 是一个域名,也可以使用 IP 地址。
    浏览器直接指向域名所在的 Web 服务器。
  • 端口(Port): :80 是端口。它表示用于访问 Web 服务器上的“gate”
    通常如果 Web 服务器使用 HTTP 协议,端口可以省略(HTTP 默认 80 端口,HTTPS 默认 443 端口)。
  • 文件路径(Path to the file): /path/to/myfile.html 是 Web 服务器上的资源路径。
    在 Web 的早期,一个像这样的路径表示 Web 服务器上的物理文件位置。如今,它主要是一个抽象的Web服务器处理,没有任何物理现实。
  • 参数(Parameters): ?key1=value1&key2=value2 提供 Web 服务器的额外参数。
    这些参数是 & 分隔的** 键/值对 **的列表。在返回资源之前,Web 服务器可以使用这些参数做额外的工作。每个 Web 服务器都有自己的有关参数的规则,而唯一可靠的方法来知道一个特定的 Web 服务器是否处理参数是通过询问 Web 服务器所有者。
  • 锚点(Anchor): #SomewhereInTheDocument 叫做锚。
    它可以标记出以获取资源中的子资源,也就是该文档的某一个位置。

3. JavaScript 简介

JavaScript 简介

JavaScript 是一门跨平台、面向对象的轻量级脚本语言。 在主机环境中, JavaScript 能够通过连接环境对象而实现可控制编译。

JavaScript 内置了一个包含一系列对象的标准库,比如数组、日期、数学和一个语言元素核心集合包括操作符,流程控制符以及语句等。JavaScript 的核心部分可以通过组合已有语言核心对象来扩展语言以适应不同用途,例如:

  • 客户端的 JavaScript 通过提供控制浏览器及其文档对象模型(DOM)的对象来扩展语言核心。例如:客户端版本直接支持应用将元素放在在HTML表单中并且支持响应用户事件比如鼠标点击、表单提交和页面导航。
  • 服务端的 JavaScript 则通过提供有关在服务器上运行 JavaScript 的对象来可扩展语言核心。例如:服务端版本直接支持应用和数据库通信,提供应用不同调用间的信息连续性,或者在服务器上执行文件操作。

服务端的 JavaScript 通常使用 **Node.js **技术。Node.js 是一个基于 Chrome V8 引擎的 JavaScript 运行环境。Node.js 使用了一个事件驱动、非阻塞式 I/O 的模型,使其轻量又高效。Node.js 的包管理器 npm,是全球最大的开源库生态系统。


JavaScript 和 Java

就像** “雷峰塔” “雷锋” 的关系, “老婆饼” “老婆” **的关系。

JavaScript 和 Java 有一些共性但是在另一些方面有着根本性区别。JavaScript 名称上酷似 Java,但是并没有Java 的静态类型和强类型检查特性。

与 Java 通过声明式构建类的编译时系统不同,JavaScript 采用基于少量的数据类型如数字、布尔、字符串值的运行时系统。JavaScript 拥有基于原型的对象模型提供的动态继承,也就是说,独立对象的继承是可以改变的。 JavaScript 支持匿名函数,函数也可以作为对象的属性执行。

与 Java 相比,Javascript 是一门形式自由的语言。你不必声明所有的变量,类和方法。你不必关心方法是否是 共有、私有或者受保护的,也不需要实现接口。无需显式指定变量、参数、方法返回值的数据类型。

Java 是基于类的编程语言,设计的初衷就是为了快速执行和类型安全的。类型安全,举例来说,你不能将一个Java 整数变量转化为一个对象引用,或者由J ava 字节码访问专有存储器。Java 基于类的模型,意味着程序包含专有的类及其方法。Java 的类继承和强类型要求紧耦合的对象层级结构。这些要求使得 Java 编程比 JavaScript 要复杂的多。

相比之下,JavaScript 语句精简、拥有动态类型,为更多开发者提供了一种语法简单、内置功能强大以及用最小需求创建对象的编程工具。

  • 具体对比如下表:
JavaScript Java
面向对象。不区分对象类型。通过原型机制继承,任何对象的属性和方法均可以被动态添加。 基于类系统。分为类和实例,通过类层级的定义实现继承。不能动态增加对象或类的属性或方法。
变量类型不需要提前声明(动态类型)。 变量类型必须提前声明(静态类型)。
所有对象均为实例。 类和实例是不同的事物。
通过构造器函数来定义和创建一组对象。 通过类定义来定义类;通过构造器方法来实例化类。
通过 new 操作符创建单个对象。 相同。
指定一个对象作为原型并且与构造函数一起构建对象的层级结构 通过类定义来定义现存类的子类,从而构建对象的层级结构。
遵循原型链继承属性。 遵循类链继承属性。
构造器函数或原型指定初始的属性集。允许动态地向单个的对象或者整个对象集中添加或移除属性。 类定义指定类的所有实例的所有属性。无法在运行时动态添加属性。

JS 语法规则:

  • ** 变量(var / let)、常量(const)、变量的作用域;**
  • 数据类型
    JavaScript * 语言可以识别下面 7 种不同类型的值:
    其中六种是
    原型*的数据类型:
  • Boolean. 布尔值,true 和 false.
  • Null. 一个表明 null 值的特殊关键字。 JavaScript 是大小写敏感的,因此 null 与 Null、NULL或其他变量完全不同。
  • Undefined. 变量未定义时的属性。
  • Number. 表示数字,例如: 42 或者 3.14159。
  • String. 表示字符串,例如:"Howdy"。
  • Symbol . 一种数据类型,它的实例是唯一且不可改变的。
    以及 Object 对象。
  • 数据类型的转换
    举例:字符串转换为数字
    有一些** 有趣的方法 **可以将字符串转换为对应的数字。
  • parseInt()parseFloat(), parseInt 仅能够返回整数,所以使用它会丢失小数部分。另外,调用 parseInt 时最好总是带上进制参数,这个参数用于指定使用哪一种数制。
  • 单目加法运算符 将字符串转换为数字的另一种方法是使用单目加法运算符。
"1.1" + "1.1" = "1.11.1" 
(+"1.1") + (+"1.1") = 2.2 // 注:加入括号为清楚起见,不是必需的。
  • 运算符
    JavaScript 拥有 一元二元 运算符, 和一个特殊的** 三元 **运算符(条件运算符)。
  • 复合赋值运算符(表格整理,便于直观地查询)

|名字|速记操作|等同于|
| :---: | :---: | :---: |
|赋值|x = y|x = y|
|加法赋值 |x + = y |x = x + y|
|减法赋值 |x - = y |x = x - y|
|乘法赋值 |x * = y |x = x * y|
|除法赋值 |x / = y |x = x / y|
|求余赋值 |x % = y |x = x % y|
|求幂赋值 |x ** = y |x = x ** y|
|左移位赋值|x << = y |x = x << y|
|右移位赋值 |x >> = y |x = x >> y|
|无符号右移位赋值| x >>> = y |x = x >>> y|
|按位与赋值 |x & = y |x = x & y|
|按位异或赋值 |x ^ = y |x = x ^ y|
|按位或赋值 |x | y |x = x | y |

    • 比较运算符
      等于(==);
      不等于(!=);
      全等于(===);
      不全等于(!==);
      大于(>);
      大于等于(>=);
      小于(<);
      小于等于(<=).
  • 位运算符
    按位与:a & b
    按位或:a | b
    按位异或:a ^ b
    按位反:~a
    左移:a << b
    右移:a >> b
    无符号右移:a >>> b
  • 逻辑运算符
    与(&&) ; 或(| |) ; 非(!)。
    与: 全真才真,一假则假。 var result = "Cat" && "Dog"; // returns Dog
    或: 全假才假,一真则真。 var result = "Cat" || "Dog"; // returns Cat
    非: 真变假,假变真。
  • 条件运算符(三目运算符)
var result = 3 >2 ? console.log("This is True") : console.log("This is False");

  • ** 数组 (Array) **
  • ***创建数组 ***
    创建数组有三种方式,语法如下:
[element0, element1, ..., elementN]    //直接创建 
new Array(element0, element1[, ...[, elementN]])  //通过 new 来创建 
new Array(arrayLength)   //arrayLength 为数组长度
  • 访问数组
    JavaScript 数组的索引值(index)从0开始,即数组第一个元素的索引值为0。最后一个元素的索引值等于该数组的长度减1(即 Array.length -1)。
var Array = [0,1,2,3,4,...,Array.length-1];
var element1 = Array[0];  //数组的第一个元素
var element2 = Array[1];  //数组的第二个元素
... ...
var lastElement = Array[Array.length-1];  //以此类推,数组的最后一个元素的索引值(下标)是Array.length-1.
  • 获取数组的长度
    看过上边的示例,应该可以猜测到数组的长度就是用 length 来获取的。
    JavaScript array 的 length 属性和其数字下标是有关系的。几个内置数组的方法 (例如, joinsliceindexOf等) 被调用的时候会使用到 length 属性。 有些别的方法 (例如,pushsplice 等) 会改变 array 的 length 属性。
var fruits = [];
fruits.push('banana', 'apple', 'peach');
console.log(fruits.length); // 3

当你在 array 上使用一个合法的数组下标,而且该下标超出了当前数组的大小的时候,引擎会根据其值自动更新 array 的 length 属性:

fruits[5] = 'mango';
console.log(fruits[5]); // 'mango'
console.log(fruits.length); //名为fruits的数组的长度为6

同样的,减小 array 的 length 属性会删掉超出的元素:

fruits.length = 2;
console.log(fruits.length); // 2
  • 一起来做个小练习吧(此刻我在想诛仙,在想碧瑶,所以就拿这个来做Demo啦)
    1. 创建一个诛仙人物名的数组
  var zhuXian = ['zhangXiaoFan','biYao','linJingYu','luXueQi','daoXuan','tianBuYi','cangSong'];
  1. 获取一下这个数组的长度
  var length = zhuXian.length; // 7 个人
  1. 找到数组的第一个,最后一个是谁?碧瑶在哪里?
var first = zhuXian[0];  //小凡,你是第一个
var last = zhuXian[zhuXian.length-1];  //最后一个竟然是苍松道人
var Yao = zhuXian.indexOf("biYao");  // 1, 原来碧瑶在第二个位置
  1. 遍历一下数组,和每个人见个面
//forEach用来遍历,()内是对遍历到的每个元素执行的函数  
zhuXian.forEach(function (item, index) { 
  console.log(item, index); 
  });
/*  Output:
zhangXiaoFan  0
biYao         1
 linJingYu     2
luXueQi       3
daoXuan       4
tianBuYi      5
cangSong      6
*/
  1. 添加一个元素到数组的末尾push
var zhuXian_add = zhuXian.push('tianLingEr');
// zhuXian : ["zhangXiaoFan", "biYao", "linJingYu", "luXueQi", "daoXuan", "tianBuYi", "cangSong", "tianLingEr"]
// zhuXian_add : 8.
  1. 删除数组末尾的元素pop
var zhuXian_remove = zhuXian.pop();
// zhuXian : ['zhangXiaoFan','biYao','linJingYu','luXueQi','daoXuan','tianBuYi','cangSong'];
// zhuXian_remove : "tianLingEr".
  1. 删除数组前面的元素shift
var zhuXian_DelFirst = zhuXian.shift();
// zhuXian:["biYao", "linJingYu", "luXueQi", "daoXuan", "tianBuYi", "cangSong"]
// zhuXian_DelFirst : "zhangXiaoFan".
  1. 添加到数组的前面unshift
var zhuXian_unshift = zhuXian.unshift("xiaoFan");
// zhuXian:["xiaoFan", "biYao", "linJingYu", "luXueQi", "daoXuan", "tianBuYi", "cangSong"]
// zhuXian_unshift : 7
  1. 通过索引删除或替换某个元素splice
// Array.splice(index,howMany,substitution)
// 从数组的索引值为index的那个元素开始,howMany个元素都被substitution替换。substitution可以是多个,用逗号隔开。
var zhuXian_position = zhuXian.splice(4,1);  //删掉第四个元素开始的第一个元素,即第四个("daoXuan")自己。
// zhuXian:["xiaoFan", "biYao", "linJingYu", "luXueQi", "tianBuYi", "cangSong"] 
// zhuXian_position : ["daoXuan"]
  1. 复制一个数组slice
var zhuXian_copy = zhuXian.slice();
// zhuXian:["xiaoFan", "biYao", "linJingYu", "luXueQi", "tianBuYi", "cangSong"] 
// zhuXian_copy :["xiaoFan", "biYao", "linJingYu", "luXueQi", "tianBuYi", "cangSong"] 

  • 条件判断语句
  • if...else
if(判断条件){
          if 为 true 时执行的语句        
}else{
          执行情况为 else 的语句
   }

注意: 下面这些值将被计算出 false
false
undefined
null
0
NaN
空字符串 ("") 当传递给条件语句时,所有其他值,包括所有对象会被计算为 true 。

  • swith...case
    switch 语句允许一个程序求一个表达式的值并且尝试去匹配表达式的值到一个 case label。如果匹配成功,这个程序执行相关的语句。switch 语句如下所示:
switch (expression) {
       case label_1: statements_1
       break; 
       case label_2: statements_2 
       break;
       ... 
       default: statements_def 
       break;
}

可选的 break 语句与每个 case 语句相关联, 保证在匹配的语句被执行后,程序可以跳出 switch 并且继续执行 switch 后面的语句。
如果不写 break , 程序将继续执行 switch 中的语句。


  • 循环语句
    循环语句是一系列反复执行直到符合特定条件的命令。JavaScript 支持fordo whilewhile这些循环语句,还有 Label(label 本身不是一个循环语句,但是经常和这些语句一起使用)。另外,你可以在循环语句中使用breakcontinue语句。
    需要注意的是,还有另一种比较高级的循环语句:for each...in,但它是用来操作对象的。
  • for 语句
// 说明
for (初始化表达式, 判断继续执行的条件, 累计表达式) {
           循环内执行的语句
}
// Demo:使用了前面的示例数组(Array :zhuXian)
for (var i = 0; i < zhuXian.length; i++){
       console.log(zhuXian[i]);
}
  • do...while 语句
    do...while 语句反复直到一个特定条件计算为假。do...while 语句如下所示:
do { 
       i += 1; console.log(i);
} while (i < 5);
// do 循环至少迭代一次,然后重复执行直到 i 不再小于 5。
  • while 语句
    while 语句只要一个特定条件计算为真就执行语句。如下所示:
// 下面的 while 循环只在 n 小于 3 的时候反复执行:
  n = 0;
  x = 0;
  while (n < 3) {
       n++; 
       x += n;
 }

在每次迭代中,循环计数器 n 会增加 1 并会与 x 相加。因此,x 与 n 在每次迭代中的值为:
第一次执行后:n=1,x=1;
第二次执行后:n=2,x=3;
第三次执行后:n=3,x=6。
在第三次执行完成后,条件判断 n<3 不再为 true,循环终止。

注意:要避免死循环;所以对 while 的 条件限制 尤为重要。

** JavaScript 用 for...in, for each...inwith 语句来操作对象。**

  • for...in 循环可以遍历对象中所有可枚举的对象属性(包括对象自有属性和继承的属性)。不过需要注意的是,使用for...in 循环遍历对象属性时,返回的属性会因为各个浏览器不同,导致对象属性遍历的顺序与当初构建时的顺序不同。
var obj = { "name":"lukas" , "job":"FE" , "age":24 }
for (item in obj){
      console.log(item);
}
/* Output:
name
 job
 age
*/
  • ***for each...in ***
    它和 for...in 相似,但是让对象属性的值递回取得,而不是作用于它们的名字。
var sum = 0;
var obj = {num1: 15, num2: 13, num3: 8};
for each (var item in obj) {
      sum += item;
}
console.log(sum); // "36"  = 15+13+8

  • ** 函数 · function **
  • 定义一个函数
    定义函数时,要先写明function这个关键词,然后注明函数名字(js里还有匿名函数,这时就不用函数名了),小括号里放参数,多个参数可以用英文逗号隔开,而大括号里就是函数体,具体的操作和功能都在这里完成。
function add(a,b){
      var result = a + b;
      return result;
}
// 定义完函数后,拿来调用就可以啦
add(3,4);  // 7
  • 函数的递归调用
    所谓递归,就是在函数内自己调用自己,举个栗子,我们用一个函数来实现阶乘的计算。
function factorial(n) {
      n = parseInt(n); // 为了防止有小数输入,这里进行了取整,小数点后的全被截取掉。
      if ((n == 0) || (n == 1))
         return 1;
      else
         return (n * factorial(n - 1));  //我们在这里用了递归,当n > 1时,就再次调用自己
}
// 执行结果
factorial(1);  // 1
factorial(3);  // 6
factorial(3.5);  // 6
  • 函数的作用域
    函数的作用域针对函数内定义的变量。

在函数内定义的变量不能从函数之外的任何地方取得,因为变量仅仅在该函数的域的内部有定义。
相对应的,一个函数可以取得在它的域中定义的任何变量和子函数。
换言之,定义在全局域中的函数可以取得所有定义在全局域中的变量。
而定义在一个函数内部的子函数可以取得定义在其父函数内的,或其父函数取得的任何变量。

变量的作用域无非就是两种:全局变量局部变量
Javascript 语言的特殊之处,就在于函数内部可以直接读取全局变量。
另一方面,由于JS 的 “链式作用域”, 在函数外部自然无法读取函数内的局部变量。
当我们需要从函数外部读取内部的变量时,就需要JS中一个重要的东西** “闭包” **了。

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

推荐阅读更多精彩内容