使用 Node.js 平臺的express開發框架及mongodb搭建一個簡單的博客

首先講下簡單博客功能:

  • 1.編輯內容發布前:


    發布前.png
  • 2.發布后:
    里面的img標簽會成功解析成圖片


    發布后
  • 3.更新界面
    可點擊“更新”鏈接 對之前發布的內容進行更新,這里我就把圖片src給換了

更新界面
  • 4.更新后的頁面
    更新后,我們發現圖片也變了。


    更新后的頁面
  • 5.刪除指定的博客內容

通過這次搭建簡單的博客,我們可以對express框架、模板引擎、路由、數據庫操作及ajax等有進一步的了解。好了,轉入正題:

首先安裝node 這個就不必說了。。。以下指令如無特別說明均在Node.js command prompt(Node.js 命令提示符)完成。

一、express的準備工作

1、安裝express

npm install express-generator -g

2、快速生成項目

express blog

3、進入項目并安裝相關依賴

cd blog && npm install

4、啟動express

npm start

5、在瀏覽器中,打開 http://localhost:3000/ 即可

express安裝成功后

二、mongodb的配置工作

mongodb屬于非關系型數據庫NoSQL(Not Only SQL)。Redis,CouchDB也均屬于非關系型數據庫,而SQL Server,Oracle,MySQL(開源),PostgreSQL(開源) 屬于關系型數據庫SQL (Structured Query Language) 。關于SQL 和 NoSQL 的區別可見 SQL 和 NoSQL 的區別

關系型與非關系型數據庫結構對比

由上表,我們可以看到mongodb是由集合組成,而集合又由文檔組成,文檔又由一組組鍵值對組成,也就是說mongodb最小單位為文檔。而關系型數據庫最小單位為記錄;

非關系型數據庫舉例
關系型數據庫舉例

其他詳見上面介紹的文章或者自行查閱資料。

1、下載與安裝mongodb軟件
由于我的電腦是win7 32位 官網默認給出的最新版不支持,因此我安裝了3.2.4版(32位)
其下載地址為:http://downloads.mongodb.org/win32/mongodb-win32-i386-3.2.4-signed.msi
安裝完后,我的默認安裝地址:C:\Program Files\MongoDB\Server\3.2\bin

2、配置環境變量
配置環境變量,以便在任何目錄下均可使用mongodb,而無需進入到mongodb中bin的目錄。步驟如下:


Paste_Image.png
Paste_Image.png
Paste_Image.png

編輯圖中圈出的path(用戶變量及系統變量均要修改),在

Paste_Image.png

變量值后面加上;C:\Program Files\MongoDB\Server\3.2\bin 也就是你自己的安裝目錄;注意別忘記前面的分號;啦。

3、設置數據存放目錄

在之前新建的blog目錄下再新建data目錄,然后執行:

mongod.exe --dbpath C:\Users\ssd170329\express\blog\data --storageEngine=mmapv1  
//ssd170329記得替換成自己的pc名字

之所以在指令后面加--storageEngine=mmapv1 是因為

在2015/3/17以前,MongoDB只有一個存儲引擎,叫做MMAP,MongoDB3.0的推出使得MongoDB有了兩個引擎:MMAPv1和WiredTiger。
MMAPv1:適應于所有MongoDB版本,MongoDB3.0的默認引擎
WiredTiger:僅支持64位MongoDB

,因此不加會報錯!

設置數據存放目錄這步完成后,會有如下提示:


Paste_Image.png

并且data文件夾里會新出現一些文件及文件夾

data文件夾里新出現的文件及文件夾

4、啟動mongodb
假如我們剛完成數據存放目錄的設置,則該步驟可以省略,否則需要以相同指令啟動mongodb

mongod.exe --dbpath C:\Users\ssd170329\express\blog\data --storageEngine=mmapv1  
//ssd170329記得替換成自己的pc名字

不啟動的話在后面會報錯。

三、數據庫的操作準備知識

