React.js

函数是面向过程的,函数的调用不需要主体,而方法是属于对象的,调用方法需要一个主体-即对象。

npm install -g create-react-app
创建react项目(具体看react-commend) 项目名 描述 作者等配置可以全部默认
先创建文件夹 cd到目录下 create-react-app my-app(注意此处名字不能有大写)
然后 cd my-appnpm start启动

组件的state应该用来存储组件的事件处理函数随时可能会改变的数据,以达到重新渲染并保持组件的用户界面最新的目的

react事件触发,如onClick,onChange={this.fn.bind(this)}要用bind绑定事件以辨认

文末有贴士,也算是一种规范,习惯。

直接使用 BootCDN 的 React CDN 库,地址如下:

<script src="https://cdn.bootcss.com/react/15.4.2/react.min.js"></script>
<script src="https://cdn.bootcss.com/react/15.4.2/react-dom.min.js"></script>
<script src="https://cdn.bootcss.com/babel-standalone/6.22.1/babel.min.js"></script>

react.min.js - React 的核心库
react-dom.min.js - 提供与 DOM 相关的功能
babel.min.js - Babel 可以将 ES6 代码转为 ES5 代码,这样我们就能在目前不支持 ES6 浏览器上执行 React 代码。Babel 内嵌了对 JSX 的支持。通过将 Babel 和 babel-sublime 包(package)一同使用可以让源码的语法渲染上升到一个全新的水平。

ReactDOM.render(    /代码将一个 h1 标题,插入 id="example" 节点中。
    <h1>Hello, world!</h1>,
    document.getElementById('example')
);

JSX语法

React 使用 JSX 来替代常规的 JavaScript。

  • JSX 是一个看起来很像 XML 的 JavaScript 语法扩展。
  • JSX 执行更快,因为它在编译为 JavaScript 代码后进行了优化。
  • 它是类型安全的,在编译过程中就能发现错误。
    在 JSX 中使用 JavaScript 表达式。表达式写在花括号 {} 中
    在 JSX 中不能使用 if else 语句,但可以使用 conditional (三元运算) 表达式来替代。
ReactDOM.render(
    <div>
      <h1>{i == 1 ? 'True!' : 'False'}</h1>
    </div>
    ,
    document.getElementById('example')
);

JSX 允许在模板中插入数组,数组会自动展开所有成员:

var arr = [
  <h1>菜鸟教程</h1>,
  <h2>学的不仅是技术,更是梦想!</h2>,
];
ReactDOM.render(
  <div>{arr}</div>,
  document.getElementById('example')
);

1、在标签内部的注释需要花括号
2、在标签外的的注释不能使用花括号

ReactDOM.render(
    /*注释 */
    <h1>孙朝阳 {/*注释*/}</h1>,
    document.getElementById('example')
);

代码中嵌套多个 HTML 标签,需要使用一个标签元素包裹它

React 组件

var HelloMessage = React.createClass({
  render: function() {
    return <h1>Hello World!</h1>;
  }
});
ReactDOM.render(
  <HelloMessage />,
  document.getElementById('example')
);

React.createClass 方法用于生成一个组件类 HelloMessage。
<HelloMessage /> 实例组件类并输出信息。
定义的 React 类名以大写字母开头,注意组件类只能包含一个顶层标签。

如果我们需要向组件传递参数,可以使用 this.props 对象:

var HelloMessage = React.createClass({
  render: function() {
    return <h1>Hello {this.props.name}</h1>;
  }
});
ReactDOM.render(
  <HelloMessage name="Runoob" />,
  document.getElementById('example')
);

class 属性需要写成 className ,for 属性需要写成 htmlFor ,这是因为 class 和 for 是 JavaScript 的保留字。
可以通过创建多个组件来合成一个组件,即把组件的不同功能点进行分离。
组件名不一定是用单标签,也可以是双标签
<HelloMessage /> == <HelloMessage></HelloMessage>

React State(状态)

