React 入门

1.React 的学习资源

2.React

什么是React?

  • React 是一个用于构建用户界面的 JAVASCRIPT 库。
  • React主要用于构建UI,很多人认为 React 是 MVC 中的 V(视图)。
  • React 起源于 Facebook 的内部项目,用来架设 Instagram 的网站,并于 2013 年 5 月开源。
  • React 拥有较高的性能,代码逻辑非常简单,越来越多的人已开始关注和使用它。
  • 既可以开发浏览器应用,又可以开发移动应用

React 特点

  • 1.声明式设计 −React采用声明范式,可以轻松描述应用。
  • 2.高效 −React通过对DOM的模拟,最大限度地减少与DOM的交互。
  • 3.灵活 −React可以与已知的库或框架很好地配合。
  • 4.JSX − JSX 是 JavaScript 语法的扩展。React 开发不一定使用 JSX ,但我们建议使用它。
  • 5.组件 − 通过 React 构建组件,使得代码更加容易得到复用,能够很好的应用在大项目的开发中。
  • 6.单向响应的数据流 − React 实现了单向响应的数据流,从而减少了重复代码,这也是它为什么比传统数据绑定更简单。

什么是JSX?
React 使用 JSX(JavaScript XML) 来替代常规的 JavaScript。JSX 是一个看起来很像 XML 的 JavaScript 语法扩展。我们不需要一定使用 JSX,但它有以下优点:

  • JSX 执行更快,因为它在编译为 JavaScript 代码后进行了优化。
  • 它是类型安全的,在编译过程中就能发现错误。
  • 使用 JSX 编写模板更加简单快速。

3.React的HelloWorld

打开网址:https://facebook.github.io/react/docs/installation.html
官网中有如何搭建React的Helloworld。
index.html:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script src="https://unpkg.com/react@latest/dist/react.js"></script>
    <script src="https://unpkg.com/react-dom@latest/dist/react-dom.js"></script>
    <script src="https://unpkg.com/babel-standalone@6.15.0/babel.min.js"></script>
    <script type="text/babel" src="01.js"></script>

</head>
<body>
<div id="root"></div>

</body>
</html>

01.js:

//React组件化(可以重用),即自定义组件
class TextCompat extends React.Component{
    //组件的内容
    render(){
        return <div>Hello world!!!</div>
    }
}


class WrapperText extends React.Component{
    render(){
        //虚拟DOM(Document Object Model)
        //html标签,小写开头
        //自定义组件:大写开头
        return <p>
            <TextCompat></TextCompat>
            <span>jarry</span>
        </p>
    }
}


//绘制到页面中
//ReactDOM.render(<WrapperText></WrapperText>, document.body);
ReactDOM.render(<TextCompat/>, document.getElementById('root'));

流程:
1.编写组件
2.绘制到页面

ReactDOM.render(<TextCompat/>, document.getElementById('root'));

虚拟DOM
DOM:html标签
虚拟DOM即包括DOM又嵌套组件,和普通DOM的区别:html标签是小写,组件是大写开头
虚拟DOM的好处:

  • 1.跨平台(讲虚拟DOM翻译成对应平台的语言)
  • 2.组件化管理,适合大型项目

缺点:

4.React的状态

State(状态)
React 把组件看成是一个状态机(State Machines)。通过与用户的交互,实现不同状态,然后渲染 UI,让用户界面和数据保持一致。
React 里,只需更新组件的 state,然后根据新的 state 重新渲染用户界面(不要操作 DOM)。
不需要直接操作DOM,而是通过修改state,自动更新界面

1.初始化状态
2.改变状态
3.获取状态,当状态改变的时候,会重绘页面

注意需要安装React dev tools的插件,来查看错误日志
需要用React.createClass,而不是用继承的方式,因为这个会走生命周期流程。

案例:
点击切换,喜欢不喜欢?

