Angular


title: Angular
tags:

  • Angular
  • JS

Angular

简介

  • 一款非常优秀的前端高级 JS 框架
  • 最早由Misko Hevery等人创建
  • 09被Google收购
  • 可以轻松构建 SPA 应用程序
  • 其核心就是通过指令扩展HTML,通过表达式绑定数据到HTML

SPA

  • single page application 单页应用程序
//根据url中锚点值的变化,动态的请求不同的数据
<a href="#find"></a>
window.addEventListener("hashchange",function(){
//hashchange监听url中锚点值变化的事件
    var hash= location.hash;
    //location.hash, location.href
    switch(hash){
        case '#find':
            $.get('find.json',function(data){
                console.log(data);
            },'json');
        break;
        case:...;
    }
})

指令

  • 指令:在angular中以ng-开头的html标签属性
    • ng-app: 选择angular去管理哪一部分的html代码, 管理的是ng-app所在元素的子元素及其本身
    • ng-model: 指定一个属性值,这个属性就表示当前的value值,只能用在input中和select中
    • ng-init: 可以对数据进行初始化操作,给一个默认值
    • ng-click: 注册点击事件
<!-- 约定ng-app -->
<body ng-app>
    <!-- 获取值ng-model -->
    <input type="text" ng-model="val">
    <!-- 添加点击事件ng-click -->
    <input type="text" value="+1" ng-click="myVal-0+1">
    <div>{{val}}</div>
    <!-- 初始化ng-init -->
    <div ng-init="val=1"></div>
</body>
<!-- 引包 -->
<script src="./libs/angular.js"></script>

模块

  • 创建模块var app = angular.module('模块名',[])
  • 如果不依赖其他模块,也需要提供一个空的数组
  • 需要在ng-app指令的属性值上写我们的模块名
  • 模块的划分方式
    1. 按照项目的功能去划分模块
    2. 按照项目中文件的类型去划分模块

控制器

  • 创建控制器app.controller('控制器的名字',function($scope){})
  • 要在它所在标签或者父标签上加上ng-controller指令,ng-controller的值就是我们想要显示的数据模型所在控制器的名字

双向数据绑定

  • 数据模型($scope.属性)的改变,会影响内容的显示(文本框的值)
  • 改变文本框的值,对应的数据模型发生了改变
<body ng-app="hello">
    <input type="text" ng-model="name">
    <span>{{name}}</span>
    <input type="button" value="打印值" ng-click="getName()">
    <input type="button" value="改变为小红" ng-click="setName()">
    <script src="./libs/angular.js"></script>
    <script>
        // 创建模块
        var app=angular.module('hello',[]);
        // 创建控制器
        app.controller('helloController',function($scope){
            // 初始化数据模型
            $scope.name="小明";
            // 初始化行为模型
            $scope.getName=function(){
                console.log($scope.name)
            };
            $scope.setName=function(){
                $scope.name="小红"
            }
        })
    </script>
</body>

MVC 思想

  • M : Model: 存储,获取数据
  • V : View 视图,把数据呈现给用户
  • C : Controller 做一些控制和调度的操作
  • MVC只是一种思想,只是约定了我们代码应该如何去组织,让我们代码的每一部分都有一个明确的职责,用利于后期的维护性
<body ng-app="app">
  <!-- view 开始 -->
  <table ng-controller="demoController">
    <tr><td>用户名: <input type="text" ng-model="username"></td></tr>
    <tr><td>密码: <input type="text" ng-model="userpwd"></td></tr>
    <tr><td>用户类型:
        <select ng-model="type">
          <option value="tmp01">学生</option>
          <option value="tmp02">老师</option>
          <option value="tmp03">校长</option>
        </select>
    </td></tr>
    <tr><td>注册协议: <input type="checkbox" ng-model="isAgree"></td></tr>
    <tr><td><input type="button" value="注册" ng-click="register()"></td></tr>
    <tr><td>{{msg}}</td></tr>
  </table>
  <!-- View 结束 -->
  <script src="libs/angular.js"></script>
  <script>
    var app = angular.module('app',[])
    // Controller 开始
    app.controller('demoController',function($scope){
      // 初化数据模型
      $scope.username = '';
      $scope.usertype = '';
      $scope.userpwd = '';
      $scope.isagree = false;
      $scope.msg = ''
      // 初始化行为模型
      $scope.register = function(){
        if($scope.userpwd.length<6){
          $scope.msg='密码太短,不安全!';
          return
        }
        // 准备存储数据
        // 调用用Model里的方法
        var u = new User($scope.username,$scope.userpwd,$scope.type);
        var result = u.save();
        if(result){
          $scope.msg = '注册成功!'
        }else{
          $scope.msg = '注册失败!'
        }
      }
    })
    // Controller 结束
    // Model 开始
    function User(name,pwd,type){
      this.name = name;
      this.pwd = pwd;
      this.type = type
    }
    User.prototype.save = function(){
      // 判断用户名是否存在
      var str = localStorage.getItem('myusers')||'[]';
      // 注意'[]'
      var arr = JSON.parse(str);
      for (var i = 0; i < arr.length; i++) {
        if(arr[i].name===this.name){
          return 
        }
      }
      arr.push({name:this.name,pwd:this.pwd,type:this.type});
      localStorage.setItem('myusers',JSON.stringify(arr));
      return true
    }
  </script>