React 把组件看成是一个状态机(State Machines)。通过与用户的交互,实现不同状态,然后渲染 UI,让用户界面和数据保持一致。

 var LikeButton = React.createClass({
        getInitialState: function() {
          return {liked: false};
        },
        handleClick: function(event) {
          this.setState({liked: !this.state.liked});
        },
        render: function() {
          var text = this.state.liked ? '喜欢' : '不喜欢';
          return (
            <p onClick={this.handleClick}>
              你<b>{text}</b>我。点我切换状态。
            </p>
          );
        }
      });
      ReactDOM.render(
        <LikeButton />,
        document.getElementById('example')
      );

与原生 HTML 不同,on 之后第一个字母是大写的。 onClick={this.handleClick}

React Props

state 和 props 主要的区别在于 props 是不可变的,而 state 可以根据与用户交互来改变。state 来更新和修改数据。 而子组件只能通过 props 来传递数据。
可以通过 getDefaultProps() 方法为 props 设置默认值:

var HelloMessage = React.createClass({
  getDefaultProps: function() {
    return {
      name: 'Runoob'
    };
  },
  render: function() {
    return <h1>Hello {this.props.name}</h1>;
  }
});
ReactDOM.render(
  <HelloMessage />,
  document.getElementById('example')
);

可以在父组件中设置 state, 并通过在子组件上使用 props 将其传递到子组件上。

React 组件 API

setState(object nextState[, function callback])
合并nextState和当前state,并重新渲染组件。setState是React事件处理函数中和请求回调函数中触发UI更新的主要方法。setState()并不会立即改变this.state,而是创建一个即将处理的state。setState()并不一定是同步的,为了提升性能React会批量执行state和DOM渲染。setState()总是会触发一次组件重绘。

  • 设置状态:setState
  • 替换状态:replaceState
  • 设置属性:setProps
  • 替换属性:replaceProps
  • 强制更新:forceUpdate
  • 获取DOM节点:findDOMNode
  • 判断组件挂载状态:isMounted
var HelloMessage = React.createClass({
  getInitialState: function() {
    return {value: 'Hello Runoob!'};
  },
  handleChange: function(event) {
    this.setState({value: event.target.value});
  },
  render: function() {
    var value = this.state.value;
    return <div>
            <input type="text" value={value} onChange={this.handleChange} /> 
            <h4>{value}</h4>
           </div>;
  }
});
ReactDOM.render(
  <HelloMessage />,
  document.getElementById('example')
);

React小书

组件化可以帮助我们解决前端结构的复用性问题,整个页面可以由这样的不同的组件组合、嵌套构成。组件的显示形态和行为可以由数据状态(state)和配置参数(props)共同决定。

编译阶段你需要借助 Babel;需要 Redux 等第三方的状态管理工具来组织代码;如果你要写单页面应用那么你需要 React-router。这就是所谓的“React.js全家桶”。

一个 DOM 元素包含的信息其实只有三个:标签名,属性,子元素。
JSX 在编译的时候会变成相应的 JavaScript 对象描述。
我们在编写 React.js 组件的时候,一般都需要继承 React.js 的 Component(还有别的编写组件的方式我们后续会提到)。一个组件类必须要实现一个 render 方法,这个 render 方法必须要返回一个 JSX 元素。但这里要注意的是,必须要用一个外层的 JSX 元素把所有内容包裹起来。返回并列多个 JSX 元素是不合法的,下面是错误的做法:

render () {
  return (
    <div>第一个</div>
    <div>第二个</div>
  )
}

正确写法:

render () {
  return (
    <div>
      <div>第一个</div>
      <div>第二个</div>
    </div>
  )
}

{} 内可以放任何 JavaScript 的代码,包括变量、表达式计算、函数执行等等。 render 会把这些代码返回的内容如实地渲染到页面上,非常的灵活。
表达式插入不仅仅可以用在标签内部,也可以用在标签的属性上。
JSX 元素其实可以像 JavaScript 对象那样自由地赋值给变量,或者作为函数参数传递、或者作为函数的返回值。
作为变量:

const isGoodWord = true
const goodWord = <strong> is good</strong>
const badWord = <span> is not good</span>
  {isGoodWord ? goodWord : badWord}