//实例化组件对象过程中,调用getInitialState设置state对象的初始值
var Text = React.createClass({
    //设置状态的初始值
    getInitialState : function(){
        return {isLike:false};
    },
    //点击事件回调
    handleClick : function(){
        //改变状态
        this.setState({isLike:!this.state.isLike});
    },
    //当状态改变时,会重新调用render函数,重绘
    render : function(){
        //获取状态
        var text = this.state.isLike ? "喜欢" : "不喜欢";
        return <p onClick={this.handleClick}>你{text}吗?</p>
    }
});

ReactDOM.render(<Text/>, document.getElementById("myDiv"));

上面例子的加载流程:
1.getInitialState(初始化,设置组件的state的值,给了一个对象)
2.render(不喜欢)

点击之后的流程
1.handleClick(点击回调)
2.setState(改变状态)
3.render(喜欢)

5.Props(属性)

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

var Text = React.createClass({
    render : function(){
        return <p>I love {this.props.name}</p>;
    }
});

ReactDOM.render(<Text name="Jason"/>, document.getElementById("myDiv"));

案例:
实现在输入框中,输入内容,上面的文字控件也跟着改变

//子组件
var TextComponent = React.createClass({
    render : function(){
        return <div>Hello {this.props.text}!</div>;
    }

});

//父组件
var WrapperComponent = React.createClass({
    //state初始化
    getInitialState : function(){
        return {text:''};
    },
    //内容改变回调
    handleChange : function(e){
        //e 是Event事件对象,target是指事件的目标对象
        //改变状态
        this.setState({text:e.target.value});
    },
    render : function(){
        return <div>
            <TextComponent text={this.state.text}/>
            <input type="text" onChange={this.handleChange}/>
        </div>;
    }

});

ReactDOM.render(<WrapperComponent/>, document.getElementById("myDiv"));

例子中传参流程
1.handleChange(父组件回调)
2.setState(修改父组件的状态)
3.render(父组件重新渲染,子组件也会渲染)
3.把父组件的状态值,作为子组件的属性值传入
4.render(子组件内容改变)

6.React组件生命周期

实例化

首次实例化

  • getDefaultProps
  • getInitialState
  • componentWillMount
  • render
  • componentDidMount

实例化完成后的更新

  • getInitialState
  • componentWillMount
  • render
  • componentDidMount

存在期
组件已存在时的状态改变

  • componentWillReceiveProps
  • shouldComponentUpdate
  • componentWillUpdate
  • render
  • componentDidUpdate

销毁&清理期

  • componentWillUnmount

7.生命周期共提供了10个不同的API。

1.getDefaultProps
作用于组件类,只调用一次,返回对象用于设置默认的props,对于引用值,会在实例中共享。

2.getInitialState
作用于组件的实例,在实例创建时调用一次,用于初始化每个实例的state,此时可以访问this.props。

3.componentWillMount
在完成首次渲染之前调用,此时仍可以修改组件的state。

4.render
必选的方法,创建虚拟DOM,该方法具有特殊的规则:

  • 只能通过this.props和this.state访问数据
  • 可以返回null、false或任何React组件
  • 只能出现一个顶级组件(不能返回数组)
  • 不能改变组件的状态
  • 不能修改DOM的输出

5.componentDidMount
真实的DOM被渲染出来后调用,在该方法中可通过this.getDOMNode()访问到真实的DOM元素。此时已可以使用其他类库来操作这个DOM。
在服务端中,该方法不会被调用。

6.componentWillReceiveProps
组件接收到新的props时调用,并将其作为参数nextProps使用,此时可以更改组件props及state。

    componentWillReceiveProps: function(nextProps) {
        if (nextProps.bool) {
            this.setState({
                bool: true
            });
        }
    }

7.shouldComponentUpdate
组件是否应当渲染新的props或state,返回false表示跳过后续的生命周期方法,通常不需要使用以避免出现bug。在出现应用的瓶颈时,可通过该方法进行适当的优化。
在首次渲染期间或者调用了forceUpdate方法后,该方法不会被调用

8.componentWillUpdate
接收到新的props或者state后,进行渲染之前调用,此时不允许更新props或state。

9.componentDidUpdate
完成渲染新的props或者state后调用,此时可以访问到新的DOM元素。

