Vue 实例和数据绑定

首先引入vue.js,然后通过构造函数 Vue 创建一个 Vue 实例,启动 vue

<div id="app"></div>
<script src="https://cdn.jsdelivr.net/npm/vue@2.5.16/dist/vue.js"></script>
<script>
  var app = new Vue({
    el: "#app", //element,指定一个DOM元素来挂在Vue实例,也可以是css语法
    data: {
      msg: "开始", //声明需要双向绑定的数据
    },
  });
</script>
  • 访问 vue 实例的属性: 以$开头,如app.$el
  • 访问data元素的属性: 直接 app.属性名,如app.msg

生命周期钩子

created:实例创建完成后调用,此阶段完成了数据的观测等---尚未挂载
mounted:挂载到实例上后调用,相当于$(document).ready()---刚刚挂载
beforeDestroy:实例销毁之前调用。主要解绑一些使用addEventListener监听的事件

文本插值和表达式

语法:使用双大括号(Mustache 语法){{}}是最基本的文本插值方法,它会自动将我们双向绑定的数据实时显示出来。
用法:只支持单个表达式,不支持语句和流控制

{{6 + 6}} //可以进行简单运算
{{ 6<3 ? msg :a}} //可以使用三元运算符
{{if(6>3){}}} //不行
{{var a = 3}} //不行

过滤器,指令和事件

一个实时显示当前时间的小 demo

<body>
  <div id="App">
    {{date}} <br />
    {{date | formatDate}}
  </div>
  <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
  <script>
    //在月份,日期,小时小于10的时候前面补0
    var addZero = function (value) {
      return value < 10 ? "0" + value : value;
    };
    var app = new Vue({
      el: "#App",
      data: {
        date: new Date(),
      },
      //定义一个过滤器
      filters: {
        //这里的value就是要过滤的数据
        formatDate: function (value) {
          //将传进来的value这个字符串转化为date类型
          var date = new Date(value);
          var year = date.getFullYear();
          var month = addZero(date.getMonth() + 1); //0代表1月,所以要加1
          var day = addZero(date.getDate());
          var hours = addZero(date.getHours());
          var min = addZero(date.getMinutes());
          var sec = addZero(date.getSeconds());
          //将整理好的数据返回
          return (
            year +
            "年" +
            month +
            "月" +
            day +
            "日" +
            hours +
            "时" +
            min +
            "分" +
            sec +
            "秒"
          );
        },
      },
      mounted: function () {
        var _this = this; //this代表的就是app这个Vue实例
        this.timer = setInterval(function () {
          _this.date = new Date();
        }, 1000);
      },
      beforeDestory: function () {
        if (this.timer) {
          clearInterval(this.timer);
        }
      },
    });
  </script>
</body>

过滤器

  • Vue支持在{{}}插值的尾部添加一小管道符|对数据进行过滤,经常用于格式化文本,比如字母全部大写、货币千位使用逗号分隔等。过滤的规则是自定义的,通过给Vue实例添加选项filters来设置
  • 可以有多个过滤器: {{data | filter1 | filter2}}
  • {{data | formatDate(arg1,arg2)}}中可以添加参数arg1ar2,对应于formatDate方法中的第二和第三个参数,因为第一个参数是需要处理的数据value

指令和事件

指令( Directives )是 Vue 模板中最常用的一项功能,它带有前缀v-,能帮我们快速完成 DOM 操作,循环渲染,显示和隐藏。

  • v-text:—————解析文本和{{ }}作用一样
  • v-html:—————解析 html
  • v-bind—————动态更新 HTML 元素上的属性,比如 id 和 class 等
  • v-on——————用来绑定事件监听器
v-on 具体介绍
在普通元素上, v-on 可以监听原生的 DOM 事件,除了 click 外,还有 dblclick, keyup, mousemove 等。表达式可以是一个方法名,这些方法都写在 Vue 实例的 methods 属性内,并且是函数的形式,函数内的 this 指向的是当前 Vue 实例本身,因此可以直接使用 this.xxx 的形式来访问或修改数据
vue 中用到的所有方法都定义在 methods 中

语法糖

v-bind:class = "xxx" ——> :class = "xxx"
v-on:click = "xxx" ——> @click = "xxx"
写法
v-text="xxx" 后面是加=
v-html="xxx" 后面是加=

计算属性

计算属性

双向绑定一些数据或表达式时,表达式如果过长,或逻辑更为复杂
时,就会变得雕肿甚至难以阅读和维护

<div>
    {{ text.split(',').reverse().join(’,’) }}
</div>

这里的表达式包含 3 个操作,并不是很清晰,所以在遇到复杂的逻辑时应该使用计算属性
所有的计算属性都以函数的形式写在 Vue 实例内的computed选项内,最终返回计算后的结果。

计算属性的用法

在一个计算属性里可以完成各种复杂的逻辑,包括运算、函数调用等,只要最终返回一个结果就可以。计算属性是可以依赖多个 Vue 实例的数据的,只要其中任一数据变化,计算属性就会重新执行,视图也会更新

<body>
  <div id="demo">总价{{prices}}</div>
  <script src="https://cdn.jsdelivr.net/npm/vue@2.5.16/dist/vue.js"></script>
  <script>
    //第二个vue实例,无需挂载到页面上,数据都可以在计算属性中进行访问
    var app2 = new Vue({
      el: "#hjhh",
      data: {
        msg: "我是app2的数据",
      },
    });
    var app1 = new Vue({
      el: "#demo",
      data: {
        // 第一个购物车
        package1: [
          { name: "ipad", price: 20, number: 4 },
          { name: "imac", price: 90, number: 3 },
        ],
        //第二个购物车
        package2: [
          { name: "iphone", price: 400, number: 9 },
          { name: "imac", price: 90, number: 3 },
        ],
      },
      // 定义计算属性
      computed: {
        prices: function () {
          var prices = 0;
          for (var i = 0; i < this.package1.length; i++) {
            prices += this.package1[i].price * this.package1[i].number;
          }
          for (var j = 0; j < this.package1.length; j++) {
            prices += this.package2[j].price * this.package2[j].number;
          }
          return prices + "----" + app2.msg; //访问到了app2这个vue实例的数据
        },
      },
    });
  </script>