// 作为函数:
renderGoodWord (goodWord, badWord) {
  const isGoodWord = true
  return isGoodWord ? goodWord : badWord
}        // 伪代码
{this.renderGoodWord(
          <strong> is good</strong>,
          <span> is not good</span>
)}

自定义的组件都必须要用大写字母开头,普通的 HTML 标签都用小写字母开头。

class Index extends Component {
  render () {
    return (
      <div>
        <Header />
        <Main />
        <Footer />
      </div>
    )}}     
ReactDOM.render(
  <Index />,
  document.getElementById('root')
)    //组件间的嵌套    树状结构

React.js 监听事件

只需要给需要监听事件的元素加上属性类似于 onClick、onKeyDown 这样的属性。
React.js 帮我们封装好了一系列的 on* 的属性,当你需要为某个元素监听某个事件的时候,只需要简单地给它加上 on* 就可以了。这些事件属性名都必须要用驼峰命名法。

这些 on* 的事件监听只能用在普通的 HTML 的标签上,而不能用在组件标签上。也就是说,<Header onClick={…} /> 这样的写法不会有什么效果的。

事件监听函数会被自动传入一个 event 对象,event 对象并不是浏览器提供的,而是它自己内部所构建的。

class Title extends Component {
  handleClickOnTitle (e) {
    console.log(e.target.innerHTML) }
  render () {
    return (
      <h1 onClick={this.handleClickOnTitle.bind(this)}>React 小书</h1>
    )  }
}
关于事件中的 this

React.js 调用你所传给它的方法的时候,并不是通过对象方法的方式调用(this.handleClickOnTitle),而是直接通过函数调用 (handleClickOnTitle),所以事件监听函数内并不能通过 this 获取到实例。如果你想在事件函数当中使用当前的实例,你需要手动地将实例方法 bind 到当前实例上再传入给 React.js。bind 会把实例方法绑定到当前实例上,然后我们再把绑定后的函数传给 React.js 的 onClick 事件监听。

bind 不仅可以帮我们把事件监听方法中的 this 绑定到当前组件实例上;还可以帮助我们在在渲染列表元素的时候,把列表元素传入事件监听函数当中,后面会介绍。

class LikeButton extends Component {
  constructor () {
    super()
    this.state = { isLiked: false }  //  这个对象在构造函数里面初始化  
  }
  handleClickOnLikeButton () {
    this.setState({  //  setState 函数,每次点击都会更新 isLiked 属性
      isLiked: !this.state.isLiked    })
  }
}

setState 方法由父类 Component 所提供。
React.js 内部会把 JavaScript 事件循环中的消息队列的同一个消息中的 setState 都进行合并以后再重新渲染组件。所以并不需要担心多次进行 setState 会带来性能问题。

组件内部是通过 this.props 的方式获取到组件的参数的,如果 this.props 里面有需要的属性我们就采用相应的属性,没有的话就用默认的属性。

在使用一个组件的时候,可以把参数放在标签的属性当中,所有的属性都会作为 props 对象的键值:

class Index extends Component {
  render () {
    return (
      <div>
        <LikeButton likedText='已赞' unlikedText='赞' />
      </div>
    ) }
}

前面的章节我们说过,JSX 的表达式插入可以在标签属性上使用。所以其实可以把任何类型的数据作为组件的参数,包括字符串、数字、对象、数组、甚至是函数等等:
<LikeButton wordings={{likedText: '已赞', unlikedText: '赞'}} />
JSX 的 {} 内可以嵌入任何表达式,{{}} 就是在 {} 内部用对象字面量返回一个对象而已。

  static defaultProps = {  //如果没有传进来,会直接使用 defaultProps 中的默认属性。
    likedText: '取消',
    unlikedText: '点赞'
  }   //defaultProps 作为点赞按钮组件的类属性,里面是对 props 中各个属性的默认配置。