10.componentWillUnmount
组件被移除之前被调用,可以用于做一些清理工作,在componentDidMount方法中添加的所有任务都需要在该方法中撤销,比如创建的定时器或添加的事件监听器。

8.传参

通过属性Props可以在父组件中给子组件设置属性值,也就是将父组件的值传递给子组件。但是要解决子组件访问父组件的方法,可以通过回调函数解决,这就和Java的接口一样。
他的主要思路:子组件委托父组件处理。

下面通过一个案例来实现

  • 下拉列表(子组件)的数据发生改变,表单(父组件)能够获取到,用于后面的提交子组件向父组件传递参数

1.下拉选择组件:

//表单的子组件
var ChildGenderSelect = React.createClass({
    render : function(){
        return <select onChange={this.props.handleSelectChange}>
            <option value="1">男</option>
            <option value="0">女</option>
        </select>;
    }
});

2.表单的组件:

//提交数据的两种做法:
//1.直接提交表单,跳转,整个页面刷新(过时的做法)
//2.屏蔽表单的默认提交行为,通过ajax提交数据,服务器响应成功之后在跳转(类似于Android)
var ParentForm = React.createClass({
    getInitialState : function(){
        return {gender:0};
    },
    handleChange : function(e){
        //保存到state
        this.setState({gender:e.target.value});
    },
    handleSubmit : function(e){
        //屏蔽表单的默认提交行为
        e.preventDefault();
        //ajax发起请求,提交数据
        /*var request = new XMLHttpRequest();
        request.open("GET","test.json?gender="+this.state.gender);
        request.onreadystatechange = handler;
        request.responseType = "json"; //服务器响应数据的类型 json
        request.setRequestHeader("Accept","application/json");
        request.send();

        //回调
        function handler(){
            //4(完成)响应内容解析完成
            if(this.readyState !== 4){
                return;
            }
            if(this.status == 200){
                //请求成功:显示数据
                console.log("ok");
            }
        }*/
    },
    render : function () {
        return <form onSubmit={this.handleSubmit}>
            <ChildGenderSelect handleSelectChange={this.handleChange}></ChildGenderSelect><br/>
            <button type="submit">提交</button>
        </form>;
    }
});

3.将表单组件渲染到页面:

ReactDOM.render(<ParentForm></ParentForm>,document.body);

4.案例的流程:
(1).通过handleSelectChange属性,传入父组件的handleChange函数给子组件。
(2).当子组件的onChange事件触发,调用this.props.handleSelectChange->父组件的handleChange函数。

9.表单提交和函数复用

案例:

  • 点击提交按钮,提交输入框输入的内容,通过Ajax请求提交

1.方式一:不可控组件
主要思路:通过ref获取组件

var FormComponent = React.createClass({
    //处理表单提交
    handleSubmit : function(e){
        e.preventDefault();
        //ref类似于id,是一个唯一标示 React.findDOMNode
        var text = this.refs.input_name.value;
        alert(text);
    },
    render : function(){
        return <form onSubmit={this.handleSubmit}>
            <input type="text" ref="input_name" defaultValue="Hello..."/><br/>
            <button type="submit">提交</button>
        </form>;
    }
});

ReactDOM.render(<FormComponent></FormComponent>,document.body);

2.方式二:可控组件(和MVVM data binding很类似)
主要思路:把数据存储在状态中(通过事件监听,进行数据绑定),需要时,从状态中获取

var FormComponent = React.createClass({
    getInitialState : function () {
        return {text:''};
    },
    handleChange : function(e){
        //保存到state
        this.setState({text:e.target.value});
    },
    handleSubmit : function(e){
        e.preventDefault();
        alert(this.state.text);
    },
    render : function(){
        return <form onSubmit={this.handleSubmit}>
            <input type="text" defaultValue="Hello..." onChange={this.handleChange}/><br/>
            <button type="submit">提交</button>
        </form>;
    }
});

ReactDOM.render(<FormComponent></FormComponent>,document.body);

随之产生的问题:多个控件需要多个事件处理函数,如何做到事件处理函数的复用?