</body>

Angular开发流程回顾

  • 1.引包:引入angular.js文件
  • 2.约定:加上ng-app指令,告诉angular要管理页面哪一部分代码
  • 3.创建模块:在js中创建模块,给页面中的ng-app指令一个值,这个值就是这个模块的模块名
  • 4.创建控制器:在js中创建控制器,需要在页面上加上ng-controller指令,指令的值为控制器的名字
  • 5.建模,(数据模型,行为模型)根据页面结构,抽象出具体的js对象.
  • 6.初始化,通过$scope做一些初始化操作
  • 7.通过ng-model , ng-click , 插值表达式 把$scope的属性在页面展示出来
  • 8.在js写一些具体的逻辑

augular.element (不推崇)

  • (jqLite对象) 类似于jq,但是要求传入的参数是一个原生的dom对象,而不是选择器

$scope

  • 视图和控制器之间的数据桥梁,用于在视图和控制器之间传递数据,用来暴露数据模型(数据,行为)

正是因为$scope在Angular中大量使用甚至盖过了C(控制器)的概念,所以很多人把Angular称之为MVVM框架,$scope 实际上就是MVVM中所谓的VM(视图模型)

控制器

传统的方式创建控制器

    // 创建控制器(1.2.x版本)
    // angular会把全局的函数当作控制器
    function demoController($scope){
      $scope.name = '小明'
    }

面向对象的方式创建控制器

<!-- 这里的obj 代表控制器中回调函数new 出的对象 -->
<div ng-controller="demoController as obj">
  <p>{{myname}}</p>
  <p>{{obj.name}}</p>
</div>
    var app = angular.module('myApp', [])
    // angular会把这二个参数当作构造函数使用
    app.controller('demoController', function($scope){
      $scope.myname='小红'
      this.name = '小明'
    })

安全的方式创建控制器

  • 为了避免压缩后代码无法运行
    // 把第二个参数改为一个数组,在数组把我们需要的参数的名字写上
    // 回调函数就写在数组的最后一个元素上
    // 数据中传入的元素的顺序,要和function的中顺序一一对应
    app.controller('demoController',['$scope','$log',function($scope,$log){
      $scope.msg = 'hello World!'
      $log.log('哈哈哈哈!')
      //注意$log.log()
    }])
// 注意是'$scope'

指令

ng-bind

  • <p ng-bind="msg"></p>

解决表达式闪烁问题,浏览器不会把标签的属性显示出来,angular会把ng-bind对应的数据显示到所在标签中间

ng-cloak

  • <div class="ng-cloak">{{msg}}</div>

也可以解决表达闪烁问题,注意ng-cloak是样式,我们要先给ng-cloak设置display:none,angular在解析表达式之后会把页面上的ng-cloak样式移除,这样ng-cloak对应的样式就不生效了

ng-repeat

  • 能够把一组数据直接渲染到页面上,不需要我们拼接字符串
  • ng-repeat="item in users",item对应是遍历users时的每一条数据,users是我们要遍历的数据(是一个数组)