state 是让组件控制自己的状态,props 是让外部对组件自己进行配置。尽量少地用 state,尽量多地用 props。因为状态会带来管理的复杂性,我们尽量多地写无状态组件,尽量少地写有状态的组件。这样会降低代码维护的难度,也会在一定程度上增强组件的可复用性。

渲染列表数据

一般来说,在 React.js 处理列表就是用 map 来处理、渲染的。
{ users.map((user) => <User user = {user} />) }
对于用表达式套数组罗列到页面上的元素,都要为每个元素加上 key 属性,这个 key 必须是每个元素唯一的标识。一般来说,key 的值可以直接后台数据返回的 id,因为后台的 id 都是唯一的。

{ users.map((user, i) => <User key={i} user={user} />)}
在实际项目当中,如果你的数据顺序可能发生变化,标准做法是最好是后台数据返回的 id 作为列表元素的 key。

React.js生命周期

React.js 将组件渲染,并且构造 DOM 元素然后塞入页面的过程称为组件的挂载(这个定义请好好记住)。

挂载阶段

React.js 会在组件的 render 之前调用 componentWillMount,在 DOM 元素塞入页面以后调用 componentDidMount。而componentWillUnmount控制了这个组件的删除过程。

-> constructor()
-> componentWillMount()
-> render()
// 然后构造 DOM 元素插入页面
-> componentDidMount()
// ...
// 即将从页面中删除
-> componentWillUnmount()
// 从页面中删除

我们一般会把组件的 state 的初始化工作放在 constructor 里面去做;
在 componentWillMount 进行组件的启动工作,例如 Ajax 数据拉取、定时器的启动;组件从页面上销毁的时候,有时候需要一些数据的清理,例如定时器的清理,就会放在 componentWillUnmount 里面去做。如下:

  constructor () {
    super()
    this.state = {
      date: new Date()
    }
  }
每隔 1 秒更新中的 state.date,这样页面就可以动起来了。
  componentWillMount () {
    this.timer = setInterval(() => {
      this.setState({ date: new Date() })
    }, 1000)
  }

现页面上有个按钮可显示或者隐藏时钟,当时钟隐藏的时候,我们并没有清除定时器。
添加 componentWillUnmount,在组件销毁的时候清除该组件的定时器:

  componentWillUnmount () {
    clearInterval(this.timer)
  }
更新阶段(说白了就是 setState,先了解即可)

shouldComponentUpdate(nextProps, nextState):你可以通过这个方法控制组件是否重新渲染。如果返回 false 组件就不会重新渲染。这个生命周期在 React.js 性能优化上非常有用。
componentWillReceiveProps(nextProps):组件从父组件接收到新的 props 之前调用。
componentWillUpdate():组件开始重新渲染之前调用。
componentDidUpdate():组件重新渲染并且把更改变更到真实的 DOM 以后调用。

ref属性

React.js 当中提供了 ref 属性来帮助我们获取已经挂载的元素的 DOM 节点,你可以给某个 JSX 元素加上 ref属性:

  componentDidMount () {
    this.input.focus()
  }
  render () {
    return (
      <input ref={(input) => this.input = input} />
    )  }
}   //我们就可以通过 this.input 获取到这个 DOM 元素。
就可以在 componentDidMount 中使用这个 DOM 元素。并且调用 this.input.focus() 的 DOM API。

但是记住一个原则:能不用 ref 就不用。不利于我们理解和维护。
其实可以给组件标签也加上 ref ,例如:
<Clock ref={(clock) => this.clock = clock} />

props.children

组件本身是一个不带任何内容的方形的容器,可以在用这组件的时候给它传入任意内容
嵌套的结构在组件内部都可以通过 props.children 获取到,这种组件编写方式在编写容器类型的组件当中非常有用。而在实际的 React.js 项目当中,我们几乎每天都需要用这种方式来编写组件。
http://huziketang.com/books/react/lesson22
{this.props.children}
React.js 就是把我们嵌套的 JSX 元素一个个都放到数组当中,然后通过 props.children 传给了Card

dangerouslySetHTML 和 style 属性
  render () {
    return (
      <div
        className='editor-wrapper'
        dangerouslySetInnerHTML={{__html: this.state.content}} />
    )  }