3.方式三:事件处理函数的复用方式1
在方式二的基础上进行改进,让子控件可以实现复用,并保存对应的属性值。
思路:bind返回改变了上下文this后的函数

var FormComponent = React.createClass({
    getInitialState : function () {
        return {
            username:'',
            gender:0,
            agree:true
        };
    },
    //key ->'username' ....
    handleChange : function(key,e){
        //this->FormComponent对象
        //保存到state
        var obj = {};
        obj[key] = e.target.value;
        this.setState(obj);
    },
    handleSubmit : function(e){
        e.preventDefault();
        console.log(this.state);
    },
    //多个控件的事件响应,共用这个函数
    render : function() {
        return <form onSubmit={this.handleSubmit}>
            <label htmlFor="username">输入用户名:</label>
            <input id="username" type="text" onChange={this.handleChange.bind(this,'username')}/><br/>
            <label htmlFor="gender">请选择性别:</label>
            <select id="gender" onChange={this.handleChange.bind(this,'gender')}>
                <option value="1">男</option>
                <option value="0">女</option>
            </select><br/>
            <label htmlFor="agree">是否同意:</label>
            <input id="agree" type="checkbox" onChange={this.handleChange.bind(this,'agree')} /><br/>
            <button type="submit">提交</button>
        </form>;
    }

});

ReactDOM.render(<FormComponent></FormComponent>,document.body);

注意:this的作用域问题,如果this指定的函数是非箭头函数,会导致作用域不正确,子控件拿不到对应的函数和属性值。

4.方式四:事件处理函数的复用方式2
思路:指定属性,比如说name属性区分不同的组件

var FormComponent = React.createClass({
    getInitialState : function () {
        return {
            username:'',
            gender:0,
            agree:true
        };
    },

    handleChange : function(e){
        var obj = {};
        obj[e.target.name] = e.target.value;
        this.setState(obj);
    },
    handleSubmit : function(e){
        e.preventDefault();
        console.log(this.state);
    },
    //多个控件的事件响应,共用这个函数
    render : function() {
        return <form onSubmit={this.handleSubmit}>
            <label htmlFor="username">输入用户名:</label>
            <input id="username" type="text" name="username" onChange={this.handleChange}/><br/>
            <label htmlFor="gender">请选择性别:</label>
            <select id="gender" name="gender" onChange={this.handleChange}>
                <option value="1">男</option>
                <option value="0">女</option>
            </select><br/>
            <label htmlFor="agree">是否同意:</label>
            <input id="agree" name="agree" type="checkbox" onChange={this.handleChange} /><br/>
            <button type="submit">提交</button>
        </form>;
    }

});

ReactDOM.render(<FormComponent></FormComponent>,document.body);

10.动画

案例:让一个文字,在3秒之类从左到右移动一段距离
思路:用定时器,不断改变属性值,并渲染。

var MyComponent = React.createClass({
    getDefaultProps : function(){
        return {
            position:100, //marginLeft目标值,组件实现可配置
            time:10
        };
    },
    getInitialState : function () {
        return {position:0};  //marginLeft开始值
    },
    render : function(){
        var style = {
            color:'red',
            marginLeft:this.state.position //左外边距
        };
        return <div style={style}>This will animated!</div>;
    },
    //动画函数,不断改变state的position属性
    transformComponnent : function () {
        if(this.state.position < this.props.position){
            this.setState({
                position : ++this.state.position
            });
        }else{
            //动画完成,取消定时器
            clearInterval(this.timer);
        }
        console.log("transformComponnent");
    },
    //渲染完成
    componentDidMount : function () {
        //开启定时器
        this.timer = setInterval(this.transformComponnent,this.props.time);
    }
});


ReactDOM.render(<MyComponent position={200} time={20}></MyComponent>,document.body);

流程
1.初始化控件,执行生命周期中的getDefaultProps 和getInitialState ;
2.控件渲染完成,执行componentDidMount ;
3.开启定时器,不断执行transformComponnent ;
4.保存状态setState;
5.不断渲染render,渲染的时候marginLeft拿取状态值;

