封裝React AntD的table表格組件

封裝組件是為了能在開發(fā)過程中高度復(fù)用功能和樣式相似的組件耳胎,以便我們只關(guān)注于業(yè)務(wù)邏輯層的處理送滞,提高開發(fā)效率谬墙,提高逼格夫嗓,降低代碼重復(fù)率迹炼,降低勞動(dòng)時(shí)間德迹,減少加班的可能知染。

本次組件的封裝采用了函數(shù)式組件即無狀態(tài)組件的方式來提高頁面渲染性能烈掠,由于無狀態(tài)組件在數(shù)據(jù)變更后不會(huì)主動(dòng)觸發(fā)頁面的重新渲染彤钟,所以本次的封裝也用到了React Hooks来候。下面簡要介紹一下函數(shù)式組件和React Hooks。

函數(shù)式組件是被精簡成一個(gè)render方法的函數(shù)來實(shí)現(xiàn)的逸雹,由于是無狀態(tài)組件营搅,所以無狀態(tài)組件就不會(huì)再有組件實(shí)例化的過程云挟,無實(shí)例化過程也就不需要分配多余的內(nèi)存,從而性能得到一定的提升转质。但函數(shù)式組件是沒有this和ref的园欣,如果強(qiáng)行給函數(shù)式組件添加ref會(huì)報(bào)一個(gè)'Function components cannot have string refs. We recommend using useRef() instead.'的錯(cuò)誤。函數(shù)式組件也沒有生命周期休蟹,沒有所謂的componentWillMount沸枯、componentDidMount、componentWillReceiveProps赂弓、shouldComponentUpdate等方法绑榴。

React Hooks是react16.8引入的特性,他允許你在不寫class的情況下操作state和react的其他特性盈魁。Hook就是JavaScript函數(shù)翔怎,但是使用它們會(huì)有兩個(gè)額外的規(guī)則:

只能在函數(shù)最外層調(diào)用Hook,不能在循環(huán)备埃、條件判斷或者子函數(shù)中調(diào)用姓惑;

只能在React的函數(shù)組件中調(diào)用Hook,不能在其他JavaScript函數(shù)中調(diào)用(自定義Hook除外)按脚。

React Hooks中用的比較頻繁的方法:

useState

useEffect

useContext

useReducer

useMemo

useRef

useImperativeHandle

由于以上方法的具體介紹及使用的篇幅過大于毙,故請(qǐng)自行查閱API或資料,這里不再展開描述辅搬。

另外唯沮,本次封裝一部分采用了JSX來創(chuàng)建虛擬dom節(jié)點(diǎn),一部分采用了createElement方法來創(chuàng)建虛擬dom節(jié)點(diǎn)堪遂,createElement方法接收三個(gè)參數(shù):

第一個(gè)參數(shù):必填介蛉,可以是一個(gè)html標(biāo)簽名稱字符串如span、div溶褪、p等币旧,也可以是一個(gè)react組件;

第二個(gè)參數(shù):選填猿妈,創(chuàng)建的標(biāo)簽或組件的屬性吹菱,用對(duì)象方式表示;

第三個(gè)參數(shù):選填彭则,創(chuàng)建的標(biāo)簽或組件的子節(jié)點(diǎn)鳍刷,可以是一個(gè)字符串或一個(gè)組件,也可以是一個(gè)包含了字符串或組件的數(shù)組俯抖,還可以是一個(gè)采用createElement創(chuàng)建的虛擬dom節(jié)點(diǎn)输瓜。

createElement方法可能用的人不會(huì)很多,因?yàn)楝F(xiàn)在有了類似于html的JavaScript語法糖JSX,使用和理解起來也較為直觀和方便尤揣,符合我們對(duì)html結(jié)構(gòu)的認(rèn)知搔啊。但其實(shí)JSX被babel編譯后的呈現(xiàn)方式就是使用createElement方法創(chuàng)建的虛擬dom,至于為何使用createElement方法芹缔,私心覺得可以提升編譯打包效率坯癣。另外本次封裝組件時(shí)有些地方也使用了JSX,是覺得在那些地方使用JSX更舒服最欠,而有些地方使用createElement方法私心也覺得更符合js的編寫習(xí)慣,如果你覺得在一個(gè)組件中既有JSX又有createElement會(huì)很亂的話惩猫,你可以統(tǒng)一使用一種即可芝硬。

