Vue.js入门:打造你的教育平台前端项目

发表时间: 2020-09-01 00:41


Introduction to Vue.js

What is Vue.js

Vue.js 是一套用于构建用户界面的渐进式框架。与其它大型框架不同的是 Vue 被设计为可以自底向上逐层应用。

Vue.js 的核心库只关注视图层,不仅易于上手,还便于与第三方库或既有项目整合。另一 方面,当与 现代化的工具链以及各种支持类库结合使用时,Vue 也完全能够为复杂的单页应用提供驱动。

自底向上逐层应用:作为渐进式框架要实现的目标就是方便项目增量开发(即插即用)。

官方网站: https://cn.vuejs.org/v2/guide/

Why Use Vue.js?

  • 声明式渲染:前后端分离是未来趋势。
  • 渐进式框架:适用于各种业务需求。
  • 简单易学:中文文档,易于理解和学习。


Basic Knowledge

使用 Vue.js

在 html 页面使用 script 引入 vue.js 的库即可使用:

  • 远程CDN:<script src="https://cdn.jsdelivr.net/npm/vue@2.5.16/dist/vue.js"></script>
  • 本地:<script src="js/vue.min.js"></script>

Vue-CLI 脚手架:使用 vue.js 官方提供的 CLI 脚本架可以方便地去创建 vue.js 工程雏形。

入门程序

创建一个 vue_test 目录,并且在目录下创建 01_vue入门程序.html 文件。

  1. 定义 html,引入 vue.js
  2. 定义 app div,此区域作为 vue.js 的接管区域
  3. 定义 Vue.js 实例,接管 app 区域。
  4. 定义 model(数据对象)
  5. 在 app 中展示数据
<!DOCTYPE html><html lang="en">  <head>    <meta charset="UTF-8" />    <meta name="viewport" content="width=<device-width>, initial-scale=1.0" />    <meta http-equiv="X-UA-Compatible" content="ie=edge" />    <title>Document</title>    <!-- 引入 vue.js -->    <!-- <script src="https://cdn.jsdelivr.net/npm/vue@2.5.16/dist/vue.js"></script> -->    <script src="js/vue.min.js"></script>  </head>  <body>    <!-- 创建 id 为 app 的 div -->    <div id="app">{{name}}</div>  </body>  <script>    // 创建 vue 实例    var VM = new Vue({      el: "#app",      data: {        name: "Hello Vue",      },    });  </script></html>

{{}} 插值表达式:通常用来获取 Vue.js 实例中定义的数据(data);属性节点中不能够使用插值表达式。

el 挂载点:定义 Vue.js 实例挂载的元素节点,表示 vue.js 接管该区域。

Vue 的作用范围 :Vue 会管理 el 选项中的元素及其内部元素。

选择挂载点时,可以使用其他选择器,但是建议使用 ID 选择器。

挂载点可以设置其他的 DOM 元素进行关联,但是建议选择 DIV,不能使用 HTML 和 Body 标签。

data 数据对象:Vue 中用到的数据定义在 data 中;data 中可以写复杂类型;渲染复杂类型数据的时候遵守 js 语法。

<body>    <!-- 创建 id 为 app 的 div -->    <div id="app">        {{name}} <br>        {{school.name}} {{school.number}} <br>        <ul>            <li>{{names[0]}}</li>            <li>{{names[1]}}</li>            <li>{{names[2]}}</li>        </ul>    </div></body><script>    // 创建 vue 实例    var VM = new Vue({        el: "#app",        data: {            name: "Hello Vue",            // 对象类型            school: {                name: "学校名称",                number: "100000"            },            // 数组类型            names: ["张人大", "刘小明", "赵小红"]        },    });</script>

声明式渲染的好处

Vue 中的声明式渲染,简单理解就是 Vue 将声明的数据渲染到 HTML。

<body>    <div id="app">        <h2>{{name}}</h2>    </div></body>​<!-- <script src="js/jquery-1.8.3.min.js"></script><script>$(document).ready(function() {$("#app").append("<h2>Hello World</h2>")});</script> -->​<script src="js/vue.min.js"></script><script>    var VM = new new Vue({        el: "#app",        data: {            name: "Hello World!!",        },    });</script>

Vue 常用指令

Vue 指令是带有 v- 前缀的特殊属性;通过指令来操作 DOM 元素 。

v-text 指令

作用:获取 data 数据,设置标签的内容。 注意:默认写法会替换全部内容,使用插值表达式 {{}} 可以替换指定内容。

<body>        <div id="app">        <h2>{{message}}高级</h2>​        <!-- v-text 获取 data 数据,设置标签的内容,会覆盖标签里的内容体-->        <h2 v-text="message">高级</h2>​        <!-- 拼接字符串 -->        <h2 v-text="message+1"></h2>        <h2 v-text="message+'abc'"></h2>    </div></body><script src="js/vue.min.js"></script><script>    var VM = new new Vue({       el: "#app",       data: {           message: "Java程序员"       }     });</script>

