【前端Vue】05 - [插槽 ,前端模块化开发,webpack]

1. 插槽

1.1 插槽的基本使用

组件的插槽:
  1. 组件的插槽也是为了让我们封装的组件更加具有扩展性。

  2. 让使用者可以决定组件内部的一些内容到底展示什么。

定义插槽的步骤
  1. 在组件中使用一个特殊的元素<slot></slot>可以为组件开启一个插槽。

  2. 该插槽插入什么内容取决于父组件如何使用。

插槽的基本使用
<div id="app">
  <cpn><span>用户</span></cpn>
  <hr>
  <cpn></cpn>
  <hr>
  <cpn>
    <span>更多</span>
    <span>收藏</span>
  </cpn>
</div>

<template id="cpn">
  <div>
    <span>返回</span>
    <h1>我是子组件</h1>
    <slot>
      <!-- 设置一个默认的span -->
      <span>登录</span>
    </slot>
  </div>
</template>

<script src="../../js/vue.js"></script>
  /*
  * 1. 插槽的基本使用 <slot></slot>
  * 2. 插槽的默认值 <slot></slot>
  * 3. 如果有多个值同时放入到插槽中进行替换的时候,一起作为替换元素。
  * */
    const app = new Vue({
        el: '#app',
        data: {},
        components: {
            'cpn': {
                template: '#cpn'
            }
        }
    });

1.2 具名插槽

  1. 定义具名插槽,需要在slot标签中使用 name属性标识该插槽的名称,在使用时在具体的标签中使用 slot属性指定需要替换的插槽的名称。
具名插槽slot
<div id="app">
  <cpn>
    <span slot="center">我是标题</span>
  </cpn>
  <hr>
  <cpn>
    <span slot="left">返回</span>
  </cpn>
  <hr>
  <cpn>
    <span slot="left">返回</span>
    <span slot="center">我是标题</span>
    <span slot="right">用户</span>
  </cpn>
</div>

<template id="cpn">
  <div>
    <slot name="left"><span>左边</span></slot>
    <slot name="center"><span>中间</span></slot>
    <slot name="right"><span>右边</span></slot>
  </div>
</template>

<script src="../../js/vue.js"></script>
const app = new Vue({
        el: '#app',
        data: {},
        components: {
            'cpn': {
                template: '#cpn'
            }
        }
    });

1.3 编译作用域

编译作用域
<div id="app">
  <cpn v-show="isShow"></cpn>
</div>

<template id="cpn">
  <div>
    <h1>我是子组件</h1>
    <span>6666</span>
    <!-- 这里的isShow是子组件中的所以下面是不会显示的 -->
    <span v-show="isShow">我会显示吗?</span>
  </div>
</template>

<script src="../../js/vue.js"></script>
const app = new Vue({
        el: '#app',
        data: {
            isShow: true
        },
        components: {
            'cpn': {
                template: '#cpn',
                data() {
                    return {
                        isShow: false
                    }
                }
            }
        }
    });

1.4 作用域插槽

  1. 当子组件中的数据使用了默认的显示方式,但是父组件希望拿到子组件的数据在其基础上修改显示方式,就可以使用作用域插槽。
作用域插槽的使用步骤
  1. 在子组件中定义一个插槽,可以指定一种默认的显示方式。并在插槽上使用自定义属性绑定一个子组件的数据,传递给父组件。
通过自定义属性传递数据
  1. 父组件使用 template标签 和 slot-scope属性获取来自子组件的数据,在slot-scope中指定一个属性接收数据。
接收数据
<div id="app">
  <!-- 默认以列表方式显示 -->
  <cpn></cpn>
  <!-- 这里希望使用分割符方式进行展示,但是如何拿到子组件的数据? -->
  <cpn>
    <!-- 父组件需要使用 template 获取子组件传递的数据  -->
    <template slot-scope="cpnSlot">
      <span>{{cpnSlot.data.join(' - ')}}</span>
    </template>
  </cpn>

  <cpn>
    <!-- 父组件展示列表时希望使用 * 分割 -->
    <template slot-scope="myData">
      <span>{{myData.data.join(' * ')}}</span>
    </template>
  </cpn>
</div>

<template id="cpn">
  <div>
    <!-- :data="pLanguage" 自定义一个属性将子组件的数据传递给父组件 -->
    <slot :data="pLanguage">
      <ul>
        <!-- 默认是使用列表方式进行展示 -->
        <li v-for="item in pLanguage">{{item}}</li>
      </ul>
    </slot>
  </div>