本次封裝所使用到的方法的介紹基本完畢,以下是組件封裝的具體實(shí)現(xiàn)部分轧房。

先貼一張最后實(shí)現(xiàn)的效果圖:

1拌阴、所封裝的antd table組件table.js

import React, { createElement, useState, useImperativeHandle } from 'react'

import PropTypes from 'prop-types'

import { Link } from "react-router-dom"

import { Table } from 'antd';

import { timestampToTime, currency } from '@/utils'

const h = createElement;

const TableComp = ({columns, dataSource, hasCheck, cRef, getCheckboxProps}) => {

? const empty = '-',

? ? [selectedRowKeys, setSelectedRowKeys ] = useState([]),

? ? [selectedRows, setSelectedRows] = useState([]),

? ? render = {

? ? ? Default: v => v,

? ? ? Enum: (v, {Enum}) => {

? ? ? ? if(!Enum[v]) return empty;

? ? ? ? return Enum[v]

? ? ? },

? ? ? Format: (v, {format}, row) => format(v, row),

? ? ? Currency: v => currency(v),

? ? ? Date: v => timestampToTime(v, 'second'),

? ? ? Link: (v, {url}) => <Link to={url}>{v}</Link>,

? ? ? Action: (v, {value}, row) => {

? ? ? ? const result = value.filter(n => {

? ? ? ? ? const {filter = () => true} = n

? ? ? ? ? return filter(row)

? ? ? ? })

? ? ? ? return result.map(t => <span className="table-link" onClick={() => t.click(row)} key={t.label}>{t.label}</span>)

? ? ? },

? ? }

? columns = columns.map(n => {

? ? const { type = 'Default' } = n;

? ? return {...n, render: (v, row) => (!v || v.length < 1) && type != 'Action' ? empty : render[type](v, n, row)}

? })

? //父組件獲取selectedRowKeys的方法-cRef就是父組件傳過來的ref

? useImperativeHandle(cRef, () => ({

? ? //getSelectedRowKeys就是暴露給父組件的方法

? ? getSelectedRowKeys: () => selectedRowKeys,

? ? getSelectedRows: () => selectedRows

? }));

? const onSelectChange = (selectedRowKeys, selectedRows) => {

? ? setSelectedRowKeys(selectedRowKeys);

? ? setSelectedRows(selectedRows);

? }

? const rowSelection = {

? ? selectedRowKeys,

? ? onChange: onSelectChange,

? ? getCheckboxProps: record => getCheckboxProps(record)

? };

? return hasCheck ? h(Table, {columns, dataSource, rowSelection}) : h(Table, {columns, dataSource})

}

TableComp.propTypes = {

? columns: PropTypes.array.isRequired,? ? //表格頭部

? dataSource: PropTypes.array.isRequired, //表格數(shù)據(jù)

? hasCheck: PropTypes.bool,? ? ? ? ? ? ? //表格行是否可選擇

? cRef: PropTypes.object,? ? ? ? ? ? ? ? //父組件傳過來的獲取組件實(shí)例對(duì)象或者是DOM對(duì)象

? getCheckboxProps: PropTypes.func,? ? ? //選擇框的默認(rèn)屬性配置

}

export default TableComp

2、時(shí)間戳格式化timestampToTime.js

export const timestampToTime = (timestamp, type) => {

? let date = new Date(timestamp); //時(shí)間戳為10位需*1000奶镶,時(shí)間戳為13位的話不需乘1000

? let Y = date.getFullYear() + '-';

? let M = (date.getMonth() + 1 < 10 ? '0' + (date.getMonth() + 1) : date.getMonth() + 1) + '-';

? let D = date.getDate() < 10 ? '0' + date.getDate() + ' ' : date.getDate() + '';

? let h = date.getHours() < 10 ? '0' + date.getHours() + ':' : date.getHours() + ':';

? let m = date.getMinutes() < 10 ? '0' + date.getMinutes() + ':' : date.getMinutes() + ':';

? let s = date.getSeconds() < 10 ? '0' + date.getSeconds() : date.getSeconds();

? if (type == 'second') {

? ? return Y + M + D + ' ' + h + m + s;

? } else {

? ? return Y + M + D

? }

}

3迟赃、金額千分位currency.js