<body ng-app="myApp">
  <div ng-controller="demoController">
    <ul>
      <li ng-repeat="item in users" >
        {{item.name}} {{item.age}}
      </li>
    </ul>
  <ul>
    <li ng-repeat="item in obj">
      {{item.name}} {{item.age}}
    </li>
  </ul>
  <ul>
    <li ng-repeat="item in arr track by $index">
      {{item}} {{$index}}
    </li>
  </ul>
  </div>
  <script src="libs/angular.js"></script>
  <script>
    var app = angular.module('myApp', [])
    app.controller('demoController',['$scope',function($scope){
      $scope.users = [
        {name:'小明',age:18},
        {name:'小红',age:18},
        {name:'小朋',age:28},
        {name:'小月',age:19},
        {name:'小黑',age:18},
        {name:'小白',age:20}
      ]
      $scope.obj = {
        xm:{name:'小明',age:18},
        xh:{name:'小红',age:28},
        xt:{name:'小天',age:10},
        xy:{name:'小月',age:38}
      }
      $scope.arr = [1,2,3,4,5,1]
    }])
    // 注意:item in arr track by $index
  </script>
</body>

  • ng-repeat 在遍历时会提供以下值:
    • $odd : 为true时,表明当前数据是否是第[奇]数条
    • $even: 为true时,表明当前数据是否是第[偶]数条
    • $first: 为true时,表明当前数据是否是第1条
    • $last: 为true时,表明当前数据是否是最后一条
    • $middle: 为true时,表明当前数据是否是中间的数据
      <li class="{{ $odd ?'red':'green'}}" ng-repeat="item in data">
        {{item.name}},{{item.age}}
      </li>

ng-class

  • 动态的添加class样式,以对象的形式书写,angular会把属性值为true的属性名当作样式添加到class
    <!--  ng-class,动态的添加class样式,
      以对象的形式书写,angular会把属性值为true的属性名当作样式添加到class-->
    <li ng-class="{red:item.age>=20, green:item.age>=10&&item.age<20,blue:item.age<10}" ng-repeat="item in data">
      {{item.name}},{{item.age}}
    </li>
    <!-- 注意格式ng-class="{classname:true,classname2:true,...}" -->

ng-show/ng-hide

  • ng-show,控制元素的显示或隐藏,值为true时显示,为false隐藏,ng-hide作用是相反的(只是设置display:none来隐藏元素)
<body ng-app="myApp">
  <div ng-controller="demoController">
    <p ng-show="isShowing">hello</p>
    <button ng-click="showOrHide()">显示/隐藏</button>
  </div>
  <script src="libs/angular.js"></script>
  <script>
    var app = angular.module('myApp', [])
    app.controller('demoController', ['$scope', function($scope){
        $scope.isShowing= true;
        $scope.showOrHide=function(){
          $scope.isShowing = !$scope.isShowing
        }
    }])
  </script>
</body>

ng-if

  • 与ng-show用法一致,注意当值为false时,会将当前dom元素移除

ng-switch

  • 当ng-switch-when对应的值等于ng-switch对应值时,当前dom元素就显示
<body ng-app="myApp">
<div ng-controller="demoController">
    <div ng-switch="name">
        <div ng-switch-when="小明">
            我是小明
        </div>
    </div>
</div>
<script src="libs/angular.js"></script>
<script>
    var app = angular.module('myApp', [])
    app.controller('demoController',['$scope', function($scope){
        $scope.name = '小明'
    }])
    // 注意ng-switch-when
</script>

其他常用指令

  • ng-model:双向数据绑定
  • ng-checked:单选/复选是否选中(单向数据绑定,界面操作不会影响数据模型的值)
  • ng-selected:是否选中(单向数据绑定)
  • ng-disabled:是否禁用
  • ng-readonly:是否只读

常用事件指令

  • ng-blur:失去焦点
  • ng-focus:获得焦点
  • ng-change:内容改变
  • ng-copy:复制
  • ng-click: 单击
  • ng-dblclick:双击
  • ng-submit:form表单提单

指令的其他使用方式

  • 兼容H5,在使用angular指令时,只需要在原先的指令前加上data-或x-,如:data-ng-app,x-ng-click

todomvc案例

todomvc功能分析

  1. 任务的展示
  2. 添加任务
  3. 删除任务
  4. 修改任务内容
  5. 切换任务完成与否的状态
  6. 批量切换任务完成与否的状态
  7. 显示未完成的任务数
  8. 清除所有已完成任务
    • 注意: 在循环删除数组长度,会导致循环条件改变,也会导致元素原来的索引改变
  9. 切换显示不同状态的任务

