zoukankan      html  css  js  c++  java
  • Vue.js 学习笔记 第2章 数据绑定和第一个Vue应用

    本篇目录:

    2.1 Vue实例与数据绑定

    2.2 指令与事件

    2.3 语法糖

    学习任何一种框架,从一个Hello World应用开始是最快了解该框架特性的途径。
    我们先从一段简单的HTML代码开始,感受Vue.js最核心的功能:

     1 <!doctype html>
     2 <html lang="zh">
     3     <head>
     4         <meta charset="UTF-8">
     5         <meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
     6         <meta http-equiv="X-UA-Compatible" content="ie=edge">
     7         <title>Vue 示例</title>
     8     </head>
     9     <body>
    10         <div id="app">
    11             <input type="text" v-model="name" placeholder="你的名字">
    12             <h1>你好,{{name}}!</h1>
    13         </div>
    14 
    15         <script src="https://unpkg.com/vue/dist/vue.min.js"></script>
    16         <script>
    17             new Vue({
    18                 el: "#app",
    19                 data: {
    20                     name: ""
    21                 }
    22             });
    23         </script>
    24     </body>
    25 </html>

    这是一段简单到不能再简单的代码,但却展示出了Vue.js最核心的功能:数据的双向绑定。
    在输入框输入的内容会实时展示在页面的<h1>标签内,如图2-1所示:

    提示:
    从本章开始,示例不再提供完整代码,而是根据上下文,将HTML部分与JavaScript部分单独展示,省略了<head><body>等标签以及Vue.js的加载等,大家可根据上例结构来组织代码。

    2.1 Vue实例与数据绑定

    2.1.1 实例与数据

    Vue.js应用的创建很简单,通过构造函数Vue就可以创建一个Vue的根实例,并启动Vue应用:

    1 var app = new Vue({
    2     // 选项
    3 });

    变量app就代表了这个Vue实例。
    事实上,几乎所有的代码都是一个对象,写入Vue实例的选项内的。

    首先,必不可少的一个选项就是el
    el用于指定一个页面中已存在的DOM元素来挂在Vue实例,它可以是HTMLElement,也可以是CSS选择器。
    比如:

    1 <div id="app"></div>
    2 
    3 <script>
    4     var app = new Vue({
    5         el: document.getElementById("app")  // 或者是"#app"
    6     });
    7 </script>

    挂载成功后,我们可以通过app.$el来访问该元素。
    在浏览器中打开开发者工具,切换到控制台中测试访问app.$el,如图2-2所示:

    Vue提供了很多常用的实例属性与方法,都以$开头,比如$el,后续还会介绍更多有用的方法。

    回顾章节开始的Hello World代码,在<input>标签上,有一个v-model的指定,它的值对应于我们创建的Vue实例的data选项中的name字段,这就是Vue的数据绑定。

    通过Vue实例的data选项,可以声明应用内需要双向绑定的数据。
    建议所有会用到的数据都预先在data内声明,这样不至于将数据散落在业务逻辑中,难以维护。

    Vue实例本身也代理了data对象里的所有属性,所以可以这样访问:

     1 <div id="app"></div>
     2 
     3 <script>
     4     var app = new Vue({
     5         el: "#app",
     6         data: {
     7             a: 2
     8         }
     9     });
    10             
    11     console.log(app.a); // 输出结果:2
    12 </script>

    除了显式地声明数据外,也可以指向一个已有的变量。
    并且它们之间默认建立了双向绑定,当修改其中任意一个时,另一个也会一起变化:

     1 <script>
     2     var myData = {
     3         a: 1
     4     };
     5             
     6     var app = new Vue({
     7         el: "#app",
     8         data: myData
     9     });
    10             
    11     console.log(app.a);     // 输出结果: 1
    12             
    13     // 修改属性,原数据也会随之修改
    14     app.a = 2;
    15     console.log(myData.a);  // 输出结果: 2
    16             
    17     // 反之,修改原数据,Vue属性也会修改
    18     myData.a = 3;
    19     console.log(app.a);     // 输出结果: 3
    20 </script>

    2.1.2 生命周期

    每个Vue实例创建时,都会经历一系列的初始化过程,同时也会调用相应的生命周期钩子,我们可以利用这些钩子,在合适的时机执行我们的业务逻辑。
    如果你使用过jQuery,一定知道它的ready()方法,比如以下示例:

    1 <script>
    2     $(document).ready(function() {
    3        // DOM加载完后,会执行这里的代码
    4     });
    5 </script>

    Vue的生命周期钩子与之类似,比较常用的有:

    • create: 实例创建完成后调用,此阶段完成了数据的观测等,但尚未挂载,$el还不可用,需要初始化处理一些数据时会比较有用,后面章节将有介绍;
    • mounted: el挂载到实例上后调用,一般我们的第一个业务逻辑会在这里开始;
    • beforeDestroy: 实例销毁之前调用,主要解绑一些使用addEventListener监听的事件等。

    这些钩子与eldata类似,也是作为选项写入Vue实例的,并且钩子的this指向的是调用它的Vue实例:

     1 var app = new Vue({
     2     el: "#app",
     3     data: {
     4         a: 2
     5     },
     6     created: function() {
     7         console.log(this.a); // 2
     8     },
     9     mounted: function() {
    10         console.log(this.$el); // <div id="app"></div>
    11     }
    12 });

    2.1.3 插值与表达式

    使用双大括号(Mustache语法){{}}是最基本的文本插值方法,它会自动将我们双向绑定的数据实时显示出来。
    例如:

     1 <div id="app">
     2     {{book}}
     3 </div>
     4 
     5 <script>
     6     var app = new Vue({
     7         el: "#app",
     8         data: {
     9             book: "《Vue.js 实战》"
    10         }
    11     });
    12 </script>

    大括号里的内容会被替换为《Vue.js 实战》,通过任何方法修改数据book,大括号的内容都会被实时替换。
    比如下面的这个示例,实时显示当前的时间,每秒更新:

     1 <div id="app">
     2     {{date}}
     3 </div>
     4 
     5 <script>
     6     var app = new Vue({
     7         el: "#app",
     8         data: {
     9             intervalId: -1,
    10             date: new Date()
    11         },
    12         mounted: function() {
    13             // 声明一个变量指向Vue实例this,保证作用域一致
    14             var _this = this;
    15             // 启动计时器
    16             this.intervalId = setInterval(function() {
    17                 // 修改数据date
    18                 _this.date = new Date();
    19             }, 1000);
    20         },
    21         beforeDestroy: function() {
    22             if (this.intervalId) {
    23                 // 在Vue实例销毁前,清除我们的定时器
    24                 clearInterval(this.intervalId);
    25             }
    26         }
    27     });
    28 </script>

    提示:
    这里的{{date}}输出的是浏览器默认的时间格式,比如Thu Apr 25 2019 03:40:06 GMT+0800 (中国标准时间),并非格式化的时间(2019-04-25 03:40:06),所以需要注意时区,有多种方法可以对时间格式化,比如赋值前先使用自定义的函数处理。
    Vue的过滤器(filter)或计算属性(computed)也可以实现,稍后会介绍到。

    如果有的时候就是想输出HTML,而不是将数据解释后的纯文本,可以使用v-html

     1 <div id="app">
     2     <span v-html="link"></span>
     3 </div>
     4 
     5 <script>
     6     var app = new Vue({
     7         el: "#app",
     8         data: {
     9             link: "<a href='#'>这是一个超链接</a>"
    10         }
    11     });
    12 </script>

    link的内容将会被渲染为一个具有点击功能的<a>标签,而不是纯文本。
    这里需要注意,如果将用户产生的内容使用v-html输出,有可能导致XSS攻击,所以要在服务端对用户提交的内容进行处理,一般可将尖括号<>转义。

    如果想显示{{}}标签,而不进行替换,使用v-pre即可跳过这个元素和它的子元素的编译过程。
    例如:

    1 <span v-pre>{{这里的内容是不会被编译的}}</span>

    {{}}中除了简单的绑定属性值外,还可以使用JavaScript表达式进行简单的运算、三元运算符等。
    例如:

     1 <div id="app">
     2     {{number/10}}
     3     {{isOK ? "确定" : "取消"}}
     4     {{text.split(",").reverse().join("")}}
     5 </div>
     6 
     7 <script>
     8     var app = new Vue({
     9         el: "#app",
    10         data: {
    11             number: 100,
    12             isOK: false,
    13             text: "123,456"
    14         }
    15     });
    16 </script>

    显示结果依次为:10、取消、456123。

    Vue.js只支持表达式,不支持语句和流控制。
    另外,在表达式中,不能使用用户自定义的全局变量,只能使用Vue白名单内的全局变量,例如MathDate
    以下是一些无效的示例:

    1 <!-- 这是语句,不是表达式 -->
    2 {{ var book = "Vue.js 实战" }}
    3 <!-- 不能使用流控制,要使用三元运算 -->
    4 {{ if (ok) return msg }}

    2.1.4 过滤器

    Vue.js支持在{{}}插值的尾部添加一个管道符|对数据进行过滤,经常用于格式化文本,比如字母全部大写、货币千位使用逗号分隔符。
    过滤的规则是自定义的,通过给Vue实例添加选项filters来设置,例如上一节中实时显示当前时间的示例,可以对时间进行格式化处理:

     1 <div id="app">
     2     {{ date | formatDate }}
     3 </div>
     4 
     5 <script>
     6     // 在月份、日期、小时等小于10时前面补0
     7     var padDate = function(value) {
     8         return (value < 10 ? "0" + value : value);
     9     };
    10     
    11     var app = new Vue({
    12         el: "#app",
    13         data: {
    14             intervalId: -1,
    15             date: new Date()
    16         },
    17         filters: {
    18             // 这里的value就是需要过滤的数据
    19             formatDate: function(value) {
    20                 var date = new Date(value);
    21                 
    22                 var year = date.getFullYear();
    23                 var month = padDate(date.getMonth() + 1);
    24                 var day = padDate(date.getDate());
    25                 
    26                 var hours = padDate(date.getHours());
    27                 var minutes = padDate(date.getMinutes());
    28                 var seconds = padDate(date.getSeconds());
    29                 
    30                 return (year + "-" + month + "-" + day + " " + hours + ":" + minutes + ":" + seconds);
    31             }
    32         },
    33         mounted: function() {
    34             var _this = this;
    35             this.intervalId = setInterval(function() {
    36                 _this.date = new Date();
    37             }, 1000);
    38         },
    39         beforeDestroy: function() {
    40             if (this.intervalId) {
    41                 clearInterval(this.intervalId);
    42             }
    43         }
    44     });
    45 </script>

    过滤器也可以串联,而且可以接受参数,例如:

    1 <!-- 串联 -->
    2 {{ message | filterA | filterB }}
    3 
    4 <!-- 接收参数 -->
    5 {{ message | filterA("arg1", "arg2") }}

    这里的字符串arg1arg2分别传给过滤器的第二个和第三个参数,因为第一个是数据本身。

    提示:
    过滤器应当用于处理简单的文本转换,如果要实现更为复杂的数据变换,应该使用计算属性,下一章会详细介绍它的用法。

    2.2 指令与事件

    指令(Directives)是Vue.js模板中最常用的一项功能,它带有前缀v-,在前面我们已经使用了不少指令了,比如v-ifv-htmlv-pre等。
    指定的主要职责就是当其表达式的值改变时,相应地将其某些行为应用到DOM上,以v-if为例:

     1 <div id="app">
     2     <p v-if="show">显示这段文本</p>
     3 </div>
     4 
     5 <script>
     6     var app = new Vue({
     7         el: "#app",
     8         data: {
     9             show: true
    10         }
    11     });
    12 </script>

    当数据show的值为true时,p元素会被插入,为false时则会被移除。
    数据驱动DOM是Vue.js的核心理念,所以不到万不得已时不要主动操作DOM,你只需要维护好数据,DOM的事Vue.js会帮你优雅地处理。

    Vue.js内置了很多指定,帮助我们快速完成常见的DOM操作,比如循环渲染、显示与隐藏等。
    在第5章会详细地介绍这些内置指令,但在此之前,你需要先知道v-bindv-on

    v-bind的基本用途是动态更新HTML元素上的属性,比如idclass等,例如下面几个示例:

     1 <div id="app">
     2     <a v-bind:href="url">超链接</a>
     3     <img v-bind:src="imgUrl">
     4 </div>
     5 
     6 <script>
     7     var app = new Vue({
     8         el: "#app",
     9         data: {
    10             url: "https://www.geeksss.com",
    11             imgUrl: "https://www.geeksss.com/logo.png"
    12         }
    13     });
    14 </script>

    示例中的链接地址与图片的地址都与数据进行了绑定,当通过各种方式改变数据时,链接和图片都会自动更新。
    上述示例渲染后的结果为:

    1 <div id="app">
    2     <a href="https://www.geeksss.com">超链接</a>
    3     <img src="https://www.geeksss.com/logo.png">
    4 </div>

    以上是介绍v-bind最基本的用法,它在Vue.js组件中还有这重要的作用,将在第4章和第7章中详细介绍。

    另一个非常重要的指令就是v-on,它用来绑定事件监听器,这样我们就可以做一些交互了。
    先来看下面的示例:

     1 <div id="app">
     2     <p v-if="show">这是一段文本</p>
     3     <button v-on:click="handleClose">点击隐藏</button>
     4 </div>
     5 
     6 <script>
     7     var app = new Vue({
     8         el: "#app",
     9         data: {
    10             show: true
    11         },
    12         methods: {
    13             handleClose: function() {
    14                 this.show = false;
    15             }
    16         }
    17     });
    18 </script>

    <button>按钮上,使用v-on:click给钙元素绑定了一个点击事件,在普通元素上,v-on可以监听原生的DOM事件,除了click外,还有dbclick、keyup、mousemove等。
    表达式可以是一个方法名,这些方法都写在Vue实例的methods属性内,并且是函数的形式,函数内的this指向的是当前Vue实例本身,因此可以直接使用this.xxx的形式来访问或修改数据,如示例中的this.show = false;,把数据show修改为了false,所以点击按钮时,文本<p>元素就被移除了。

    表达式除了方法名,也可以直接是一个内联语句,上例也可以改写为:

     1 <div id="app">
     2     <p v-if="show">这是一段文本</p>
     3     <button v-on:click="handleClose">点击隐藏</button>
     4 </div>
     5 
     6 <script>
     7     var app = new Vue({
     8         el: "#app",
     9         data: {
    10             show: true
    11         },
    12         methods: {
    13             handleClose: function() {
    14                 this.show = false;
    15             }
    16         }
    17     });
    18 </script>

    如果绑定的事件要处理复杂的业务逻辑,建议还是在methods里声明一个方法,这样可读性更强也好维护。

    Vue.js将methods里的方法也代理了,所以也可以像访问Vue数据那样来调用方法:

     1 <div id="app">
     2     <p v-if="show">这是一段文本</p>
     3     <button v-on:click="handleClose">点击隐藏</button>
     4 </div>
     5 
     6 <script>
     7     var app = new Vue({
     8         el: "#app",
     9         data: {
    10             show: true
    11         },
    12         methods: {
    13             handleClose: function() {
    14                 this.close();
    15             },
    16             close: function() {
    17                 this.show = false;
    18             }
    19         }
    20     });
    21 </script>

    handleClose方法内,直接通过this.close()调用了close()函数。
    在上面示例中是多此一举的,只是用于演示它的用法,在业务中经常用到,例如以下几种用法都是正确的:

     1 <script>
     2     var app = new Vue({
     3         el: "#app",
     4         data: {
     5             show: true
     6         },
     7         methods: {
     8             init: function(text) {
     9                 console.log(text);
    10             }
    11         },
    12         mounted: function() {
    13             // 在初始化时调用
    14             this.init("在初始化时调用");
    15         }
    16     });
    17     // 在Vue实例外部调用
    18     app.init("通过外部调用");
    19 </script>

    更多关于v-on事件的用法将会在第7章中详细介绍。

    2.3 语法糖

    语法糖是指在不影响功能的情况下,添加某种方法实现同样的效果,从而方便程序开发。

    Vue.js的v-bindv-on指令都提供了语法糖,也可以说是缩写。
    比如v-bind,可以省略v-bind,直接写一个冒号:
    例如:

    1 <a v-bind:href="url">超链接</a>
    2 <img v-bind:src="imgUrl">
    3 <!-- 缩写为 -->
    4 <a :href="url">超链接</a>
    5 <img :src="imgUrl">

    v-on可以直接用@来缩写:

    1 <button v-on:click="handleClose">点击隐藏</button>
    2 <!-- 缩写为 -->
    3 <button @click="handleClose">点击隐藏</button>

    使用语法糖可以简化代码的书写,从下一章开始,所有示例的v-bindv-on指令将默认使用语法糖的写法。

  • 相关阅读:
    通讯录封装实现
    简单通讯录的实现 main..h .m文件全部
    iOS 开发 OC编程 字典和集合 排序方法
    iOS 开发 OC编程 数组冒泡排序.图书管理
    iOS 开发 OC编程 属性和字符串练习
    iOS 开发 OC编程 属性和字符串
    iOS 开发 OC编程 便利构造器以及初始化方法
    iOS 开发 OC编程 方法的书写
    IOS 开发 OC编程 类和对象
    iOS 开发 c语言阶段考试题
  • 原文地址:https://www.cnblogs.com/geeksss/p/10767682.html
Copyright © 2011-2022 走看看