export const currency = v => {

? let [n, d = []] = v.toString().split('.');

? return [n.replace(/(\d)(?=(?:\d{3})+$)/g, '$1,')].concat(d).join('.');

};

簡單介紹下封裝的table組件,本組件基本涵蓋了大多數(shù)情況下我們所用到的表格組件的情況厂镇,包括:操作按鈕的權(quán)限控制纤壁、某一列的跳轉(zhuǎn)、某一列的字段映射以及金額千分位捺信、時(shí)間戳格式化和某一列數(shù)組數(shù)據(jù)的循環(huán)展示酌媒、表格是否可選擇等等。如還有其他需求迄靠,可自行添加即可秒咨。

4、table組件的使用方法:

import React, { useRef } from 'react'

import { Button } from 'antd'

import Table from './table'

const TableDemo = () => {

? const permission = ["handle", "pass", "refuse", "reApply", 'export'], Enum = {

? ? CREATED: '代辦理',

? ? PASS: '待審批',

? ? REJECT: '駁回',

? ? REFUSE: '拒絕',

? };

? const statisticFormat = val => val.map((t, idx) => <span key={idx} style={{marginRight: '5px'}}>{t.total}</span>)

? const columns = [

? ? { title: '姓名', dataIndex: 'name', key: 'name', type: 'Link', url: 'https://www.baidu.com' },

? ? { title: '年齡', dataIndex: 'age', key: 'age' },

? ? { title: '狀態(tài)', dataIndex: 'status', key: 'status', type: 'Enum', Enum, },

? ? { title: '預(yù)警統(tǒng)計(jì)', dataIndex: 'statistic', key: 'statistic', type: 'Format', format: statisticFormat },

? ? { title: '存款', dataIndex: 'money', key: 'money', type: 'Currency' },

? ? { title: '日期', dataIndex: 'date', key: 'date', type: 'Date'},

? ? { title: '操作', dataIndex: 'action', key: 'action', type: 'Action', value: [

? ? ? {label: "查看", click: data => {console.log(data)}},

? ? ? {label: "辦理", click: data => {}, filter: ({status}) => status == 'CREATED' && permission.some(n => n == 'handle')},

? ? ? {label: "通過", click: data => {}, filter: ({status}) => status == 'PASS' && permission.some(n => n == 'pass')},

? ? ? {label: "駁回", click: data => {}, filter: ({status}) => status == 'REJECT' && permission.some(n => n == 'reject')},

? ? ? {label: "拒絕", click: data => {}, filter: ({status}) => status == 'CREATED' && permission.some(n => n == 'refuse')},

? ? ? {label: "重新付款", click: data => {}, filter: ({status}) => status == 'REAPPLY' && permission.some(n => n == 'reApply')},

? ? ]},

? ]

? const dataSource = [

? ? {key: 1, name: '小壞', age: 20, status: 'CREATED', date: 1596791666000, statistic: [{level: 3, total: 5}, {level: 2, total: 7}, {level: 1, total: 20}, {level: 0, total: 0}], money: 200000000000},

? ? {key: 2, name: 'tnnyang', age: 18, status: 'PASS', date: 1596791666000, statistic: [],? money: 2568912357893},

? ? {key: 3, name: 'xiaohuai', status: 'REJECT', statistic: [], money: 6235871},

? ? {key: 4, name: '陳公子', age: 21, status: 'REAPPLY', date: 1596791666000, statistic: []},

? ]

? const config = {

? ? columns,

? ? dataSource,

? ? hasCheck: true,? //是否顯示表格第一列的checkbox復(fù)選框

? ? getCheckboxProps: record => {return {disabled: record.status == 'REJECT'}}? //table表格rowSelection的禁用

? }

? //點(diǎn)擊獲取通過checkbox復(fù)選框選中的表格

? const childRef = useRef();

? const getTableChecked = () => {

? ? const selectedRowKeys = childRef.current.getSelectedRowKeys(), selectedRows = childRef.current.getSelectedRows();

? ? console.log(selectedRowKeys)

? ? console.log(selectedRows)

? }

? return <div>

? ? <Table {...config} cRef={childRef} />

? ? <Button type="primary" onClick={getTableChecked}>獲取選擇的列表項(xiàng)</Button>

? </div>

}

export default TableDemo

最后再貼一下本次封裝所用到的各個(gè)包的版本:

react: 16.8.6,

react-dom: 16.8.6,

react-router-dom: 5.0.0,

antd: 4.3.5,

@babel/core: 7.4.4,

babel-loader: 8.0.5

其實(shí)最主要的是react和antd的版本掌挚,其中antd4和antd3在table組件上的差異還是很大的雨席,在其他組件上的差異也是很大的。

------------------------------------ 分割線 -----------------------------------

有大佬在我另一篇博文封裝react antd的form表單組件的評(píng)論區(qū)提出關(guān)于合并表格的單元格功能等吠式,我一想陡厘,合并單元格也是我們?cè)谑褂帽砀窠M件時(shí)可能會(huì)經(jīng)常遇到的需求,那么就在之前封裝的基礎(chǔ)上加上合并單元格的實(shí)現(xiàn)吧奇徒。

在看了antd的表格組件的實(shí)例后覺得合并單元格其實(shí)也很簡單雏亚,是基于單元格的值和索引來實(shí)現(xiàn)的,那么在我們之前封裝的基礎(chǔ)上再套一層合并單元格的函數(shù)就可以了摩钙。

帶有合并單元格功能的table封裝組件的完整代碼如下:

import React, { createElement, useState, useImperativeHandle } from 'react'

import PropTypes from 'prop-types'

import { Link } from "react-router-dom"

import { Table } from 'antd';

import { timestampToTime, currency } from '@/utils'

const h = createElement;

const TableComp = ({columns, dataSource, hasCheck, cRef, getCheckboxProps, bordered}) => {

? const empty = '-',

? ? [selectedRowKeys, setSelectedRowKeys ] = useState([]),

? ? [selectedRows, setSelectedRows] = useState([]),

? ? render = {

? ? ? Default: v => v,

? ? ? Enum: (v, {Enum}) => {

? ? ? ? if(!Enum[v]) return empty

? ? ? ? return Enum[v]

? ? ? },

? ? ? Format: (v, {format}, row) => format(v, row),

? ? ? Currency: v => currency(v),

? ? ? Date: v => timestampToTime(v, 'second'),

? ? ? Link: (v, {url}) => <Link to={url}>{v}</Link>,

? ? ? Action: (v, {value}, row) => {

? ? ? ? const result = value.filter(n => {

? ? ? ? ? const {filter = () => true} = n

? ? ? ? ? return filter(row)

? ? ? ? })

? ? ? ? return result.map(t => <span className="table-link" onClick={() => t.click(row)} key={t.label}>{t.label}</span>)

? ? ? },

? ? }

? columns = columns.map(n => {

? ? const { type = 'Default', merge } = n;

? ? return {...n, render: (v, row, index) => (!v || v.length < 1) && type != 'Action' ? empty : merge && typeof merge == 'function' ? merge(render[type](v, n, row), index) : render[type](v, n, row)}

? })

? //父組件獲取selectedRowKeys的方法-cRef就是父組件傳過來的ref

? useImperativeHandle(cRef, () => ({

? ? //getSelectedRowKeys就是暴露給父組件的方法

? ? getSelectedRowKeys: () => selectedRowKeys,

? ? getSelectedRows: () => selectedRows

? }));

? const onSelectChange = (selectedRowKeys, selectedRows) => {

? ? setSelectedRowKeys(selectedRowKeys);

? ? setSelectedRows(selectedRows);

? }

? const rowSelection = {

? ? selectedRowKeys,

? ? onChange: onSelectChange,

? ? getCheckboxProps: record => getCheckboxProps(record)

? };

? return hasCheck ? h(Table, {columns, dataSource, rowSelection, bordered}) : h(Table, {columns, dataSource, bordered})

}

Components.propTypes = {

? columns: PropTypes.array.isRequired,? ? //表格頭部

? dataSource: PropTypes.array.isRequired,? //表格數(shù)據(jù)

? onChange: PropTypes.func,? ? ? ? ? ? ? ? //表格翻頁函數(shù)

? hasCheck: PropTypes.bool,? ? ? ? ? ? ? ? //表格行是否可選擇

? cRef: PropTypes.object,? ? ? ? ? ? ? ? ? //父組件傳過來的獲取組件實(shí)例對(duì)象或者是DOM對(duì)象

? getCheckboxProps: PropTypes.func,? ? ? ? //選擇框的默認(rèn)屬性配置

}