上面啟動mongodb后,我們先來熟悉下mongodb數據庫的操作,在數據庫操作之前,我們需要先連接mongodb 連接的指令:mongo 。提示:該指令需要另外開一個Node.js command prompt窗口再輸入!!!前面的指令mongod.exe --dbpath C:\Users\ssd170329\express\blog\data --storageEngine=mmapv1只是啟動mongodb用的,后面我們重新開一個Node.js command prompt窗口是為了可以方便的操作數據庫。

1、數據庫操作
  • a、查看本地有哪些數據庫可以使用show dbs (默認會有個名為test的數據庫)
  • b、查看當前操作的數據庫名db
  • c、新建數據庫use blog (此時我們輸入db時還不會顯示blog,需要進行比如插入文檔等,才會被記錄到本地)
  • d、往blog插入文檔 db.post.insert({"content": "123"})
    此時命令行中會出現 WriteResult({"nInserted" : 1}) ,則表明我們插入數據成功,同時在數據存放目錄里(blog\data)看到新增了 blog.ns 和 blog.0 兩個文件。
  • e、刪除數據庫
    刪除前需要切換到該數據庫,否則會默認刪除test數據庫。刪除的指令db.dropDatabase()
2、集合操作

不同的集合便構成了數據庫,下面針對某個集合來說說集合的相關操作

  • a、查看數據庫里的集合 show collections
    若無,則什么也不顯示,若有則顯示相應的集合名詞及system.indexes
  • b、創建一個名為items的集合db.createCollection('items')
  • c、當然你可以無需向上面那樣特意創建集合,你可以db.items.insert({}), 這樣表示向items集合里插入空文檔,當無items集合時,會自動創建一個items集合
  • d、刪除items集合 db.items.drop()
3、文檔操作

上面講了集合的操作,下面講下其里面的文檔如何操作(增、刪、改、查):

  • a、增-----在post集合中插入一個或多個文檔
    插入單個文檔: db.post.insert({"content":"123"})
    插入多個文檔:db.post.insert([{"content":"456"},{"content":"789"}])
  • b、刪----刪除post集合中的文檔
    db.post.remove({"content","123"})
  • c、改-----修改post集合中的文檔
    db.post.update({"content","456"},{$set{"content","abc"}})
  • d、查----查詢post集合中的文檔
    查詢所有文檔:db.post.find()
    查詢content為abc的文檔:db.post.find({},{"content","abc"})

當然還有很多其他方法,大家可以自行查閱資料。
另外值得一提的是,大家別把數據庫和集合的概念搞錯了,比如本例中show dbs 結果是 blog 、local(或者test),而show collections結果是info 、post、system.indexes , 因此db.blog.find()在此處的用法是錯誤的!而db.post.find()才正確!

Paste_Image.png

四、修改express里的相關文件

express文件解釋.png
1、修改模板引擎

由于express默認的jade模板引擎我們前端使用的不怎么習慣,我們可以改成ejs模板。

  • a、安裝ejs模板引擎 (安裝前記得cd到blog目錄下)
    npm install ejs --save
  • b、修改app.js中的關于模板引擎部分
    在根目錄app.js中修改模板引擎
    修改前,app.js中有這樣一段是關于模板引擎的
// view engine setup
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'jade');

第一句話的意思是 設置模板引擎的路徑在根目錄中的views里,第二句話的意思是,將模板引擎設置為jade的后綴的文件,為了修改成ejs的模板引擎我們需要將上面兩句改為

// view engine setup
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'html');
app.engine('html', require("ejs").__express);
  • c、 修改views文件夾下的文件
    將views文件夾下的jade文件全部刪除,并新增index.html、update.html、error.html 三個文件,
    改三個文件里的內容分別如下:
    index.html
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1.0,minimum-scale=1.0,maximum-scale=1.0,user-scalable=no">
<title><%= title %></title>
<link rel="stylesheet" type="text/css" href="/stylesheets/style.css">
</head>