需要给 dangerouslySetInnerHTML 传入一个对象,这个对象的 __html 属性值就相当于元素的 innerHTML,这样我们就可以动态渲染元素的 innerHTML 结构了。因为设置 innerHTML 可能会导致跨站脚本攻击(XSS).这个属性不必要的情况就不要使用。

style 接受一个对象,这个对象里面是这个元素的 CSS 属性键值对,原来 CSS 属性中带 - 的元素都必须要去掉 - 换成驼峰命名,如 font-size 换成 fontSize,text-align 换成 textAlign。我们用 setState 就可以修改样式。
<h1 style={{fontSize: '12px', color: this.state.color}}>React.js 小书</h1>
只要简单地 setState({color: 'blue'}) 就可以修改元素的颜色成蓝色。

React 提供的第三方库 prop-types

通过 PropTypes 给组件的参数做类型限制,这在构建大型应用程序的时候特别有用。
npm install --save prop-types
http://huziketang.com/books/react/lesson24
在文件头部引入了 PropTypes import PropTypes from 'prop-types'
并且给 Comment 组件类添加了类属性 propTypes,里面的内容的意思就是你传入的 comment 类型必须为 object(对象)。isRequired 关键字来强制组件某个参数必须传入.:

static propTypes = {
  comment: PropTypes.object.isRequired
}

贴士

组件的私有方法都用 _ 开头,所有事件监听的方法都用 handle 开头。把事件监听方法传给组件的时候,属性名用 on 开头。监听(on)CommentInput 的 Submit 事件,并且交给 this 去处理(handle)。这样思路非常清晰。
<CommentInput onSubmit={this.handleSubmitComment.bind(this)} />

组件的内容编写顺序如下:

  1. static 开头的类属性,如 defaultProps、propTypes。
  2. 构造函数,constructor。
  3. getter/setter(还不了解的同学可以暂时忽略)。
  4. 组件生命周期。
  5. _ 开头的私有方法。
  6. 事件监听方法,handle*。
  7. render开头的方法,有时候 render() 方法里面的内容会分开到不同函数里面进行,这些函数都以 render 开头。
  8. render() 方法。

React ES5 与 ES6 区别

React Router

npm install -S react-router
使用时,路由器Router就是React的一个组件。

import { Router } from 'react-router';
render(<Router/>, document.getElementById('app'));

Router组件本身只是一个容器,真正的路由要通过Route组件定义。

import { Router, Route, hashHistory } from 'react-router';
render((
  <Router history={hashHistory}>
    <Route path="/" component={App}/>
  </Router>
), document.getElementById('app'));