export default TableComp

使用方法完整代碼:

import React, { useRef } from 'react'

import { Button } from 'antd'

import Table from './mergeTable'

import './demo.css'

const TableDemo = () => {

? const permission = ["handle", "pass", "refuse", "reApply", 'export'], Enum = {

? ? CREATED: '代辦理',

? ? PASS: '待審批',

? ? REJECT: '駁回',

? ? REFUSE: '拒絕',

? };

? const statisticFormat = val => val.map((t, idx) => <span key={idx} style={{marginRight: '5px'}}>{t.total}</span>)

? const columns = [

? ? { title: '姓名', dataIndex: 'name', key: 'name', type: 'Link', url: 'https://www.baidu.com' },

? ? { title: '身份證號(hào)/年齡', dataIndex: 'ID', key: 'ID', colSpan: 2, },

? ? { title: '年齡', dataIndex: 'age', key: 'age', colSpan: 0, },

? ? { title: '狀態(tài)', dataIndex: 'status', key: 'status', type: 'Enum', Enum, merge: (v, index) => {

? ? ? const obj = {

? ? ? ? children: v,

? ? ? ? props: {},

? ? ? };

? ? ? if (index != 2) {

? ? ? ? return v;

? ? ? }

? ? ? //從第二行開始合并罢低,合并兩列 - index從0開始,colSpan代表合并行。

? ? ? if (index === 2) {

? ? ? ? obj.props.colSpan = 2;

? ? ? }

? ? ? return obj;

? ? }},

? ? { title: '規(guī)則', dataIndex: 'rule', key: 'rule', merge: (v, index) => {

? ? ? const obj = {

? ? ? ? children: v,

? ? ? ? props: {},

? ? ? };

? ? ? //從第二行開始合并网持,合并兩列 - index從0開始宜岛,colSpan代表合并行。

? ? ? if (index === 2) {

? ? ? ? obj.props.colSpan = 0;

? ? ? }

? ? ? return obj;

? ? }},

? ? { title: '預(yù)警統(tǒng)計(jì)', dataIndex: 'statistic', key: 'statistic', type: 'Format', format: statisticFormat },

? ? { title: '存款', dataIndex: 'money', key: 'money', type: 'Currency', merge: (v, index) => {

? ? ? const obj = {

? ? ? ? children: v,

? ? ? ? props: {},

? ? ? };

? ? ? //從第二行開始合并功舀,合并兩行 - index從0開始萍倡,rowSpan代表合并列,rowSpan = 2代表合并兩列辟汰,即將存款列的第二行和第三行合并

? ? ? if (index === 1) {

? ? ? ? obj.props.rowSpan = 2;

? ? ? }

? ? ? //colSpan或者rowSpan設(shè)值為0時(shí)列敲,設(shè)置的表格不會(huì)渲染,即表格數(shù)據(jù)不會(huì)展示出來帖汞。這段代碼的意思是第三行的數(shù)據(jù)不展示并將第三行合并到第二行

? ? ? if (index === 2) {

? ? ? ? obj.props.rowSpan = 0;

? ? ? }

? ? ? return obj;

? ? }},

? ? { title: '日期', dataIndex: 'date', key: 'date', type: 'Date'},

? ? { title: '操作', dataIndex: 'action', key: 'action', type: 'Action', value: [

? ? ? {label: "查看", click: data => {console.log(data)}},

? ? ? {label: "辦理", click: data => {}, filter: ({status}) => status == 'CREATED' && permission.some(n => n == 'handle')},

? ? ? {label: "通過", click: data => {}, filter: ({status}) => status == 'PASS' && permission.some(n => n == 'pass')},

? ? ? {label: "駁回", click: data => {}, filter: ({status}) => status == 'REJECT' && permission.some(n => n == 'reject')},

? ? ? {label: "拒絕", click: data => {}, filter: ({status}) => status == 'CREATED' && permission.some(n => n == 'refuse')},

? ? ? {label: "重新付款", click: data => {}, filter: ({status}) => status == 'REAPPLY' && permission.some(n => n == 'reApply')},

? ? ]},

? ]

? const dataSource = [

? ? {key: 1, name: '小壞', ID: 'abc', age: 20, status: 'CREATED', rule: '標(biāo)準(zhǔn)', date: 1596791666000, statistic: [{level: 3, total: 5}, {level: 2, total: 7}, {level: 1, total: 20}, {level: 0, total: 0}], money: 200000000000},

? ? {key: 2, name: 'tnnyang', ID: 'def', age: 18, status: 'PASS', rule: '個(gè)性化', date: 1596791666000, statistic: [],? money: 2568912357893},

? ? {key: 3, name: 'xiaohuai', ID: 'ghi', status: 'REJECT', rule: '標(biāo)準(zhǔn)', statistic: [], money: 6235871},

? ? {key: 4, name: '陳公子', ID: 'jkl', age: 21, status: 'REAPPLY', rule: '個(gè)性化', date: 1596791666000, statistic: []},

? ]

? const config = {

? ? columns,

? ? dataSource,

? ? getCheckboxProps: record => {return {disabled: record.status == 'REJECT'}},? //table表格rowSelection的禁用

? ? bordered: true,

? }

? //點(diǎn)擊獲取通過checkbox復(fù)選框選中的表格

? const childRef = useRef();

? const getTableChecked = () => {

? ? const selectedRowKeys = childRef.current.getSelectedRowKeys(), selectedRows = childRef.current.getSelectedRows();

? ? console.log(selectedRowKeys)

? ? console.log(selectedRows)

? }

? return <div style={{margin: '20px'}}>

? ? <Table {...config} cRef={childRef} />

? ? <Button type="primary" onClick={getTableChecked}>獲取選擇的列表項(xiàng)</Button>

? </div>

}