v-html 指令

作用: 设置元素的 innerHTML (可以向元素中写入新的标签)

<body>    <div id="app">        <!-- 获取普通文本 -->        <h2>{{message}}</h2>        <h2 v-text="message"></h2>        <h2 v-html="message"></h2>​        <!-- 设置元素的 innerHTML -->        <h2 v-html="url"></h2>        <h2 v-text="url"></h2>    </div></body><script src="js/vue.min.js"></script><script>    var VM = new new Vue({       el: "#app",       data: {           message: "Java程序员",           url: "<a href='https://www.baidu.com'>百度一下</a>"       }     });</script>

v-on 指令

作用:为元素绑定事件, 比如: v-on:click 可以简写为 @click="方法"

绑定的方法定义在 VUE 实例的 method 属性中

<body>    <div id="app">        <!-- 使用 v-on 绑定 click 点击事件 -->        <input type="button" value="Button" v-on:click="methodName">        <!-- 使用 @ 符号也可以绑定-->        <input type="button" value="Button" @click="methodName">         <!-- 双击事件 -->        <input type="button" value="双击击按钮" @dblclick="show">        <!-- 绑定点击事件 -->        <h2 @click="changeName">{{food}}</h2>    </div></body><script src="js/vue.min.js"></script><script>    var VM = new new Vue({       el: "#app",       data: {           food: "Turkey"       },       // 通过 methods,专门存放 Vue 中的方法       methods: {           methodName: function() {               alert("提醒!");           },           show: function() {               alert("Double Click");           },           changeName: function() {               console.log(this.food);               // 在 VUE 中不需要考虑如何更改 DOM 元素,                // 重点放在数据更新之后,使用数据的那个元素会同步更新               this.food+=" Delicious!";           }       }    });</script>

v-on 指令补充

传递自定义参数:函数调用传参

事件修饰符:对事件触发的方式进行限制

<body>    <div id="app">        <!-- 函数传参 -->        <input          type="button"          value="礼物刷起来"          @click="showTime(111, 'test111')"        />          <!-- 事件修饰符指定哪些方式可以触发事件 -->        <input type="text" @keyup.enter="hiFunction" />      </div></body><script src="js/vue.min.js"></script><script>  var VM = new Vue({    el: "#app",    data: {},    methods: {      showTime: function (p1, p2) {        console.log(p1);        console.log(p2);      },      hiFunction: function () {        alert("How are you");      },    },  });</script>
  • 事件绑定方法,可以传入自定义参数
  • 定义方法时,需要定义形参来接收实际的参数
  • 事件的后面跟上 .修饰符 可以对事件进行限制
  • .enter 可以限制触发的按键为回车
  • 事件修饰符有许多,使用时可以查询文档

计数器案例

  1. data 中定义数据:比如 num 值为 1
  2. methods 中添加两个方法:比如 add(递增),sub(递减)
  3. 使用 {{}} 将 num 设置给 span 标签
  4. 使用 v-on 将 add、sub 分别绑定给加、减按钮
  5. 累加到 10 停止
  6. 递减到 0 停止
<body>    <body>        <div id="app">            <!-- 计算功能区域 -->            <div>                <input type="button" value="+" v-on:click="add"/>                          <span>{{num}}</span>                <input type="button" value="-" @click="sub"/>            </div>        </div>    </body>    <script src="js/vue.min.js"></script>    <script>        //创建 VUE 实例        var VM = new Vue({            el: "#app",            data: {                num: 1            },            methods: {                add: function() {                    if(this.num < 10) {                        this.num++;                    } else {                        alert("Number is at Maximum");                    }                },                sub: function() {                    if(this.num > 0) {                        this.num--;                    } else {                        alert("Number is Minimum");                    }                }            }        });    </script></body>

总结:

  • 创建 VUE 实例:el 挂载点,data 数据,methods 方法
  • v-on 指令的作用是绑定事件,简写为 @
  • 方法中使用 this 关键字,获取 data 中的数据
  • v-text 与 {{}} 的作用都是用来设置元素的文本值

v-show 指令

作用:v-show 指令,根据真假值切换元素的显示状态

<body>    <div id="app">        <input type="button" value="切换状态" @click="changeShow" />        <img v-show="isShow" src="img/car.gif" alt="" />        <img v-show="age > 18" src="img/car.gif" />    </div></body><script src="js/vue.min.js"></script><script>    var VM = new Vue({        el: "#app",        data: {            isShow: true,            age: 19        },        methods: {            changeShow: function() {                // 触发方法,对 isShow 进行取反                this.isShow = !this.isShow;            }        }    });</script>
  • 原理是修改元素的 display 实现显示或者隐藏
  • 指令后面的内容,最终会解析为布尔值
  • 值为 true 显示,为 false 则隐藏
  • 数据改变之后,显示的状态会同步更新

v-if 指令

根据表达式的真假,切换元素的显示和隐藏(操作是 dom)

<body>    <div id="app">        <input type="button" value="切换状态" @click="changeShow" />        <img v-if="isShow" src="img/car.gif" />    </div></body><script src="js/vue.min.js"></script><script>  var VM = new Vue({    el: "#app",    data: {      isShow: false,    },    methods: {      changeShow: function () {        this.isShow = !this.isShow;      },    },  });</script>
  • v-if 指令的作用:根据表达式的真假切换元素的显示状态
  • 本质是通过操作 dom 元素,来切换显示状态
  • 表达式为 true 时元素存在于 dom 树,为 false 则从 dom 树中移除
  • 频繁切换使用 v-show,反之使用 v-if

v-bind 指令

作用:设置元素的属性(比如:src,title,class)

<body>    <div id="app">        <img src="img/buddha.jpg" alt="" />          <!-- 使用 v-bind 设置 src 属性 -->        <img v-bind:src="imgSrc" />          <!-- v-bind 简写为冒号-->        <img :src="imgSrc" :title="imgTitle" />          <!-- 设置 class -->        <div :style="{ fontSize: size+'px' }">v-bind 指令</div>    </div></body><script src="js/vue.min.js"></script><script>  var VM = new Vue({    el: "#app",    data: {      imgSrc: "img/buddha.jpg",      imgTitle: "Buddha",      size: 50,    },  });</script>
  • v-bind 指令的作用是:为元素绑定属性
  • 完整写法 v-bind:属性名,可以简写为 :属性名

v-for 指令

作用:根据数据生成列表结构

<body>  <div id="app">    <input type="button" value="添加数据" @click="add" />    <input type="button" value="移除数据" @click="remove" />    <ul>      <!-- 在 li 标签中获取数组的元素 -->      <li v-for="(item, index) in arr">        {{index+1}}城市:{{item}}      </li>    </ul>    <!-- 使用h2标签显示 -->    <h2 v-for="p in persons">      {{p.name}}    </h2>  </div></body><script src="js/vue.min.js"></script><script>  var VM = new Vue({    el: "#app",    data: {      // 数组      arr: ["上海", "北京", "广东", "深圳"],      // 对象数组      persons: [        { name: "张人大" },        { name: "刘小明" },        { name: "赵小红" },      ],    },    methods: {      add: function() {        // 向数组添加元素        this.persons.push({name: "小郑"});      },      remove: function() {        // 移除数据        this.persons.shift();      }    }  });</script>
  • 数组经常和 v-for 结合使用,数组有两个常用方法:push() 向数组末尾添加一个或多个元素;shift() 把数组中的第一个元素删除
  • 语法是: (item, index) in 数据
  • item 和 index 可以结合其他指令一起使用
  • 数组的长度变化,会同步更新到页面上,是响应式的

MVVM 模式

MVVM 是 Model-View-ViewModel 的缩写,它是一种基于前端开发的架构模式 MVVM 模式将页面分层了 M、V、和 VM,解释为: Model:负责数据存储 View:负责页面展示 View Model:负责业务逻辑处理(比如 Ajax 请求等),对数据进行加工后交给视图展示

<body>    <div id="app">        <!-- View 视图部分 -->        <h2>{{name}}</h2>    </div></body><script src="js/vue.min.js"></script><script>    // 创建的 vue 实例就是 ViewModel    var VM = new Vue({      el: "#app",      // data 就是 MVVM 模式中的 model      data: {        name: "hello",      },    });</script>

首先,我们将 View Model 的 DOM Listeners 和 Data Bindings 看作两个工具,它们是实现双向绑定的关键:

  • 从 View 看,View Model 中的 DOM Listeners 工具会监测页面上 DOM 元素的变化,如果有变化,则更改 Model 中的数据;
  • 从 Model 看,当 Model 中的数据更新时,Data Bindings 工具会更新页面中的 DOM 元素。

MVVM 的思想主要是为了让开发更加方便,因为 MVVM 提供了数据的双向绑定。

v-mode 指令

作用:获取和设置表单元素的值,实现双向数据绑定。

  • 单向绑定:将 model 绑定到 view 上,当 model 发生变化时 view 会随之变化。
  • 双向绑定:除了单向绑定的功能外,用户更新了 View,而 Model 的数据也自动被更新。

填写表单:当用户填写表单时,View 的状态就被更新了,此时 MVVM 框架可以自动更新 Model 的状态,就相当于把 Model 和 View 做了双向绑定。绑定的数据会和表单元素值相关联。

<body>    <div id="app">        <input type="button" value="update message" @click="update" />          <!-- View 视图演示自动单向数据绑定 -->        <input type="text" v-bind:value="message" />        <br>​        <!-- v-model 实现自动双向数据绑定 -->        <input type="text" v-model="message" />        <input type="text" v-model="password" />        <h2>{{message}}</h2>        <h2>{{password}}</h2>    </div></body><script src="js/vue.min.js"></script><script>  // VM 业务逻辑控制  var VM = new Vue({    el: "#app",    // Model 数据存储    data: {      message: "Where are you from?",      password: 123456,    },    methods: {      update: function () {        this.message = "China";      },    },  });</script>

实现简单记事本

新增内容

  1. 生成列表结构(v-for 数组)
  2. 获取用户输入(v-model 双向绑定)
  3. 点击回车键新增数据(v-on .enter 事件修饰符)
  4. 页面布局不熟悉,可以通过审查元素的方式快速找到元素

删除内容

  1. 点击删除指定的内容(根据索引删除元素)
  2. 在 methods 中添加一个删除的方法,使用 splice 函数进行删除

统计操作

  1. 统计页面信息的个数,就是列表中的元素的个数
  2. 获取 list 数组的长度,就是信息的个数

清空数据

  1. 点击清除所有信息
  2. 本质就是清空数组
<html><head>  <meta http-equiv="content-type" content="text/html; charset=UTF-8" />  <title>记事本</title>  <meta http-equiv="content-type" content="text/html; charset=UTF-8" />  <meta name="robots" content="noindex, nofollow" />  <meta name="googlebot" content="noindex, nofollow" />  <meta name="viewport" content="width=device-width, initial-scale=1" />  <link rel="stylesheet" type="text/css" href="vue_text/css/index.css" /></head><body>  <!-- VUE 示例接管区域 -->  <section id="app">​    <!-- 输入框 -->    <header class="header">      <h1>VUE 记事本</h1>      <input autofocus="autofocus" autocomplete="off" placeholder="输入日程" class="new-todo" v-model="inputValue"        @keyup.enter="add" />    </header>​    <!-- 列表区域 -->    <section class="main">      <ul class="listview">        <!-- 使用 v-for 指令生成列表结构 -->        <li class="todo" v-for="(item, index) in list">          <div class="view">            <span class="index">{{index+1}}</span>            <label>{{item}}</label>            <!-- 删除操作传递 index -->            <button class="destroys" @click="remove(index)"></button>          </div>        </li>      </ul>    </section>​    <!-- 统计和清空 -->    <footer class="footer">      <span class="todo-count">        <strong>{{list.length}}</strong>        items left      </span>      <button class="clear-completed" @click="clear()">        Clear      </button>    </footer>  </section>​  <!-- 开发环境版本,包含了有帮助的命令行警告 -->  <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>  <script>    var VM = new Vue({      el: "#app",      data: {        list: ["Coding", "Sleep", "Eat"],        inputValue: "996 or 997"      },      methods: {        add: function () {          this.list.push(this.inputValue);        },        remove: function (index) {          this.list.splice(index, 1);        },        clear: function () {          this.list = [];        }      }    });  </script></body></html>


Axios

Ajax

What is Ajax?

Ajax 是指一种创建交互式网页应用的开发技术

Ajax = 异步 JavaScript + XML

Ajax 的作用

Ajax 可以使网页实现异步更新。这意味着可以在不重新加载整个网页的情况下,对网页的某部分进行更新(局部更新)。传统的网页如果需要更新内容,必须重载整个网页页面。 简单记:Ajax 是一种在无需重新加载整个网页的情况下,能够更新部分网页的技术,维护用户体验性,进行网页的局部刷新.。

异步和同步

同步访问:客户端必须等待服务器端的响应,在等待过程中不能进行其他操作 异步访问:客户端不需要等待服务的响应,在等待期间浏览器可以进行其他操作

案例

AjaxServlet

@WebServlet("/ajax")public class AjaxServlet extends HttpServlet {    @Override    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {        // 获取请求参数        String username = req.getParameter("name");​        // 模拟业务操作的延时        try {            Thread.sleep(3000);        } catch (InterruptedException e) {            e.printStackTrace();        }​        // 打印 username        System.out.println(username);        resp.getWriter().write("Hello Ajax");    }​    @Override    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {        this.doPost(req, resp);    }}

ajax.jsp

<%@ page contentType="text/html;charset=UTF-8" language="java" %><html><head>    <title>Ajax</title></head><body>    <input type="text">    <input type="button" value="JQuery is sending Asynchronous request" onclick="run1()"></body><script src="jquery-1.8.3.min.js"></script><script>    function run1() {        $.ajax({            url: "/hello_maven/ajax",            async: true,            data: {                name: "Renda"            },            type: "post",            dataType: "text",            success: function (res) {                console.log(res);                alert("sucess: " + res);            },            error: function () {                alert("error");            }        });    }</script></html>

axios 介绍

VUE 中结合网络数据进行应用的开发:

  • 目前十分流行网络请求库,专门用来发送请求,其内部还是 ajax,进行封装之后使用更加方便
  • axios 作用:在浏览器中可以帮助我们完成 ajax 异步请求的发送

Vue 2.0 之后推荐用 axios 替换 JQuery ajax。

axios 入门

导包:<script src="https://unpkg.com/axios/dist/axios.min.js"></script>

GET:axios.get(地址?key=value&key2=value2).then(function(response){},function(error){});

POST:axios.post(地址,{key:value,key2:value2}).then(function(response){},function(error){});

  1. axios 必须导包才能使用
  2. 使用 get 或者 post 方法就可以发送请求
  3. then 方法中的回调函数会在请求成功或者请求失败的时候触发
  4. 通过回调函数的形参可以获取响应的内容或者错误信息

接口 1:随机笑话

请求地址:https://autumnfish.cn/api/joke/list 请求方法:get 请求参数:num(笑话条数,数字) 响应内容:随机笑话

接口 2:用户注册

请求地址:https://autumnfish.cn/api/user/reg 请求方法:post 请求参数:username(用户名,字符串) 响应内容:注册成功或失败

接口 3:天气查询

请求地址:http://wthrcdn.etouch.cn/weather_mini 请求方法:get 请求参数:city(要查询的城市名称) 响应内容:天气信息

获取笑话案例

<body>    <div id="app">        <input type="button" value="点击获取一个笑话" @click="getJoke" />        <input type="button" value="Post请求" @click="postRegister">        <p>{{joke}}</p>    </div></body><script src="vue_text/js/vue.min.js"></script><script src="vue_text/js/axios.min.js"></script><script>    var VM = new Vue({        el: "#app",        data: {            joke: "This is a Joke",        },        methods: {            getJoke: function () {                var jokeThis = this;​                // 异步访问                axios.get("https://autumnfish.cn/api/joke").then(                    // 在回调函数内部,this 无法正常使用,需要提前保存起来                    function (resp) {                        console.log(jokeThis.joke);                        jokeThis.joke = resp.data;                    },                    function (error) {                        alert("error: " + error);                    }                );            },            postRegister: function () {                axios.post("https://autumnfish.cn/api/user/reg", { username: "张人大" }).then(                    function (resp) {                        console.log(resp);                        alert(resp.data);                    },                    function (error) {                        console.log(error);                        alert("error: " + error.data);                    }                );            }        }    });</script>

axios 回调函数中 this 指向已经改变,无法访问 data 中的数据。

解决方案:将 this 进行保存,回调函数中直接使用保存的 this 即可。

天气查询案例

js/main.js

var VM = new Vue({  el: "#app",  data: {    city: "",    // 定义数组保存天气信息    weatherList: [],  },  // 编写查询天气的方法  methods: {    searchWeather: function () {      console.log("天气查询");      console.log(this.city);​      var savedThis = this;​      // 调用接口      axios.get("http://wthrcdn.etouch.cn/weather_mini?city=" + this.city).then(        function (resp) {          console.log(resp)          // 获取天气信息保存到 weatherList          savedThis.weatherList = resp.data.data.forecast;        },        function (error) {          console.log(error);        }      );    },  },});

HTML 代码

<!DOCTYPE html><html lang="en">  <head>    <meta charset="UTF-8" />    <meta name="viewport" content="width=device-width, initial-scale=1.0" />    <meta http-equiv="X-UA-Compatible" content="ie=edge" />    <title>天气查询</title>    <link rel="stylesheet" href="css/reset.css" />    <link rel="stylesheet" href="css/index.css" />  </head>​  <body>    <div class="wrap" id="app">      <div class="search_form">        <div class="logo">天气查询</div>        <div class="form_group">          <input             type="text"             class="input_txt"             placeholder="请输入要查询的城市"            v-model="city"            @keyup.enter="searchWeather"/>          <button class="input_sub" @click="searchWeather">回车查询</button>        </div>            </div>      <ul class="weather_list">        <li v-for="item in weatherList">            <div class="info_type">                <span class="iconfont">{{item.type}}</span>            </div>          <div class="info_temp">            <b>{{item.low}}</b>            ~            <b>{{item.high}}</b>          </div>          <div class="info_date"><span>{{item.date}}</span></div>        </li>    </div>​    <!-- 开发环境版本,包含了有帮助的命令行警告 -->    <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>    <!-- 官网提供的 axios 在线地址 -->    <script src="https://unpkg.com/axios/dist/axios.min.js"></script>    <!-- 自定义 main.js -->    <script src="js/main.js"></script>  </body></html>
  • 应用的逻辑代码,建议与页面进行分离,使用单独的 JS 编写
  1. axios 回调函数中的 this 的指向改变,无法正常使用,需要另外保存一份
  2. 服务器返回的数据比较的复杂时,获取数据时要注意层级结构

解决页面闪烁问题

当网络较慢,网页还在加载 Vue.js ,而导致 Vue 来不及渲染,这时页面就会显示出 Vue 源代码,可以使用 v-cloak 指令来解决这一问题。

v-cloak 指令:解决插值表达式闪烁问题。

<!-- 添加样式 --><style>    /*    通过属性选择器,设置添加了 v-cloak     */    [v-cloak] {        display: none;    }</style><!-- 在 id 为 app 的 div 中添加 v-cloak --><div class="wrap" id="app" v-cloak>    ...</div>


computed 计算属性

什么是计算属性

computed 的作用:减少运算次数,缓存运算结果,运用于重复相同的计算。

<body>    <div id="app">        <h1>{{res()}}</h1>        <h2>{{res()}}</h2>        <h1>{{resComputed}}</h1>        <h2>{{resComputed}}</h2>    </div></body><script src="js/vue.min.js"></script><script>    var VM = new new Vue({       el: "#app",       data: {           a: 10,            b: 20,       },       methods: {           res: function() {               console.log("res method had been executed");               return this.a * this.b;           },       },       computed: {           resComputed: function() {               console.log("resComputed method had been executed.")               return this.a * this.b;           }       }    });</script>

定义函数也可以实现与 计算属性相同的效果,都可以简化运算;

不同的是计算属性是基于它们的响应式依赖进行缓存的。只在相关响应式依赖发生改变时它们才会重新求值。


filter 过滤器

过滤器是对即将显示的数据做进一步的筛选处理,然后进行显示;值得注意的是过滤器并没有改变原 来的数据,只是在原数据的基础上产生新的数据。

数据加工车间,对值进行筛选加工。

过滤器使用位置:

  • {{ msg | filterA }}:msg 是需要处理的数据,filterA 是过滤器, | 这个竖线是管道,通过这个管道将数据传输给过滤器进行过滤加工操作。
  • v-bind 绑定的值的地方:<h1 v-bind:id=" msg | filterA"> {{ msg }} </h1>
<!-- 局部过滤器 --><body>    <div id="app">        <!-- 使用插值表达式,调用过滤器 -->        <p>Computer Price: {{price | addIcon}}</p>    </div></body><script src="js/vue.min.js"></script><script>    var VM = new Vue({        el: "#app",        data: {            price: 200,        },        methods: {​        },        computed: {​        },        // 局部过滤器 在 vue 实例的内部创建 filter        filters: {            addIcon(value) {                return "$" + value;            }        }    })</script><!-- 全局过滤器 --><body>    <div id="app">        <p>{{user.name | changeName}}</p>    </div></body><script src="js/vue.min.js"></script><script>    // 在创建 vue 实例之前创建全局过滤器    Vue.filter("changeName", function(value) {        // Change the first letter of the name to uppercase        return value.charAt(0).toUpperCase() + value.slice(1);    });​    var VM = new Vue({        el: "#app",        data: {            user: { name: "renda" }        }    })</script>
  • 过滤器常用来处理文本格式化的操作;过滤器可以用在两个地方:双花括号插值和 v-bind 表达式。
  • 过滤器应该被添加在 JavaScript 表达式的尾部,由“管道”符号指示。


watch 侦听器

作用:当有一些数据需要随着其它数据变动而变动时,可以使用侦听属性;它用于观察 Vue 实例上的数据变动。

<!-- 监听数字变化 --><body>    <div id="app">        <h2>计数器:{{count}}</h2>        <input type="button" @click="count++" value="CLICK">    </div></body><script src="js/vue.min.js"></script><script>    var VM = new Vue({        el: "#app",        data: {            count: 1,        },        watch: {            count: function(nval, oval) {                alert("Counter Change from " + oval + " to " + nval);            }        }    });</script><!-- 监听姓名变化并实时显示 --><body>    <div id="app">        <label>First Name: <input type="text" v-model="firstName"></label>        <label>Last Name: <input type="text" v-model="lastName"></label>        {{fullName}}    </div></body><script src="js/vue.min.js"></script><script>    var VM = new Vue({        el: "#app",        data: {            firstName: "",            lastName: "",            fullName: ""        },        watch: {            firstName: function(nval, oval) {                this.fullName = nval + " " + this.lastName;            },            lastName: function(nval, oval) {                this.fullName = this.firstName + " " + nval;            }        }    })</script>


Component 组件

组件(Component)是自定义封装的功能。在前端开发过程中,经常出现多个网页的功能是重复的,而且很多不同的页面之间,也存在同样的功能。

将相同的功能进行抽取,封装为组件;这样前端人员就可以在组件化开发时,只需要书写一次代码,随处引入即可使用。

组件系统让我们可以用独立可复用的小组件来构建大型应用,几乎任意类型的应用的界面都可以抽象为一个组件树。

Vue 的组件有两种:全局组件和局部组件 。

注意:

  1. 组件名以小写开头,采用短横线分割命名:例如 hello-Word
  2. 组件中的 data 必须是一个函数,注意与 Vue 实例中的 data 区分
  3. 在 template 模板中,只能有一个根元素
  4. 创建局部组件时,注意 components 的末尾有 s,而全局组件是不用加 s 的;这意味着 components 里可以创建多个组件

相比起全局组件,局部组件只能在同一个实例内才能被调用。

局部组件的写法和全局组件差不多,唯一不同就是:局部组件要写在 Vue 实例里面。

<!-- 全局组件 --><body>    <div id="app">    <!-- 使用组件 -->    <renda-header></renda-header>    </div></body><script src="js/vue.min.js"></script><script>    // 定义全局组件    // 组件的命名规则:一般用短横线进行连接,左边是公司名,右边组件的作用名称    Vue.component("renda-header", {        // template 模板中只能有一个根元素        template: "<div>TEST <h1 @click='hello'>{{msg}}</h1> </div>",        data() {            // 组件中的 data 是一个函数            return {                msg: "This is the data part of the renda-header",            };        },        methods: {            hello() {                alert("Hello !");            },        },    });​    var VM = new Vue({        el: "#app",        data: {},        methods: {},    });</script><!-- 局部组件 --><body>    <div id="app">        <web-msg></web-msg>    </div></body><script src="js/vue.min.js"></script><script>    var VM = new Vue({       el: "#app",       components: {           "web-msg": {               template: "<div><h1>{{msg1}}</h1><h1>{{msg2}}</h1></div>",               data() {                   return {                       msg1: "Developing...",                       msg2: "Development finished"                   }               },           }       }    });</script><!-- 组件与模板分离 --><!-- 由于把 html 语言写在组件里面很不方便且不好看,所以将它们分开写 --><body>    <div id="app">        <!-- 使用组件 -->        <web-msg></web-msg>    </div>​    <!-- 将模板写在 HTML 中,给模板一个 id -->    <template id="t1">        <div>            <button @click="show">{{msg}}</button>        </div>    </template></body><script src="js/vue.min.js"></script><script>    var VM = new Vue({       el: "#app",       components: {           "web-msg": {               template: "#t1",               data() {                   return {                       msg: "Search"                   }               },               methods: {                   show() {                       alert("Please wait...");                   }               },           }       }     });</script>
  • 组件与模板分离后,浏览器会把 html 里的 template 标签过滤掉;所以 template 标签的内容是不会在页面中展示的,直到它被 JS 中的 Vue 调用。
  • 在 html 中,template 标签一定要有一个 id,因为通过 id 是最直接被选中的;data 和 methods 等参数,全部都要放到 Vue 实例里面写。


Vue 生命周期

每个 Vue 实例在被创建之前都要经过一系列的初始化过程,这个过程就是 Vue 的生命周期。

生命周期中的钩子函数:钩子函数是在一个事件触发的时候,在系统级捕获到了他,然后做一些操作。

  • beforeCreate() - 在创建 Vue 实例之前,可以执行这个方法,例如加载动画操作。
  • created() - 实例创建完成,属性绑定好了,但是 DOM 还没有生成。
  • beforeMount() - 模板已经在内存中编辑完成了,尚未被渲染到页面中。
  • mounted() - 内存中的模板已经渲染到页面,用户已经可以看见内容。
  • beforeUpdate() - 数据更新的前一刻,组件在发生更新之前,调用的函数。
  • updated() - updated 执行时,内存中的数据已更新,并且页面已经被渲染。
  • beforeDestroy () - 钩子函数在实例销毁之前调用。
  • destroyed () - 钩子函数在 Vue 实例销毁后调用。
<body>    <div id="app">        <h2 id="msg">{{message}}</h2>        <button @click="next">Next</button>    </div></body><script src="js/vue.min.js"></script><script>    var VM = new Vue({       el: "#app",       data: {           message: "I am Renda Zhang",       },       methods: {           show() {               alert("show method is executed");           },           next() {               this.message = "Who are you?";           }       },       // 在 Vue 对象实例化之前执行       beforeCreate() {           alert("Before Create");           console.log(this.message); // undefined           this.show(); // error       },       // 组件的实例化完成,但是 DOM 页面还未生成       created() {           alert("Created");           console.log(this.message);           this.show();       },       // 模板已经在内存中编辑完成了,但是还没有被渲染到页面中       beforeMount() {           alert("Before Mount");           console.log("Page content: " + document.getElementById("msg").innerText);           console.log("data: " + this.message);       },       // 模板已经被渲染到页面,执行完就会显示页面       mounted() {           alert("Mounted");           console.log("Page content: " + document.getElementById("msg").innerText);       },        // 内存中的数据已经更新,但是还没有渲染到页面        beforeUpdate() {            alert("Before Update");            console.log("Page content: " + document.getElementById("msg").innerText);            console.log("data: " + this.message);        },        //  内存中的数据已经更新,此方法执行完显示页面        updated() {            alert("Updated");            console.log("Page content: " + document.getElementById("msg").innerText);            console.log("data: " + this.message);        },    });</script>


Vue Router 路由

什么是路由?

在 Web 开发中,路由是指根据 URL 分配到对应的处理程序。

路由允许我们通过不同的 URL 访问不同的内容。

通过 Vue.js 可以实现多视图单页面 web 应用。

什么是单页面应用?

单页面 Web 应用(single page web application,SPA),就是只有一张 Web 页面的应用,是加载单个 HTML 页面并在用户与应用程序交互时动态更新该页面的 Web 应用程序。

单页应用不存在页面跳转,它本身只有一个 HTML 页面;传统意义上的页面跳转在单页应用的概念下转变为了 body 内某些元素的替换和更新。

整个 body 的内容从登录组件变成了欢迎页组件,从视觉上感受页面已经进行了跳转。但实际上,页面只是随着用户操作,实现了局部内容更新,依然还是在 index.html 页面中。

单页面应用的好处:

  • 用户操作体验好,用户不用刷新页面,整个交互过程都是通过 Ajax 来操作。
  • 适合前后端分离开发,服务端提供 http 接口,前端请求 http 接口获取数据,使用 JS 进行客户端渲染。

路由相关的概念

  • router:是 Vue.js 官方的路由管理器。它和 Vue.js 的核心深度集成,让构建单页面应用(SPA)变得易如反掌,router 就相当于一个管理者,它来管理路由。
  • route:router 相当于路由器,route 就相当于一条路由。比如,Home 按钮 => home 内容, 这是一条 route;news 按钮 => news 内容, 这是另一条 route。
  • routes:是一组路由。把上面的每一条路由组合起来,形成一个数组。[{ home 按钮 => home 内容 }, { about 按钮 => about 内容 }]。
  • router-link 组件: router-link 是一个组件,是对 <a> 标签的一个封装。该组件用于设置一个导航链接,切换不同 HTML 内容。 to 属性为目标地址, 即要显示的内容。
  • router-view 组件:路由导航到指定组件后,进行渲染显示页面。

使用路由

Vue.js 路由需要载入 vue-router 库:

// 方式 1: 本地导入<script src="vue-router.min.js"></script>​// 方式 2: CDN<script src="https://unpkg.com/vue-router/dist/vue-router.js"></script>

使用步骤:

  1. 定义路由所需的组件
  2. 定义路由,每个路由有两部分 path(路径),component(组件)
  3. 创建 router 路由器实例,管理路由
  4. 创建 Vue 实例,注入路由对象,使用 $mount() 指定挂载点

Vue 的 $mount() 为手动挂载,在项目中可用于延时挂载(例如在挂载之前要进行一些其他操作、判断等),之后要手动挂载上。新建 Vue 时,el 和 $mount 并没有本质上的不同。

<body>    <div id="app">        <h1>renda.com</h1>​        <p>            <!-- 添加超链接,router-link 组件来进行导航,to 属性指定链接 -->            <router-link to="/home">Go to Home</router-link>            <router-link to="/news">Go to News</router-link>        </p>​        <!-- 路由的出口,路由匹配到组件之后,要渲染到这里 -->        <router-view></router-view>    </div></body><script src="js/vue.min.js"></script><script src="js/vue-router.min.js"></script><script>    // 定义路由所需的组件    const home = { template: "<div>首页</div>" };    const news = { template: "<div>新闻</div>" };​    // 定义路由,每个路由有两部分 path(路径),component(组件)    const routes = [        { path: "/home", component: home },        { path: "/news", component: news },    ];​    // 创建路由管理器实例    const router = new VueRouter({        routes: routes,    });​    // 创建 Vue 实例,将 router 注入到 vue 实例中,让整个应用都拥有路由的功能    var VM = new Vue({        router,        // 代替 el    }).$mount("#app");</script>
  • router 是 Vue 中的路由管理器对象,用来管理路由
  1. route 是路由对象,一个路由就对应了一条访问路径,一组路由用 routes 表示
  2. 每个路由对象都有两部分 path(路径)和 component(组件)
  3. router-link 是对 a 标签的封装,通过 to 属性指定连接
  4. router-view 路由访问到指定组件后,进行页面展示