</template>
<script src="../../js/vue.js"></script>
    /* 作用域插槽是父组件替换插槽的标签,但是内容由子组件提供 */

    /* 问题:如何在父组件中拿到子组件中的数据 */
    const app = new Vue({
        el: '#app',
        data: {},
        components: {
            cpn: {
                template: '#cpn',
                data() {
                    return {
                        pLanguage: ['JavaScript', 'Java', 'C++', 'C#']
                    };
                }
            }
        }
    });

2. 前端模块化开发

2.1 JavaScript原始功能

存在的问题
  1. 客户端需要完成的事情越来越多,代码量也是与日俱增。

  2. 为了应对代码量的剧增,我们通常会将代码组织在多个js文件中,进行维护。

  3. 但是这种维护方式,依然不能避免一些灾难性的问题。

如下面的代码
  1. index.html
<body>
<script src="../js/xiaoming.js"></script>
<script src="../js/xiaohong.js"></script>
<script src="../js/tiancai.js"></script>
</body>
  1. xiaoming.js
// 小明的文件
var name = '小明';

var age = 23;

function sum(a, b) {
    return a + b;
}

var flag = true;

if (flag) {
    console.log(sum(12, 36));
}
  1. xiaohong.js
// 小红的js文件
var name = '小红';

console.log(name);

var flag = false;
  1. tiancai.js
if (flag) {
    console.log('我真是个天才');
}
  1. 上面代码由于调用顺序问题,和变量名重名问题,导致后面的代码修改了前面的变量,出现问题。

2.2 解决方案:匿名函数

  1. 我们可以使用匿名函数来解决方面的重名问题,在 xiaoming.js 文件中。
匿名函数的方式解决变量命名冲突问题

3. webpack

对打包的理解
  1. 理解了webpack可以帮助我们进行模块化,并且处理模块间的各种复杂关系后,打包的概念就非常好理解了。

  2. 就是将webpack中的各种资源模块进行打包合并成一个或多个包(Bundle)。

  3. 并且在打包的过程中,还可以对资源进行处理,比如压缩图片,将scss转成css,将ES6语法转成ES5语法,将TypeScript转成JavaScript等等操作。

3.1 webpack 的介绍和安装

  1. webpack要正常运行必须依赖于nodenode为了可以正常执行很多代码,必须包含各种包。

  2. 查看自己的node版本:

node -v 或者 node --version
  1. 全局安装webpack(这里我先指定版本号3.6.0,因为vue cli2依赖该版本)。
npm install webpack@3.6.0 -g 
  1. 局部安装webpack(后续才需要)。
cd   对应目录

npm install webpack@3.6.0 --save-dev
为什么全局安装后,还需要局部安装呢?
  1. 在终端直接执行webpack命令,使用的全局安装的webpack

  2. 当在package.json中定义了scripts时,其中包含了webpack命令,那么使用的是局部webpack

3.2 webpack 的基本使用

  1. 在项目文件夹下创建 distsrc文件夹。dist文件夹用于存放的是打包完成的文件。src存放的是打包之前的文件。

  2. 场景 : 创建 main.jsmathUtils.jsinfo.js三个文件。在项目下创建 index.html文件。下面分别使用 CommonJs 模块化 和 ES6模块化。最终使用 webpack 打包

  3. main.js 分别导入 info.jsmathUtils.js 的模块。

/* CommonJS的方式 */
const {add, mul} = require('./mathUtils.js');

console.log(add(20, 30));

console.log(mul(100, 10));


/* 使用ES6的方式 */
import {age, height, name} from './info.js';

console.log(name);
console.log(age);
console.log(height);


/*
webpack 打包命令 :
    1. 切换到当前目录 ;

    2. 使用 webpack ./src/main.js ./dist/bundle.js 进行打包;
*/
  1. info.js 使用ES6模块化方式。
export const name = '张三';
export const age = 23;
export const height = 1.88;
  1. mathUtils.js使用CommonJs 模块化方式。
function add(a, b) {
    return a + b;
}

function mul(a, b) {
    return a * b;
}

/* CommonJs的方式 */
module.exports = {
    add,
    mul
};
  1. 使用命令进行打包操作:webpack ./src/main.js ./dist/bundle.js

3.3 webpack.config.js配置和package.json配置

webpack.config.js 文件
  1. 在项目下创建一个 webpack.config.js 的文件,定义打包的对象。