export default TableDemo


轉(zhuǎn)自:https://www.cnblogs.com/tnnyang/p/13491868.html

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末戴而,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子翩蘸,更是在濱河造成了極大的恐慌所意,老刑警劉巖,帶你破解...
    沈念sama閱讀 206,968評(píng)論 6 482
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件催首,死亡現(xiàn)場離奇詭異扶踊,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)郎任,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,601評(píng)論 2 382
  • 文/潘曉璐 我一進(jìn)店門秧耗,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人涝滴,你說我怎么就攤上這事绣版。” “怎么了歼疮?”我有些...
    開封第一講書人閱讀 153,220評(píng)論 0 344
  • 文/不壞的土叔 我叫張陵杂抽,是天一觀的道長。 經(jīng)常有香客問我韩脏,道長缩麸,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 55,416評(píng)論 1 279
  • 正文 為了忘掉前任赡矢,我火速辦了婚禮杭朱,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘吹散。我一直安慰自己弧械,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,425評(píng)論 5 374
  • 文/花漫 我一把揭開白布空民。 她就那樣靜靜地躺著刃唐,像睡著了一般羞迷。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上画饥,一...
    開封第一講書人閱讀 49,144評(píng)論 1 285
  • 那天衔瓮,我揣著相機(jī)與錄音,去河邊找鬼抖甘。 笑死热鞍,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的衔彻。 我是一名探鬼主播薇宠,決...
    沈念sama閱讀 38,432評(píng)論 3 401
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢(mèng)啊……” “哼米奸!你這毒婦竟也來了昼接?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,088評(píng)論 0 261
  • 序言:老撾萬榮一對(duì)情侶失蹤悴晰,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后逐工,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體铡溪,經(jīng)...
    沈念sama閱讀 43,586評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,028評(píng)論 2 325
  • 正文 我和宋清朗相戀三年泪喊,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了棕硫。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,137評(píng)論 1 334
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡袒啼,死狀恐怖哈扮,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情蚓再,我是刑警寧澤滑肉,帶...
    沈念sama閱讀 33,783評(píng)論 4 324
  • 正文 年R本政府宣布,位于F島的核電站摘仅,受9級(jí)特大地震影響靶庙,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜娃属,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,343評(píng)論 3 307
  • 文/蒙蒙 一六荒、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧矾端,春花似錦掏击、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,333評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春钠惩,著一層夾襖步出監(jiān)牢的瞬間柒凉,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,559評(píng)論 1 262
  • 我被黑心中介騙來泰國打工篓跛, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留膝捞,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 45,595評(píng)論 2 355
  • 正文 我出身青樓愧沟,卻偏偏與公主長得像蔬咬,于是被迫代替她去往敵國和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子沐寺,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,901評(píng)論 2 345

推薦閱讀更多精彩內(nèi)容