用户访问根路由/(比如http://www.example.com/),组件APP就会加载到document.getElementById('app')。Router组件有一个参数history,它的值hashHistory表示,路由的切换由URL的hash变化决定,即URL的#部分发生变化。举例来说,用户访问http://www.example.com/,实际会看到的是http://www.example.com/#/

Route组件定义了URL路径与组件的对应关系。你可以同时使用多个Route组件。

<Router history={hashHistory}>
  <Route path="/" component={App}/>
  <Route path="/repos" component={Repos}/>
  <Route path="/about" component={About}/>
</Router>

上面代码中,用户访问/repos(比如http://localhost:8080/#/repos)时,加载Repos组件;访问/about(http://localhost:8080/#/about)时,加载About组件。

嵌套路由

<Router history={hashHistory}>
  <Route path="/" component={App}>
    <Route path="/repos" component={Repos}/>
    <Route path="/about" component={About}/>
  </Route>
</Router>

上面代码,用户访问/repos时,会先加载App组件,然后在它的内部再加载Repos组件。

<App>
  <Repos/>
</App>

this.props.children属性就是子组件。

path 属性

Route组件的path属性指定路由的匹配规则。这个属性是可以省略的,这样的话,不管路径是否匹配,总是会加载指定组件。

<Route path="inbox" component={Inbox}>
   <Route path="messages/:id" component={Message} />
</Route>

当用户访问 /inbox/messages/:id 时,会加载下面的组件。

<Inbox>
  <Message/>
</Inbox>

如果省略外层Route的path参数,写成下面的样子。

<Route component={Inbox}>
  <Route path="inbox/messages/:id" component={Message} />
</Route>

现在用户访问 /inbox/messages/:id 时,组件加载还是原来的样子。

path属性可以使用通配符。

<Route path="/hello/:name">
// 匹配 /hello/michael
// 匹配 /hello/ryan

<Route path="/hello(/:name)">
// 匹配 /hello
// 匹配 /hello/michael
// 匹配 /hello/ryan

<Route path="/files/*.*">
// 匹配 /files/hello.jpg
// 匹配 /files/hello.html

<Route path="/files/*">
// 匹配 /files/ 
// 匹配 /files/a
// 匹配 /files/a/b

<Route path="/**/*.jpg">
// 匹配 /files/hello.jpg
// 匹配 /files/path/to/file.jpg

通配符的规则如下。
(1):paramName
:paramName匹配URL的一个部分,直到遇到下一个/、?、#为止。这个路径参数可以通过this.props.params.paramName取出。
(2)()
()表示URL的这个部分是可选的。
(3)*
*匹配任意字符,直到模式里面的下一个字符为止。匹配方式是非贪婪模式。
(4) **
** 匹配任意字符,直到下一个/、?、#为止。匹配方式是贪婪模式。

路由匹配规则是从上到下执行,一旦发现匹配,就不再其余的规则了。

设置路径参数时,需要特别小心这一点。

<Router>
  <Route path="/:userName/:id" component={UserPage}/>
  <Route path="/about/me" component={About}/>
</Router>

IndexRoute 组件

显式指定Home是根路由的子组件,即指定默认情况下加载的子组件。你可以把IndexRoute想象成某个路径的index.html。

<Router>
  <Route path="/" component={App}>
    <IndexRoute component={Home}/>
    <Route path="accounts" component={Accounts}/>
    <Route path="statements" component={Statements}/>
  </Route>
</Router>

用户访问 / 的时候,加载的组件结构如下。

<App>
  <Home/>
</App>

App只包含下级组件的共有元素,本身的展示内容则由Home组件定义。这样有利于代码分离,也有利于使用React Router提供的各种API。

Redirect 组件

<Redirect>组件用于路由的跳转,即用户访问一个路由,会自动跳转到另一个路由。

<Route path="inbox" component={Inbox}>
  {/* 从 /inbox/messages/:id 跳转到 /messages/:id */}
  <Redirect from="messages/:id" to="/messages/:id" />
</Route>

现在访问 /inbox/messages/5,会自动跳转到/messages/5。

IndexRedirect组件用于访问根路由的时候,将用户重定向到某个子组件。

<Route path="/" component={App}>
  <IndexRedirect to="/welcome" />
  <Route path="welcome" component={Welcome} />
  <Route path="about" component={About} />
</Route>

用户访问根路径时,将自动重定向到子组件welcome。

Link

Link组件用于取代<a>元素,生成一个链接,允许用户点击后跳转到另一个路由。它基本上就是<a>元素的React 版本,可以接收Router的状态。

render() {
  return <div>
    <ul role="nav">
      <li><Link to="/about">About</Link></li>
      <li><Link to="/repos">Repos</Link></li>
    </ul>
  </div>
}

如果链接到根路由/,不要使用Link组件,而要使用IndexLink组件。

histroy 属性

Router组件的history属性,用来监听浏览器地址栏的变化,并将URL解析成一个地址对象,供 React Router 匹配。
history属性,一共可以设置三种值。

  • browserHistory
  • hashHistory
  • createMemoryHistory

如果设为hashHistory,路由将通过URL的hash部分(#)切换,URL的形式类似example.com/#/some/path

如果设为browserHistory,浏览器的路由就不再通过Hash完成了,而显示正常的路径example.com/some/path 但是,这种情况需要对[服务器改造])。

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

推荐阅读更多精彩内容