webpack.config.js文件
  1. 上面文件定义完成之后便可以在项目路径下使用 webpack 命令直接打包了。

  2. 初始化 package.json 文件配置命令映射。使用 npm init 命令初始化package.json文件。

webpack命令映射
  1. 如上配置之后可以使用 npm run build打包项目。

  2. 但是此时使用打包的webpack是全局安装的webpack但是在之后可能全局webpack版本和项目使用的webpack版本不一致的情况,此时就需要在项目的目录下自己安装一个本地(局部)webpack。使用命令npm install webpack@3.6.0 --save-devcnpm install webpack@3.6.0 --save-dev 但是不建议使用 cnpm ,我试过可能因为下载太快,我使用 webstorm加载过程中非常卡 。

局部的webpack安装完成之后

3.4 什么是loader?

  1. webpack 可以使用 loader 来预处理文件。这允许你打包除 JavaScript之外的任何静态资源。loader 可以将所有类型的文件转换为 webpack 能够处理的有效模块,然后你就可以利用 webpack 的打包能力,对它们进行处理。本质上,webpack loader 将所有类型的文件,转换为应用程序的依赖图(和最终的 bundle)可以直接引用的模块。

  2. 在我们之前的实例中,我们主要是用webpack来处理我们写的js代码,并且webpack会自动处理js之间相关的依赖,但是,在开发中我们不仅仅有基本的js代码处理,我们也需要加载css、图片,也包括一些高级的将ES6转成ES5代码,将TypeScript转成ES5代码,将scssless转成css,将.jsx.vue文件转成js文件等等。对于webpack本身的能力来说,对于这些转化是不支持的。那怎么办呢?给webpack扩展对应的loader就可以啦。

3.5 loader使用过程:

  1. 步骤一:通过npm安装需要使用的loader

  2. 步骤二:在webpack.config.js中的modules关键字下进行配置。

  3. 大部分loader我们都可以在webpack的中文网中找到。

3.6 使用 css-loader 和 style-loader 的场景

  1. 编写一个样式文件 noemal.css文件,在 main.js(入口文件)中进行使用 require() 引入。
require('./css/normal.css');
  1. 此时如果使用 nom run build 打包的话将会出现下面一个问题。
需要一个合适的loader
  1. 查看官方文档,使用命令安装 css-loader 此时未指定版本默认是最新版本。
npm install --save-dev css-loader
  1. 安装完成之后在webpack.config.js中进行配置:
数组默认从右往左读
  1. 配置完成之后,发现尚未可??? 原来是还缺少了一个loader style-loaderstyle-loader 将模块的导出作为样式添加到 DOM 中。安装 style-loader
npm install style-loader --save-dev
  1. 安装配置完成还有个问题 ??? ,,, (node:58300) UnhandledPromiseRejectionWarning: TypeError: this.getResolve is not a function。 百度一下发现,是我的版本太高了,我按照提示将 package.json下的依赖版本进行修改,重新使用 npm install 对依赖进行安装之后。终于可以了。
修改style-loader 和 css-loader 的版本

3.7 webpack 对 less 文件的处理

  1. 在开发过程中我们大多数时候会使用到less语法,所以 webpack需要提供对 less的支持。

  2. 安装less-loader ,但是 less-loader 需要 less支持。同时需要安装 less

npm install --save-dev less-loader less // 这样安装的是最新版的,后面会出问题 可以后面修改版本或者现在修改版本

npm install --save-dev less-loader@4.1.0 less@4.1.0
  1. 安装完成之后在webpack.config.js中配置less-loader :
            {
                test: /\.less$/,
                use: [{
                    loader: "style-loader" // creates style nodes from JS strings
                }, {
                    loader: "css-loader" // translates CSS into CommonJS
                }, {
                    loader: "less-loader" // compiles Less to CSS
                }]
            }
在webpack.config.js中配置less-loader

3.8 webpack对图片文件的处理案例

  1. 准备两张图片,大小分别一大一小。之后可以设置文件大小一个分界线。

  2. 在样式中设置背景图片:该样式文件已经在main.js中引入,到时候打包将会将样式文件打包为一个模块。

body {
  /*background-color: #f00;*/
  background: url(../images/green-logo.png) no-repeat;
  background-size: cover;
}
body {
  /*background-color: #f00;*/
  background: url(../images/green-logo-mini.png) no-repeat;
  background-size: cover;
}
  1. 使用 npm run build 进行打包,发现需要安装适当的 loader