<body>

    <h3 class=""><%= name %></h3>

</body>

</html>

里面的<%= title %><%= name %> 就是ejs所輸出的標簽(另外補充下:<%= %>輸出標簽,其會原文輸出HTML標簽,而<%- %>輸出標簽,其會被瀏覽器解析后再輸出, 這個就跟innerText與innerHTML的性質差不錯)

update.html

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1.0,minimum-scale=1.0,maximum-scale=1.0,user-scalable=no">
<title><%= title %></title>
<link rel="stylesheet" type="text/css" href="/stylesheets/style.css">
</head>

<body>

    <h3 class=""><%= name %></h3>

</body>

</html>

error.html

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1.0,minimum-scale=1.0,maximum-scale=1.0,user-scalable=no">
<title>錯誤頁</title>
<link rel="stylesheet" type="text/css" href="/stylesheets/style.css">
</head>

<body>

    <div class="content">錯誤!</div>

</body>

</html>
2、設置路由器

以上只是修改了模板引擎相關部分,接下來需要修改路由器部分:
首先刪除route里面的所有js文件,然后新建index.js及update.js (由于error 在app.js里有寫,因此這里就沒新建error.js)

index.js里的代碼:

var express = require('express');
var router = express.Router();

/* GET home page. */
router.get('/', function(req, res, next) {
    res.render('index', { title: '博客首頁', name: '博客'});
});

module.exports = router;

update.js里的代碼

var express = require('express');
var router = express.Router();

/* GET update page. */
router.get('/update', function(req, res, next) {
    res.render('update', { title: '博客更新頁', name: '博客更新'});
});

module.exports = router;

這里各自的路由設置好后,我們還需要對項目入口文件app.js中的路由部分進行修改才能夠正常訪問:
原有app.js中的部分

var routes = require('./routes/index');
var users = require('./routes/users');

...

app.use('/', routes);
app.use('/users', users);

上面修改成

var index = require('./routes/index');
var update = require('./routes/update');

...

app.use('/', index);
app.use('/', update);

接下來我們可以測試下到目前為止的效果:
控制面板cd到 在項目的根目錄里,然后執行npm start
然后瀏覽器打開 http://localhost:3000/http://localhost:3000/update 我們可以看到相應的正確頁面,而如果我們訪問 http://localhost:3000/123http://localhost:3000/qwe 等我們未在路由器里定義的路徑則會返回error的頁面。

3、修改模板

首先將頁面樣式做好:
index.html里新增的代碼

<div class="blog-add">
    <div class="blog-textarea">
        <textarea name="" class="textarea-add" cols="30" rows="10"></textarea>
    </div>
    <p class="blog-action">
        <a class="btn-publish" href="javascript:;">發布</a>
    </p>
</div>

<div class="blog">
    <ul class="blog-list">
        <li class="blog-item">
            <p class="blog-content">你好</p>
            <p class="blog-extra">
                <span class="date">2015-10-10</span>
                <a href="javascript:;" class="delete">刪除</a>
                <a href="javascript:;" class="update">更新</a>
            </p>
        </li>
    </ul>
</div>

update里新增的代碼

<div class="blog-add">
    <div class="blog-textarea">
        <textarea name="" class="textarea-add" cols="30" rows="10"></textarea>
    </div>
    <p class="blog-action">
        <a class="btn-update" href="javascript:;">更新</a>
    </p>
</div>

修改后的css