过滤器(filter)

  • 格式化数据
  • 过滤数据(filter)
  • currency,date
  <!-- 在数据模型后加上|  再加上过滤器的名字 
        也可以在过滤器名字后指定参数,参数是写在冒号后面的-->
  <p>{{money | currency : '¥'}}</p>
  <p>{{myDate | date : 'yyyy年MM月dd日 HH:mm:ss'}}</p>
  • lowercase 转换成小写,uppercase 转换成大写,number 四舍五入
  • limitTo
  <!-- limitTo第一个参数,表明显示多少个字,第二个参数表示,从第几个字开始显示(索引从0开始) -->
  <p>{{msg | limitTo : 5 : 2}}...</p>
  • orderBy 及 json
 <!--  json格式化显示json数据,参数指定缩近的长度 -->
 <pre>{{myJson | json : 8}}</pre>
 <!-- orderBy对数据进行排序,参数,给+号就按正序排,- 就按倒序排 -->
 <span ng-repeat="item in arr | orderBy:'-'">{{item}},</span>
  • 在js中使用过滤器
     app.controller('filterController', ['$scope','$filter',function($scope,$filter){// $filter 需要在控制器的回调中传入
        $scope.money = 9998;
        // 可以调用不同的过滤器得到相应的结果
        // 参数是一个过滤器的名字
        // 返回值是一个方法
        // 后面括号里的第一个参数是需要处理的数据
        // 后面括号里的的第二个参数是当前过滤器本身需要的参数
        // $filter('过滤器名称')(需要过滤的数据,filter 参数)
        $scope.result =  $filter('currency')($scope.money,'¥')
    }])
  • filter

数据模型 | filter : {key:value}

<body ng-app="filterApp" ng-controller="fitlerController">
  <div>
    <input type="text" ng-model="search">
    <ul>
      <li ng-repeat="item in todos | filter : {completed:true} ">
        {{item.name}},{{item.completed}}
      </li>
      <!-- <li ng-repeat="item in todos | filter : search ">
        {{item.name}},{{item.completed}}
      </li> -->
    </ul>
    <!--  如果指定一个布尔值,或者字符串就是全文匹配 -->
    <!-- 数据精确过滤  参数:1、scope的属性,2、自定的字符串  3、自定的对象 {}-->
    <!-- 会到对应的todos中寻找,如果当前元素有completed属性且值 为true就会被显示出来。(只会到completed属性中寻找) -->
  </div>
  <script src="libs/angular.js"></script>
  <script>
      var app = angular.module('filterApp', [])
      app.controller('fitlerController', ['$scope',function($scope){
          $scope.search='';
          $scope.todos = [
              {id:1,name:'吃饭',completed:true},
              {id:2,name:'睡觉吃饭',completed:true},
              {id:3,name:'打豆豆',completed:false},
              {id:4,name:'学习', completed:true},
              {id:5,name:'喝水,true',completed:false}
          ]
      }])
  </script>
</body>

$watch 监视数据模型的变化

<body ng-app="hello">
  <div ng-controller="helloController">
    <input type="text" ng-model="name">
    <input type="text" ng-model="age">
    <button>测试</button>
  </div>
  <script src="libs/angular.js"></script>
  <script>
    var app = angular.module('hello', [])
    app.controller('helloController',['$scope',function($scope){
      $scope.name = '小明'
      $scope.age = 18
      // $watch可以用来监视数据模型的变化
      // 第一个参数: 数据模型对应的名字(字符串形式)
      // 第二个参数: 相应的数据模型变化就会调用这个函数
      // 默认会直接执行一次回调函数
      $scope.$watch('name',function(now,old){
        // 第一个参数是变化后的值
        // 第二个参数是变化前的值
        console.log(now,old)
      })

      $scope.getAge = function(){
        return $scope.age
      }
      // 也能够监视$scope.属性中的方法的返回值
      $scope.$watch('getAge()',function(now,old){
        console.log(now,old)
      })
      // $watch监视的是$scope的属性,如果是一个普通变量是无法监视的
      // function getName(){
      //   return $scope.name
      // }
      // $scope.tmp = getName
      // $scope.$watch('tmp()',function(now,old){
      //   console.log(now,old)
      // })
    }])
  </script>
</body>

自定义属性

<body ng-app="directiveApp">
  <!-- 以属性形式使用 -->
  <!-- <div my-btn></div> -->
  <!-- 以样式名形式使用 -->
  <!-- <div class="my-btn"></div> -->
  <!-- 以自定义标签形式使用 -->
  <my-btn mystyle="red">咦</my-btn>
<script id='tpl' type='text/ng-template'>
  <div>
    <!-- <p class="tmp"> 我是在模板里定义的p,没有写ng-transclude</p> -->
    <p class="{{mystyle}}">hello</p>
    <p ng-transclude>hey</p>
  </div>