You may need an appropriate loader to handle this file type.
npm install --save-dev url-loader  
  1. 安装完成之后在 webpack.config.js文件中进行配置:options: {} 中配置的是打包的一些属性。limit 相当于文件大小的分界线,如果超出该分界线是需要file-loader的支持的。
                      {
                test: /\.(png|jpg|gif|jpeg)$/,
                use: [
                    {
                        loader: 'url-loader',
                        options: {
                            /* 当图片小于指定的尺寸的时候回将其转换为base64位的图片 */
                            limit: 10240
                        }
                    }
                ]
            }
配置url-loader

需要file-loader的支持
  1. 安装 file-loader ,npm install --save-dev file-loader
url-loader中options对象的属性 name
  1. name属性:name: 'img/[name].[hash:8].[ext]'

img:文件要打包到的文件夹;
name:获取图片原来的名字,放在该位置;
hash:8:为了防止图片名称冲突,依然使用hash,但是我们只保留8位;
ext:使用图片原来的扩展名。

3.9 babel 对 ES6 语法的处理 babel-loader

未使用babel-loader转换打包,还存在const关键字声明变量。

未使用babel-loader转换打包
  1. 使用babelES6转为 ES5
  1. 安装 babel-loadernpm install --save-dev babel-loader@7 babel-core babel-preset-es2015

  2. web.config.js中配置 babel-loaderexclude 属性用于排除某些文件夹,不对其进行转换。

             {
                test: /\.js$/,
                /* exclude 是排除的意思 */
                /* include 是包含的意思 */
                exclude: /(node_modules|bower_components)/,
                use: {
                    loader: 'babel-loader',
                    options: {
                        presets: ['es2015']
                    }
                }
            }
使用babel-loader转换之后

3.10 webpack配置Vue的过程

  1. 使用命令npm install --save vue安装Vue,在main.js中导入Vue
// 1. 导入 vue
import Vue from 'vue';
  1. 使用Vue输出一段文字。
const app = new Vue({
    el: '#app',
    data: {
        message: 'Hello webpack!'
    }
});
  1. 启动运行时发现出现下面的问题,是因为在Vue打包中有很多的版本其中有两个是 runtime-onlyruntime-compiler
使用runtime-only导致的问题
  1. 解决:在webpack.config.js文件中module同层级下配置如下代码
resolve:{
  alias:{
    'vue$':'vue/dist/vue.esm.js'
  }
}
webpack.config.js下进行配置
Vue打包的两个版本
  1. runtime-only: 代码中,不可以有任何的 template

  2. runtime-compiler: 代码中可以有 template,因为compiler可以用于编译 template

3.11 使用创建Vuetemplateel的关系

template和el的关系
  1. 在前面的Vue实例中,我们定义了el属性,用于和index.html中的#app进行绑定,让Vue实例之后可以管理它其中的内容。

  2. 上面我们将页面中 <div id="app"></div>包裹的代码删除,在main.js中使用template编写相应的模板进行替换。

3.12 Vue的终极使用方案

使用 JS方式文件分离组件
使用JS文件分离模板的方式
  1. 但是使用这种方式还是未将 templatejs代码相分离开。
创建 Vue文件的方式分离组件
  1. 需要提前安装一个loader vue-loadervue-template-compiler
npm install vue-loader vue-template-compiler --save-dev
  1. webpack.config.js中配置vue-loader
          {
                test: /\.vue$/,
                use: {
                    loader: 'vue-loader'
                }
            }
在`webpack.config.js`中配置`vue-loader`
  1. 创建一个 Vue component :
<template>
  <!-- 模板相关 -->
  <div>
    <h2>使用 JS 方式分离 template </h2>
    <h2>{{message}}</h2>
    <button @click="btnClick">点我啊</button>
  </div>
</template>

<script>
    export default {
        name: "app"
        /* js相关 */,
        data() {
            return {
                message: 'Hello webpack! i`m template 666 '
            }
        },
        methods: {
            btnClick() {
                console.log('你点了我');
            }
        }
    };
</script>

<style scoped>
  /* 样式相关 */
  h2 {
    color: #00f !important;
  }
</style>
  1. 注意 vue-loader的版本问题。改为 13.0.0
出现这个错误需要将vue-loader的版本改为 13.0.0
app.js和app.vue的对比

3.13 认识 plugin

为我们的代码添加一个版权声明插件 BannerPlugin
  1. webpack.config.js中配置。
配置webpack.config.js
最终效果
打包html的plugin html-webpack-plugin
这个html文件
安装完成并配置打包
  1. 安装 html-webpack-plugin插件:
npm install html-webpack-plugin --save-dev
  1. 配置插件并指定打包模板:
配置插件并指定打包模板
  1. 可能会出现版本问题 :在package.json中修改版本信息
这就是因为版本太高,需要调整版本
"html-webpack-plugin": "^3.0.0"

npm install 
压缩JS代码 UglifyjsWebpackPlugin
  1. UglifyjsWebpackPlugin , 丑化代码,压缩代码插件。
  1. 安装插件,为开发时插件。
npm install uglifyjs-webpack-plugin@1.1.1 --save-dev
  1. plugins中配置插件 :
配置插件

3.14 使用webpack搭建本地服务器

  1. 安装 webpack-dev-server
npm install --save-dev webpack-dev-server@2.9.3
  1. 配置 devServer
配置完成
  1. 启动有两种方式: 第一种使用在 package.json中的命令的方式,第二种方式使用node_modules中的命令的方式。
在package.json中配置启动webpack-dev-server
// 第一种方式 由于在 package.json中配置了script命令所以可以直接使用如下命令启动 
npm run dev

3.15 webpack 中配置文件的抽离

  1. 创建一个build文件夹,在里面创建 base.config.jsprod.config.jsdev.config.js

  2. 将公共的配置都抽取到 base.config.js中。将开发环境的配置配置到 dev.config.js中 ,将生产环境的配置配置到peod.config.js中。

const path = require('path');
const webpack = require('webpack');
const HtmlWebpackPlugin = require('html-webpack-plugin');

module.exports = {
    entry: './src/main.js',
    output: {
        path: path.resolve(__dirname, '../dist'),
        filename: 'bundle.js',
        /* 有关url的都会加上dist路径 */
        // publicPath: 'dist/'
    },
    module: {
        rules: [
            {
                test: /\.css$/,
                /* css-loader 只负责将css文件进行加载 */
                /* style-loader 负责将样式添加到DOM中 */
                /* loader 从右向左读  */
                use: ['style-loader', 'css-loader']
            },
            {
                test: /\.less$/,
                use: [{
                    loader: "style-loader" // creates style nodes from JS strings
                }, {
                    loader: "css-loader" // translates CSS into CommonJS
                }, {
                    loader: "less-loader" // compiles Less to CSS
                }]
            },
            {
                test: /\.(png|jpg|gif|jpeg)$/,
                use: [
                    {
                        loader: 'url-loader',
                        options: {
                            /* 当图片小于指定的尺寸的时候回将其转换为base64位的图片 */
                            limit: 10240,
                            name: 'img/[name].[hash:8].[ext]'
                        }
                    }
                ]
            },
            {
                test: /\.js$/,
                /* exclude 是排除的意思 */
                /* include 是包含的意思 */
                exclude: /(node_modules|bower_components)/,
                use: {
                    loader: 'babel-loader',
                    options: {
                        presets: ['es2015']
                    }
                }
            },
            {
                test: /\.vue$/,
                use: {
                    loader: 'vue-loader'
                }
            }
        ]
    },
    resolve: {
        alias: {
            'vue$': 'vue/dist/vue.esm.js'
        }
    },
    plugins: [
        new webpack.BannerPlugin('最终版权归我所有!'),
        new HtmlWebpackPlugin({
            template: 'index.html'
        })
    ]
};




  1. 安装合并插件,将他们分别进行合并。
npm install webpack-merge@3.0.0 --save-dev 
  1. base.config.jsprod.config.js合并:
const UglifyJsWebpackPlugin = require('uglifyjs-webpack-plugin');
const webpackMerge = require('webpack-merge');
const baseConfig = require('./base.config')


/* 合并 基本的配置 + 生产时依赖 */
module.exports = webpackMerge(baseConfig, {
    plugins: [
        new UglifyJsWebpackPlugin()
    ]
});
  1. base.config.jsdev.config.js合并:
const webpackMerge = require('webpack-merge');
const baseConfig = require('./base.config')

module.exports = webpackMerge(baseConfig, {
    devServer: {
        contentBase: './dist',
        /* 是否实时进行监听 */
        inline: true
    }
})
  1. 合并完成删除webpack.config.js,此时再使用 npm run dev 或者 npm run build 就会出现找不到命令的问题。

  2. 解决合并文件只有删除webpack.config.js再使用 npm run dev 或者 npm run build 脚本命令出现的问题。修改 package.json

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

推荐阅读更多精彩内容