11.计时器案例

1.模块化
把一些类,函数,变量写到一个文件中,作为一个功能模块,当要使用这个模块,只需要引用。
nodejs不支持,用Bable6转es6为es5(js库,实现模块化),es6模块化(新的语法特性),node和chrome都不支持。

2.创建react工程
支持语法特性,非常便利

npm install -g create-react-app
create-reate-app test
cd test

3.模块引入和导出
创建一个组件
class TimeDisplay extends React.Component{
}

引入:import React form 'react';

导出:export default TimeDisplay;

4.代码

this只有在运行时才确定
转为箭头函数,因为this的作用域是最外层的,比普通的function少了绑定this步骤;
在构造函数中对状态赋初始值,不能调用setState
TimeDisplay.js:

import React from 'react';

import DisplayLog from './DisplayLog';
import Button from './Button';
import formatTime from '../utils/formatTime';

class TimeDisplay extends React.Component{
    //在构造函数中对状态赋初始值
    constructor(props){
        super(props);
        //不能调用state
        this.state = {
            time:0,
            on:false,
            log:[] //数组
        };
    }

    //开始按钮
    handleToggle = ()=>{
        //已经开始,取消正在运行的定时器
        if(this.state.on){
            clearInterval(this.timer);
        }else{
            //否则开启
            //定时器,10ms累加1
            this.timer = setInterval(()=>this.setState({time:this.state.time+1}),10);
        }
        this.setState({on:!this.state.on});
    }
    //记录时间
    handleLogTime = ()=>{
        //存储在数组中
        this.state.log.push(this.state.time);
    }
    //清空记录
    handleClearLog = ()=>{
        this.setState({log:[]});
    }
    //重置
    handleReset = () =>{
        this.setState({time:0});
    }

    render(){
        var time = formatTime(this.state.time);
        return <div>
            <h1 className="display-time">{time}</h1>
            <div className="controls">
                <Button className={this.state.on ? "danger" : "success"} text={this.state.on ? "暂停" : "开始"} onClick={this.handleToggle}/>
                <Button className="warning"  onClick={this.handleReset}/>
                <Button className="primary" text="记录" onClick={this.handleLogTime}/>
                <Button className="undefined" text="清空" onClick={this.handleClearLog}/>
            </div>
            <DisplayLog log={this.state.log}/>
        </div>;
    }

    //监听键盘事件
    componentDidMount(){
        //内置对象
        window.addEventListener('keydown', e => e.preventDefault());
        window.addEventListener('keyup', e => {
            e.preventDefault();
            switch (e.keyCode){
                case 32: //space
                    this.handleToggle();
                    break;
                case 82:
                    this.handleReset();
                    break;
                case 13:
                    this.handleLogTime();
                    break;
                case 67:
                    this.handleClearLog();
                    break;
                default:
                    break;
            }
        });
    }

    //组件被移除,事件监听取消
    componentWillUnmount(){
        window.removeEventListener('keydown');
        window.removeEventListener('keyup');
    }

}

//在外部要使用TimeDisplay
export default TimeDisplay;

Button.js:
button的封装,数据、样式、事件的传递

import React from 'react';

class Button extends React.Component{
    //静态属性,给属性赋默认值
    static defaultProps = {
        onClick : null,
        className : '',
        text : '默认'
    };

    render(){
        return <button className={`Button ${this.props.className}`} onClick={this.props.onClick}>{this.props.text}</button>;
    }
}

export default Button;

DisplayLog.js:

import React from 'react';
import formatTime from '../utils/formatTime';

class DisplayLog extends React.Component{
    //log数组长度等于0,返回“空空如也”
    renderEmpty = () =>{
        return <span className="empty-log">空空如也...</span>;
    }

    //否则,把元素遍历(时间),得到一系列的<li>
    renderLog = () => {
        //<li>00</li>
        //<li>11</li>
        return this.props.log.map(item => {
            return <li className="log-item" >{formatTime(item)}</li>;
        });
    }