* {margin: 0;padding: 0;}
body {padding: 50px;font: 14px "Lucida Grande", Helvetica, Arial, sans-serif;}
a {color: #00B7FF;}
li {list-style: none;}
a {text-decoration: none;}

.blog-add .blog-textarea {margin: 20px 0 10px;padding: 10px;border: 1px solid #ccc;}
.blog-add .textarea-add {width: 100%;height: 80px;border: none;resize: none;outline: none;}
.blog-add .blog-action {line-height: 30px;text-align: right;}
.blog-add .blog-action .btn-publish,
.blog-add .blog-action .btn-update {border: 1px solid #00B7FF;padding: 5px 20px;border-radius: 3px;}
.blog-list .blog-item {padding-top: 10px;line-height: 22px;}
.blog-list .blog-item p {padding: 5px 0;word-wrap: break-word;}
.blog-list .blog-item {border-bottom: 1px dotted #ddd;}
.blog-list .blog-extra {overflow: hidden;color: #999;text-align: right;}
.blog-list .blog-extra .date {float: left;}
.blog-list .blog-extra a {border-right: 1px dotted #00B7FF;padding: 0 10px;margin-right: -6px;font-size: 12px;}

記得在public里javascripts目錄下新增jquery.min.js文件。

五、express與mongodb交互

首先梳理下交互的流程:前臺輸入完內容后點擊發布,將內容發送至后臺數據庫保存后,再由后臺從數據庫中讀取數據然后將數據顯示到頁面上。

1、發送數據至后臺

index.html中新增的js代碼:

<script type="text/javascript" src="/javascripts/jquery.min.js"></script>
<script>
$(function() {

    // 發布
    $('.btn-publish').on('click', function() {
        var blogContent = $('.textarea-add').val().trim().replace(/\n/g, '<br/>');

        if (!blogContent) {
            alert('內容不能為空!');
            return;
        }

        var date = new Date(),
            yy = date.getFullYear(),
            MM = date.getMonth() + 1,
            dd = date.getDate(),
            hh = date.getHours(),
            mm = date.getMinutes(),
            ss = date.getSeconds();

        var postData = {
            'content': blogContent,
            'date': yy + '-' + MM + '-' + dd + ' ' + hh + ':' + mm + ':' + ss
        };

        $.ajax({ 
            url: '/',
            type: 'post',
            data: postData,
            success: function(data){
                alert('發布成功!');
                location.href = '/';
            },
            error: function(data){ 
                alert('發布失敗!');
                location.href = 'error';
            }
        }); 

    });

});
</script>
2、后端接收數據,并將數據保存至數據庫

接下來需要用到mongoose,關于它的介紹可看下面:

mongoose 是一個文檔對象模型庫(ODM),它的語法和 mongodb 里的 shell 命令是一樣的。如果你使用過 node.js 直接操作 mongodb,你會發現代碼中會出現很多嵌套、回調以及各種潛在問題。但有了 mongoose,你可以直接在 node.js 里使用 mongoose 自身的語法,不僅代碼簡潔,操作數據方便,而且避免了很多額外的問題。

需要使用mongoose,我們就得安裝它:
npm install mongoose --save

安裝完后,

  • a、在blog/data 目錄下新建mongoose.js,mongoose.js的代碼如下:
var mongoose = require('mongoose');

mongoose.connect('mongodb://localhost/blog');
// 注意!!mongodb://localhost/blog 這里的blog要和你創建的
// 數據庫名稱(不是集合名稱)一樣,而不是指文件的路徑,它跟
// 文件路徑沒有半毛錢的關系。今天被坑到了。。。。

var blogSchema = new mongoose.Schema({
    content: {type: String, unique:true}, // unique 保證數據的唯一,但有時候不管用
    date: String
}, {collection: 'post'});

var post = mongoose.model('post', blogSchema);

module.exports = post;
  • b、在根目錄app.js里的 var app = express();下一行新增如下一行代碼:global.post = require('./data/mongoose');
  • c、由于之前我們使用ajax發送數據是在index.html中post的,因此需要在index.js中處理post請求,下面在index.js中新增代碼
/* POST home page. */
router.post('/', function(req, res) { 
    var content = req.body.content;
    var date = req.body.date;

    if (content && date) {
        var newPost = new post({
            content: content,
            date: date
        });

        newPost.save(function (err) {
            if (err) {
                console.error(err);
                return;
            }
            // newPost is saved!
            console.log('保存成功!');
            res.send(200);
        });
    }
});

接下來,我們npm start重啟服務器,然后在頁面的編輯區域隨便輸什么點擊發布鏈接后 在命令行輸入 db.post.find()后,我們可以在命令行中看到你之前輸入的內容。但是此時頁面并沒有解析出你剛剛輸入的內容,只是數據庫里存儲了你輸入的內容,接下來我們需要從數據庫中讀取該內容并發送至頁面上。

3、讀取數據庫中的數據并將其展示到頁面上
  • a、首先我們將index.js中的以下內容
/* GET home page. */
router.get('/', function(req, res, next) {
    res.render('index', { title: '博客首頁', name: '博客'});
});

修改為

/* GET home page. */
router.get('/', function(req, res, next) {

    post.find({}, function(err, docs) {
        if (err) {
            console.error(err);
            return;
        }
        // docs 是包含了符合條件的多個文檔的一個數組
        // console.log(docs);
        res.render('index', { title: '博客首頁', name: '博客', content: docs.reverse()}); //reverse的目的是讓最新的數據在前面
    });

});
  • b、其次我們將index.html中的以下部分
<div class="blog">
    <ul class="blog-list">
        <li class="blog-item">
            <p class="blog-content">你好</p>
            <p class="blog-extra">
                <span class="date">2015-10-10</span>
                <a href="javascript:;" class="delete">刪除</a>
                <a href="javascript:;" class="update">更新</a>
            </p>
        </li>
    </ul>
</div>

修改為:

<div class="blog">
    <ul class="blog-list">
        <% for(var i=0; i<content.length; i++) { %>
            <li class="blog-item">
                <p class="blog-content"><%- content[i].content %></p>
                <p class="blog-extra">
                    <span class="date"><%= content[i].date %></span>
                    <a href="javascript:;" class="delete" data-content="<%= content[i].content %>">刪除</a>
                    <a href="javascript:;" class="update" data-content="<%= content[i].content %>">更新</a>
                </p>
            </li>
        <% } %>
    </ul>
</div>

上面用到了ejs模板引擎當中的流程控制標簽<% %>,前面介紹了另外兩個輸出標簽<% - %><% = %> ,其他常用的還有<%# %> 注釋標簽 , % 對標記進行轉義,-%>去掉沒有的空格。

4、數據的刪除與更新

前面你應該注意到了下面的語句

<a href="javascript:;" class="delete" data-content="<%= content[i].content %>">刪除</a>
<a href="javascript:;" class="update" data-content="<%= content[i].content %>">更新</a>

這兩個語句就是為本節做鋪墊的。我們前面實現了頁面內容實時發布,現在我們需要增加頁面的刪除與更新功能,首先我們來實現頁面的更新功能。

  • (1)、頁面數據的刪除
    首先在index.html中新增js代碼:
    // 刪除
    $('.delete').on('click', function () {
        var deleteContent = $('.delete').attr('data-content');
        var postData ={
            'deleteContent':deleteContent
        };
        if (confirm("你確定要刪除該條微型博客嗎")){
            $.ajax({
                type: 'post',
                url: '/',
                data: postData,
                success:function (data) {
                    location.href='/'

                },
                error:function (data) {
                    alert("刪除失敗,請重試!");
                    location.href='/'
                }
            })
        }
    });

前臺我們利用ajax向后臺發了一個ajax的post請求,因此后臺我們需要對該請求進行處理(即在數據庫中刪除指定的內容):
后臺index.js 中的router.post部分新增js代碼:

    var deleteContent = req.body.deleteContent;

    if (deleteContent) {
        post.remove({content: deleteContent}, function(err) {
            if (err) {
                console.error(err);
                return;
            }
            console.log('刪除成功!');
            res.send(200);
        });
    }
  • (2)、頁面數據的更新
    接下來我們來實現下更新的功能;

更新的流程是:
在主頁面點擊更新鏈接--->調轉至更新頁面--->在更新頁面編輯文字-->再點擊發布變返回至主頁面;

代碼的實現思路是:
更新鏈接綁定點擊事件(當點擊更新鏈接時跳轉至update.html并在url后面以搜索字符串的形式添加之前已經填好的數據),當跳轉至update后再將url后面添加的數據賦值給update的textarea,再綁定update里的更新鏈接的點擊事件(當點擊時將textarea里的數據保存至數據庫中,然后跳轉至主頁面),當跳轉至主頁面后又從數據庫中讀取相應數據并渲染至主頁面上;

  • a、 index.html新增的js代碼
    // 更新跳轉
    $('.update').on('click', function() {
        var updateContent = $(this).attr('data-content');
        location.href = '/update?updateBlog=' + updateContent;
    });
  • b、update.html新增的js代碼
<script type="text/javascript" src="/javascripts/jquery.min.js"></script>
<script>
$(function() {

    // 從url讀取要更新的內容,簡單粗暴處理
    var oldContent = decodeURI(window.location.search.substr(12));

    // 設置它到文本域,并保留換行
    $('.textarea-add').val(oldContent.replace(/\<br\/>/g, '\n'));

    // 更新
    $('.btn-update').on('click', function() {
        var updateContent = $('.textarea-add').val().trim().replace(/\n/g, '<br/>');

        if (updateContent === oldContent) {
            alert('內容沒有更新!');
            return;
        }

        var postData = {
            'oldContent': oldContent,
            'updateContent': updateContent
        };

        $.ajax({ 
            url: '/',
            type: 'post',
            data: postData,
            success: function(data){
                alert('更新成功!');
                location.href = '/';
            },
            error: function(data){ 
                alert('更新失敗!');
                location.href = 'error';
            }
        }); 
    });

});
</script>

由于前端點擊更新后通過ajax發出了一個post請求,因此后端index.js需要處理該post請求,因此index.js post里面router.post的代碼更新如下:

/* POST home page. */
router.post('/', function(req, res) { 
    var content = req.body.content;
    var date = req.body.date;

    if (content && date) {
        var newPost = new post({
            content: content,
            date: date
        });

        newPost.save(function (err) {
            if (err) {
                console.error(err);
                return;
            }
            // newPost is saved!
            console.log('保存成功!');
            res.send(200);
        });
    }

    var deleteContent = req.body.deleteContent;

    if (deleteContent) {
        post.remove({content: deleteContent}, function(err) {
            if (err) {
                console.error(err);
                return;
            }
            console.log('刪除成功!');
            res.send(200);
        });
    }

    var oldContent = req.body.oldContent,
        updateContent = req.body.updateContent;

    if (oldContent && updateContent) {
        post.update({content: oldContent}, {$set: {'content': updateContent}}, function(err) {
            if (err) {
                console.error(err);
                return;
            }
            console.log('更新成功!');
            res.send(200);
        });
    }
});

至此,我們可以重啟下服務器 npm start ,終于完成了開頭描述的效果啦~ 看此簡單的功能,其實里面涉及到蠻多知識的~ 最后貼下自己的所有代碼到github上---https://github.com/have-not-BUG/simpleBlog 歡迎star或下載。
另: 以上如有錯誤之處,懇請指出。謝謝!

補充資料:
1、MongoDB 更新文檔
2、mongodb_查詢操作使用_條件查詢、where子句等

參考資料:
1、SQL 和 NoSQL 的區別
2 、使用express和mongodb搭建一個極簡博客
2、ejs模板的書寫

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 228,461評論 6 532
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 98,538評論 3 417
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 176,423評論 0 375
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 62,991評論 1 312
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,761評論 6 410
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,207評論 1 324
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,268評論 3 441
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,419評論 0 288
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 48,959評論 1 335
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 40,782評論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 42,983評論 1 369
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,528評論 5 359
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,222評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,653評論 0 26
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,901評論 1 286
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,678評論 3 392
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 47,978評論 2 374

推薦閱讀更多精彩內容