</script>
<script src="libs/angular.js"></script>
<script>
    var app = angular.module('directiveApp', [])
    // 创建自定义指令 directive
    // 第一个参数:是指令的名字,必须是驼峰命名法,使用时把大写改成小写,在原来大写前加上-
    // 第二个参数:和控制器的第二个参数类似
    app.directive('myBtn', [function(){
        // 在这里直接return 一个对象就可以了
        return {
            // template:'hello'
            // templateUrl:'template.html'
            templateUrl:'tpl',
            restrict:'ACE',
            replace:true,
            transclude: true,
            scope:{
              // tmp:'@mystyle',
              mystyle:'@',
            },
            link:function(scope,element,attributes){
                scope.msg="hello"
                console.log(element)
                element.on('click',function(){
                    alert('你点我了!')
                })
                console.log(attributes)
            }
        }
    }])
    //注意directive,type='text/ng-template',transclude
</script>
</body>

自定义指令中回调里返回的对象的属性

  • template: 需要提供一个html字符串,会被添加到当前页面使用了自定义指令的位置

  • templateUrl:

    • 需要提供一个html文件路径,angular会发请求,请求对应的文件,把文件内容作为模板插入到自定义指令中间
    • 提供一个script标签的id, angular会把script标签中的内容作为模板插入到自定义指令中间,注意要改变script标签的type="text/ng-template"
  • restrict: 需要提供一个字符串,限制自定义指令的使用形式

    • A : Attribute 表示只能以属性的形式使用
    • C : Class 表示只能以类样式名的形式使用
    • E : Element 表示只能以自定义标签的形式使用
    • ACE : 如果希望多种方式合适,就把对应值组合在一起
  • replace:需要提供一个布尔值,为true时,模板会被用来替换自定义指令所在标签,否则是插入到自定义指令中间

  • transclude: 需要一个布尔值, 为true时会将自定义标签中的内容插入到模板中拥有ng-transclude指令的标签中间

  • scope:需要一个对象: 可以用来获取自定义指令的属性值,

    • 给当前对象添加一个属性(如:tmp),属性值以@开头,后面跟上自定义指令的属性名
      然后就可以在模板中使用{{tmp}} 来得到对应的属性值,注意''
      • scope: { tmp:'@mystyle'} {{tmp}}
      • scope: { mystyle:'@'} {{mystyle}}
  • link: 需要一个function 这是function在angular解析到相应指令时就会执行一次,

    • scope :类似于$scope,只不过scope的属性 只能在模板中使用
    • element : 自定义指令所在标签对应的对象(jqLite),指向模板最外层的对象,如果replace为treu,指向的就是自定义指令所在标签
    • attributes : 包含了自定义指令所在标签的必有属性

服务

  • 创建服务
  var app = angular.module('service',[])
  // 第一个参数:服务的名字
  // 第二个参数里的function: 
  // angular会把这个function当作构建函数,angular会帮助我们new这个构建函数,然后得到一个对象
  app.service('MyService', [function(){
    this.name = '小明'
  }])
  • 使用服务
  var app = angular.module('todosApp', ['service'])
  app.controller('todosController',['MyService',function(MyService){
    // 这个MyService就是,对应的'MyService'时的回调函数new出的对象
    console.log(MyService)
}])

路由

  • 根据url中不同的锚点值,在页面显示不同的内容

路由使用

<body ng-app="myApp">
<div ng-view></div>
<script src="libs/angular.js"></script>
<script src="libs/angular-route.js"></script>
<script>
    var app=angular.module('myApp',['ngRoute'])
    //注意['ngRoute']

    // $location.url()可以得到url中锚点值#后的部分
    // 配置路由规则
    app.config(['$routeProvider',function($routeProvider){
    // 第一个参数:对应的url中锚点值
    // 当angular检测到url中锚点变为/a,就会把template对应的内容插入到页面拥有ng-view指令的标签中
        $routeProvider
            .when('/a',{
                template:'<div>{{msg}}</div>',
                controller:'demoController'
                // 指定一个控制器的名字,
                // 当前url中锚点值为/a时就会执行控制器中的回调函数
                // 我们可以直接在template/templateUrl对应的模板中使用该控制器中对应的$scope属性值
            })
            .when('/b',{
                template:'<div>hello</div>'
            })
    }])
    app.controller('demoController',['$scope',function($scope){
        $scope.msg="hi";
    }])
</script>
</body>

路由参数

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

推荐阅读更多精彩内容