    render(){
        //log数组长度等于0,返回“空空如也”
        //否则,把元素遍历(时间),得到一系列的<li>
        //<ul>
        //  <li>00</li>
        //  <li></li>
        //</ul>
        const log = this.props.log.length === 0 ? this.renderEmpty() : this.renderLog();
        return <ul className="log">
            {log}
        </ul>;
    }
}

export default DisplayLog;

formatTime.js:

//将数组转为字符串,如果数字只有一位,会在第一个位置添加一个0
//9->9->09
const appendZero = n => n.toLocaleString({},{minimumIntegerDigits:2});

export default function(t = 0){
    const msec = appendZero(t % 100),
        sec = appendZero(parseInt((t/100) % 60)),
        min = appendZero(parseInt((t/6000) % 60)),
        hour = appendZero(parseInt(t/360000));
    return `${hour}:${min}:${sec}.${msec}`;
}

App.css

.App {
  text-align: center;
}

ul,li{
  list-style: none; /*去掉列表默认样式*/
  margin: 0px;
  padding: 0px;
}

.display-time{
  font-size: 45px;
  font-weight: bold;
  margin: 60px 0px;
}

.controls{
  background-color: #eee;
}

.Button{
  width: 130px;
  font-size: 20px;
  padding: 10px 20px;
  margin: 20px;
  border: none;
  border-radius: 4px;
  background-color: lightgreen;
  cursor: pointer;
}

.Button:hover{
  /*CSS3阴影*/
  box-shadow: 0 0 25px rgba(0,0,0,0.2);
}

.success{
  background-color: lightgreen;
}
.danger{
  background-color: hotpink;
}
.warning{
  background-color: gold;
}
.primary{
  background-color: skyblue;
}
.undefined{
  background-color: #e1e1e1;
}

.log{
  text-align: center;
  font-size: 30px;
  color: #e1e1e1;
}

/*log和empty-log都会应用这个样式*/
.log .empty-log{
  display: inline-block;
  padding: 50px 10px;
}

/*.log类下的li标签 */
/*.log > li{*/
.log-item{
  font-size: 25px;
  color: #000;
  border-bottom: 1px solid #eee;
  padding: 10px 0px;
}

/*伪类*/
/*悬浮*/
.log-item:hover{
  background-color: rgba(238, 238, 238, 0.5);
}

App.js

import React from 'react';
import './App.css';
import TimeDisplay from './components/TimeDisplay'

class App extends React.Component {
  render() {
    return <div className="App">
      <TimeDisplay />
    </div>;
  }
}

export default App;

12.常用的补充点

1.数组
数组的创建

var a = [];
var b = new Array();

数组的元素赋值

a[0] = 2;
a[1] = 10;
a.push(30);

清空

console.log(a);
a = [];
console.log(a);

map 遍历数组的函数

//item是数组的元素,i数组的索引,b是返回的数组
var b = a.map(function(item,i){
    return ++item;
});
console.log(b);

2.组件的两种创建方式
1.React.createClass
对应的属性和状态初始化方法:

getDefaultProps
getInitialState

2.extends Component
对应的属性和状态初始化方法:

static defaultProps
constructor

3.css样式
.log-item

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

推荐阅读更多精彩内容

  • 欢迎访问我的博客 早期,我们开发web应用,只能是通过请求服务器,服务端响应请求,返回一个页面,,每次浏览器都得对...
    惊鸿三世阅读 510评论 0 2
  • React简介 React是一个用于构建用户界面的JavaScript库,主要有以下几个特点: 声明式设计--Re...
    紫诺_qiu阅读 889评论 0 2
  • 现在最热门的前端框架,毫无疑问是React。在基于React的React Native发布一天之内,就获得了 50...
    Mycro阅读 1,000评论 3 6
  • 在React这股目前最热前端框架之风刮来之前,一直在Cocos2d-html5游戏和半路出家的Android应用的...
    hahafei阅读 360评论 0 2
  • 国师府门前。 姜萱焦急地走来走去,她时不时看看国师府,眉头紧皱,“你们说青琅到底有什么事,为什么还不出来,快急死了...
    苏诉阅读 601评论 1 2