</body>

计算属性的 getter 和 setter

每一个计算属性都包含-个 getter 和一个 setter,上面的购物车示例就是计算属性的默认用法 , 只是利用了 getter 来读取。在你需要时,也可以提供一个 setter 函数 , 此时手动修改计算属性的值就像修改一个普通数据那样时,就会触发这个 setter 函数,执行一些自定义的操作。

<body>
  <div id="vm">{{fullName}}</div>
  <script src="https://cdn.jsdelivr.net/npm/vue@2.5.16/dist/vue.js"></script>
  <script>
    var app = new Vue({
      el: "#vm",
      data: {
        firstName: "yu",
        lastName: "huang",
      },
      computed: {
        fullName: {
          get: function () {
            return this.firstName + "" + this.lastName;
          },
          // set: function (newValue) {
          //   this.firstName = "3";
          //   this.lastName = "4";
          // },
        },
      },
    });
  </script>
</body>

上述代码如果没有指定一个 setter 函数,那么页面上就只会渲染出一个yuhuang,而且你无法改变这个名字(无法在控制台进行这样的指令app.fullName = 'zhangfei'),除非你改变app.firstName以及app.lastName的值。
但是引入 setter 函数可以很简单地解决这个问题, setter 函数接受一个值,然后可以操作这个值,进而改变firstNamelastName,但是后续的渲染到页面其实还是 getter 函数去渲染的。

计算属性缓存

计算属性的缓存 
{{ now }} 
通过methods拿到的时间戳 
{{ thisTime() }}
computed: {
    now: function () {
       return Date.now()
    }
},
methods: {
  thisTime:function(){
    return Date.now()
    }
}

调用 methods 里的方法也可以与计算属性起到同样的作用,区别在于:

  • 页面中的方法: 如果是调用方法,只要页面重新渲染。方法就会重新执行,不需要渲染,则不需要重新执行.
  • 计算属性:不管渲染不渲染,只要计算属性依赖的数据未发生变化,就永远不变

结论:使用计算属性还是 methods 取决于你是否需要缓存,当遍历大数组和做大量计算时,应当使用计算属性,除非你不希望得到缓存。

v-bind 以及 class 与 style 的绑定

了解 bind 指令

v-bind 的复习
链接的 href 属性和图片的 src 属性都被动态设置了,当数据变化时,就会重新渲染。
在数据绑定中,最常见的两个需求就是元素的样式名称 class 和内联样式 style 的动态绑定,它们也是 HTML 的属性,因此可以使用 v-bind 指令。

绑定 class 的几种方法

  • 对象方法

:class 设置一个对象,可以动态地切换 class
当 class 的表达式过长或逻辑复杂时,还可以绑定一个计算属性,这是一种很友好和常见的用法,一般当条件多于两个时, 都可以使用 data 或 computed

  • 数组方法

当需要应用多个 class 时, 可以使用数组语法, 给 :class 绑定一个数组,应用一个 class 列表:数组成员直接对应类名

  • 在组件上使用

待续

<head>
    <style>
        .divStyle {
            background: red;
            width: 100px;
            height: 100px;
        }

        .borderStyle {
            border: 10px solid black;
        }

        .btnBackground {
            background: blue;
        }

        .newStyle {
            background: red;
            width: 100px;
            height: 100px;
            border: 10px solid black;
        }

        .active {
            background: red;
            width: 100px;
            height: 100px;
        }

        .error {
            border: 10px solid black;
        }
    </style>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width">
    <title>JS Bin</title>
</head>

<body>
    <div id="vm">
        <!-- 绑定class对象方法:对象的key是类名,value是布尔值 -->
        <div :class="{divStyle:isDiv, borderStyle:isBorder}">对象方法绑定class</div>
        <hr>
        <input type="button" value="点击切换背景" :class="{btnBackground: isButton}" v-on:click="changeColor">
        <hr>
        <!-- 计算属性方法 -->
        <div :class="classNames">计算属性绑定class</div>
        <hr>
        <!-- 绑定class数组方法: -->
        <div :class="[activeClass,errorClass]">数组方法绑定class</div>
        <hr>
        <!-- 数组与对象方法混用: -->
        <div :class="[{'divStyle':isDiv},errorClass]">数组与对象方法混用</div>
        <hr>
        <!-- 绑定内联样式: -->
        <div v-bind:style="{'color':X,'fontSize':Y+'px'}">绑定内联样式</div>
    </div>
    <script src="https://cdn.jsdelivr.net/npm/vue@2.5.16/dist/vue.js"></script>
    <script>
        //需求:点击按钮切换背景 
        var app = new Vue({
            el: '#vm',
            data: {
                isDiv: true,
                isBorder: true,
                isButton: false,
                activeClass: 'active',
                errorClass: 'error',
                X: 'red',
                Y: '16'

            },
            computed: {
                classNames: function () {
                    return {
                        newStyle: this.isDiv && this.isBorder
                    }
                }
            },
            methods: {
                changeColor: function () {
                    this.isButton = !this.isButton;
                }
            },
        })
    </script>
</body>