前端技术学习-Vue

129 阅读16分钟

一.Vue.js

1.1 Vue.js是什么?

Vue (读音 /vjuː/,类似于 view) 是一套用于构建用户界面的渐进式框架。与其它大型框架不同的是, Vue 被设计 为可以自底向上逐层应用.

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

1.2 为什么使用Vue?

  1. 声明式渲染: 前后端分离是未来趋势
  2. 渐进式框架: 适用于各种业务需求
  3. 简单易学: 国人开发,中文文档,不存在语言障碍,易于理解和学习

二.Vue.js 基础

2.1 ## 引入Vue.js库

想使用Vue需要在html界面载入Vue.js的库,两种方式:

image.png

<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <!-- 1.引入vue.js -->
    <!-- <script src="https://cdn.jsdelivr.net/npm/vue@2.5.16/dist/vue.js"></script>  -->
    <script src ="js/vue.min.js"></script>

2.2 插件的安装

image.png

2.3 data存储复杂数据

使用data存储复杂数据:

<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <!-- 1.引入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>
    <!-- 2.创建ID为APP的Div -->
     <div id ="app">
    {{name}}<br>
    {{school.name}} {{school.mobile}}<br>
        <ul>
            <li>{{names[0]}}</li>
            <li>{{names[1]}}</li>
            <li>{{names[2]}}</li>

        </ul>
     </div>
     <div>
        {{name}}
     </div>
</body>

<script>
//3.创建vue实例
var VM = new Vue({
el:"#app",
data:{
    name:"Hello Vue!!",
    //对象类型
    school:{
        name:"拉钩教育",
        mobile:"1001001",
    },
    //数组类型
    names:["尼古拉斯","赵四","凯撒"]




},


{{}}: 插值表达式 插值表达式的作用?

通常用来获取Vue实例中定义的数据(data)

属性节点中 不能够使用插值表达式

el: 挂载点

el的作用?

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

Vue的作用范围是什么 ?

Vue会管理el选项命中的元素,及其内部元素

el选择挂载点时,是否可以使用其他选择器 ?

可以,但是建议使用 ID选择器

是否可以设置其他的DOM元素进行关联 ?

可以但是建议选择DIV, 不能使用HTML和Body标签

2.4 声明式渲染的好处

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

<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<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 Wrold</h2>");
    });
</script> -->
<script src ="js/vue.min.js"></script>
<script>
    var VM =new Vue({
        el:"#app", //挂载点
        data:{
            name:"Hello Wrold!"
        },

    });
</script>
</html>

不使用声明式渲染的话 需要拼接数据输出

使用声明式渲染 就可以直接把数据使用插值表达式输出

2.5 Vue常用指令

根据官网的介绍,指令 是带有 v- 前缀的特殊属性。通过指令来操作DOM元素

(1) v-text 指令

作用: 获取data数据, 设置标签的内容.

注意: 默认写法会替换全部内容,使用插值表达式{{}}可以替换指定内容. 代码示例:

<html lang="en">
<head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<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 Vue({
        el:"#app",
        data: {
            message:"Java程序员",
            
        },


    });

</script>
</html>

(3)v-html指令

v-html 指令;设置元素的innerHTML,向元素中写入标签

<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <style>
        /*
        v-html 指令;设置元素的innerHTML,向元素中写入标签
        */
    </style>
</head>

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



});

</script>

</html>

v-html可以设置元素的innerHTML,但v-text不可以,v-text会把原本的代码输出出来。

image.png

(3)v-on指令

作用: 为元素绑定事件, 比如: v-on:click,可以简写为 @click="方法" 绑定的方法定义在 VUE实例的, method属性中

<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <style >
    /* 
        v-on指令:作用是为1元素绑定事件
    */

    </style>
</head>

<body>
    <div id ="app">
        <input type="button" value ="点击按钮" v-on:click="show" />
        <!-- 简写方式 -->
        <input type="button" value ="点击按钮" @click="show" />
        <!-- 绑定双击事件 -->
        <input type="button" value ="双击按钮" @dblclick="show" />
        <!-- 绑定事件,点击后修改当前内容 -->
            <h2 @click="changeFood">{{food}}</h2>
    </div>
</body>
<script src="js/vue.min.js"></script>
<script>
    var VM = new Vue({
        el:"#app",
        data:{
            food:"麻辣小龙虾"
        },
        //通过methods专门存放Vue的方法 
        methods:{
            show:function(){
                alert("程序员在加班!!");

            },
            changeFood:function(){
            console.log(this.food); //保存    
                //使用this获取data中的数据
                //在vue中不需要考虑如何更改DOM,重点放在修改数据上,数据更新后,使用数据的那个元素也会同步更新
                this.food+="真好吃";

            },

        },




    });
    

image.png

image.png 一直点的话字体会一直增加 image.png

(4)计数器案例

image.png 首先准备页面

    <div id="app">
        <!-- 计算功能区域 -->
        <div>
            <input type="button" class="btn btn_plus">
            <span>{{num}}</span>
            <input type="button" class="btn btn_minus">
        </div>
    </div>
 </body>
 <script src="vue.min.js"></script>
 <script>
    //创建VUE实例
    var VM = new Vue({
        el:"#app",
        data:{
            num:1
        }
    })
 </script>

全部代码;

<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <link rel="stylesheet" href="css/inputNum.css" />
</head>
<body>
    <div id="app">
        <!-- 计算功能区域 -->
        <div>
            <input type="button" class = "btn btn_plus"  v-on:click="add"/>  
            <span>{{num}}</span> 
            <input type="button" class = "btn btn_minus" @click="sub"/>     

        </div>




    </div>
</body>
<script src = "js/vue.min.js"></script>
<script>
    var VM = new Vue({
        el:"#app",
        data:{
            num : 1,


        },
        methods:{
            add:function(){
                if(this.num < 10){
                    this.num++;
                }else{
                    alert("别点了");

                }

            },
            sub:function(){
                if(this.num > 0){
                    this.num--;
                }else{
                    alert("最小了");
                }
            }
        }

    });
</script>
</html>

image.png

(5)v-show指令

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

    <div id="app">
        <img src="./img/car.gif" alt="">
    </div>
 </body>
 <script src="vue.min.js"></script>
 <script>
    var VM = new Vue({
        el:"#app"
    })
 </script>
 

代码示例:

<html lang="en">
<head>  
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <style>
        /* 
        v-show:根据真假值,切换元素的显示状态
         */
    </style>
</head>
<body>
    <div id="app">
        <img v-show  = "isShow" src="img/loading.gif" />
        <input type="button" value="切换状态" @click="changeShow" />
        <img v-show="age > 18" src ="img/loading.gif" />
    </div>
 </body>
 <script src="js/vue.min.js"></script>
 <script>
    var VM = new Vue({
       el:"#app",
       data:{
        isShow:false,
        age:19,
       },
       methods:{
        changeShow:function(){
                //触发方法,对isShow进行取反
                this.isShow=!this.isShow;

        }
       }
    });
 </script>
</html>

三种方式:isShow的值改成true或者flase直接输出

写方法对isShow取反输出

以及直接在<img>里写判断输出

image.png

(6) v-if 指令

作用: 根据表达值的真假,切换元素的显示和隐藏( 操纵dom 元素)

代码示例:

<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <style>
        /* 
            v-if指令:根据表达式的真假,切换元素的显示和隐藏(操作的是dom)
            频繁切换就是用v-show,
            反之使用v-if
            */
    </style>
</head>
<body>
<div id="app">
    <input type="button" value = "切换状态" @click="changeShow">
    <img v-if="isShow" src="img/loading.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>
</html>

频繁切换就是用v-show,

反之使用v-if

image.png

(7) v-bind 指令

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

语法格式:  v-bind:属性名=表达式
<img v-bind:src="imgSrc">
 var VM = new Vue({
 el:"#app",
 data:{
 imgSrc:"图片地址"
 }
 })
 v-bind 可以省略,简写为冒号 :
<img :src="imgSrc">

代码示例:

<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
    <style>
      /*
      v-bind : 设置元素的属性 src class
      语法: v-bind:属性名=表达式

      作用: 为元素绑定属性
      完整写法: v-bind:属性名 = 表达式 ,简写 :属性=表达式
    */
    </style>
  </head>
  <body>
    <div id="app">
      <img src="img/loading.gif" alt="" />

      <!-- 使用 v-bind 设置src属性 -->
      <img v-bind:src="imgSrc" />

      <!-- v-bind 可以简写为 : -->
      <img v-bind: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/loading.gif",
        imgTitle: "拉钩教育",
        size: 50,
      },
    });
  </script>
</html>


image.png

image.png

(8) v-for 指令

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

数组经常和 v-for结合使用,数组有两个常用方法: push() 向数组末尾添加一个或多个元素

shift() 把数组中的第一个元素删除

语法是: (item,index) in 数据

item和index 可以结合其他指令一起使用

数组的长度变化,会同步更新到页面上,是响应式的

代码示例:

<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
    <style>
      /*
      v-for指令:根据数据生成列表结构
        1.数组经常和v-for结合使用
        2.语法格式: (item,index) in 数据
        3.数组的长度变化,会同步更新到页面上, 响应式的
    */
    </style>
  </head>
  <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 () {
          //向数组添加元素 push
          this.persons.push({ name: "小斌" });
        },
        remove: function () {
          //移除数据
          this.persons.shift();
        },
      },
    }); 
  </script>
</html>

image.png

(9) v-on 指令补充

  1. 传递自定义参数 : 函数调用传参
  2. 事件修饰符: 对事件触发的方式进行限制
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
    <style>
      /*
        1.函数调用传参
          事件绑定方法后,可以传递参数
          定义方法时,需要定义形参,来接收参数
          
        2.事件修饰符
          可以对事件进行限制, .修饰符
          .enter 可以限制触发的方式为 回车
    */
    </style>
  </head>
  <body>
    <div id="app">
      <!-- 函数传参 -->
      <input
        type="button"
        value="礼物刷起来"
        @click="showTime(666,'爱你老铁!')"
      />

      <!-- 事件修饰符 指定哪些方式可以触发事件 -->
      <input type="text" @keyup.enter="hi" />
    </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);
        },
        hi: function () {
          alert("你好吗?");
        },
      },
    });
  </script>
</html>

image.png

image.png

(10).MVVM模式

MVVM 是Model-View-ViewModel 的缩写,它是一种基于前端开发的架构模式.

MVVM模式将页面分成了 M 、V、和VM ,解释为:

Model: 负责数据存储 ------ View: 负责页面展示 ------View Model: 负责业务逻辑处理(比如Ajax请求等),对数据进行加工后交给视图展示

image.png

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

从View侧看,ViewModel中的DOM Listeners工具会帮我们监测页面上DOM元素的变化,如 果有变化,则更改Model中的数据;

从Model侧看,当我们更新Model中的数据时,Data Bindings工具会帮我们更新页面中的 DOM元素

(11).v-mode 指令

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

单向绑定: 就是把Model绑定到View,当我们用JavaScript代码更新Model时,View就会自动 更新。

双向绑定: 用户更新了View,Model的数据也自动被更新了,这种情况就是双向绑定。

什么情况下用户可以更新View呢?

填写表单就是一个最直接的例子。当用户填写表单时,View的状态就被更新了,如果此时 MVVM框架可以自动更新Model的状态,那就相当于我们把Model和View做了双向绑定:

<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
    <style>
      /* 
        v-model: 实现双向数据绑定
        单向数据绑定: 将model绑定到view上,当model发生变化时,view会随之变化
        双向数据绑定: view视图发生变化时,model也会随之改变
       */
    </style>
  </head>
  <body>
    <div id="app">
      <input type="button" value="修改message" @click="update" />

      <!-- View 视图 -->
      <!-- <input type="text" v-bind:value="message" /> -->

      <!-- v-model 实现双向数据绑定 -->
      <input type="text" v-model="message" />
      <input type="text" v-model="password" />
      <h2>{{message}}</h2>
    </div>
  </body>
  <script src="./js/vue.min.js"></script>
  <script>
    //VM 业务逻辑控制
    var VM = new Vue({
      el: "#app",
      //Model 数据存储
      data: {
        message: "拉钩教育训练营",
        password: 123,
      },
      methods: {
        update: function () {
          this.message = "拉钩";
        },
      },
    });
  </script>
</html>

image.png

(12) 实现简单记事本

image.png 实现一个如图所示的记事本 输入框用来对记事本添加文本,左下角显示当前记事本文本数,右下角删除当前记事本所有内容. 代码示例:

  <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="../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>
      <!-- 1.使用v-for指令生成列表结构 -->
      <!-- 列表区域 -->
      <section class="main">
        <ul class="listview">
          <li class="todo" v-for = "(item,index) in list">
            <div class="view">
              <span class="index">{{index+1}}</span> <label>{{item}}</label>
              <!-- 2.删除操作 传递index -->
              <button class="destroy" @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:["写代码","吃饭","睡觉"],
                    inputValue:"996还是997",

                },
                methods:{
                    //新增日程
                    add:function(){
                        //将用户输入的内容添加到list
                        this.list.push(this.inputValue);
                    },
                remove:function(index){
                    console.log(index);
                    //使用 splice(接收两个参数:元素的索引,删除几个对象)
                    this.list.splice(index,1); // index为元素索引 1为删除对象
                },
                //清空操作
                clear:function(){
                  this.list=[];  
                }
                },
                




        });


    </script>

  </body>
</html>

三.axios

3.1 Ajax回顾

Ajax 是指一种创建交互式网页应用的开发技术。Ajax = 异步 JavaScript 和 XML。

Ajax的作用

Ajax  可以使网页实现异步更新。这意味着可以在不重新加载整个网页的情况下,对网页的某部分 进行更新(局部更新)。传统的网页如果需要更新内容,必须重载整个网页页面。

简单记: Ajax 是一种在无需重新加载整个网页的情况下,能够更新部分网页的技术, 维护用户体验 性, 进行网页的局部刷新.

异步与同步: 浏览器访问服务器的方式

同步访问: 客户端必须等待服务器端的响应,在等待过程中不能进行其他操作 。

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

image.png Ajax案例演示:

<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
  </head>
  <body>
    <input type="text" />
    <input type="button" value="Jquery发送异步请求" onclick="run1()" />
  </body>
  <script src="./js/jquery-1.8.3.min.js"></script>
  <script>
    function run1() {
      $.ajax({
        url: "http://localhost:8080/ajax",
        async:true,
        data: { name: "天青" },
        type: "post",
        success: function () {
          alert("响应成功");
        },
        error: function () {
          alert("响应失败!");
        },
      });
    }
  </script>
</html>


Java中的Servlet文件

 public class AjaxServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) 
throws ServletException, IOException {
        //1.获取请求数据
        String username = req.getParameter("name");
        //模拟业务操作,造成的延时效果
        try {
            Thread.sleep(5000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        //2.打印username
        System.out.println(username);
        resp.getWriter().write("hello hello");
    }
    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) 
throws ServletException, IOException {
        doGet(req, resp);
    }
   }

3.2 axios介绍

axios是目前十分流行网络请求库,专门用来发送请求,其内部还是ajax,进行封装之后使用更加方便

axios作用: 在浏览器中可以帮助我们完成 ajax异步请求的发送.

axios使用步骤:

1.导包

<!-- 官网提供的 axios 在线地址 -->
 <script src="https://unpkg.com/axios/dist/axios.min.js"></script>

2.请求方式:

以GET和POST举例

image.png

image.png

测试一下axios,我们设置两个接口

接口1(笑话接口):

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

接口2(用户注册):

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

代码示例:

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
    <style>
      /*
        axios总结
          1.axios必须要导包
          2.使用get或者post方式发送请求
          3.then方法 中的回调函数,会在请求成功或者失败的时候被触发
          4.通过回调函数的形参,可以获取响应的内容
      */

    </style>
  </head>
  <body>
    <input type="button" value="get请求" id="get" />
    <input type="button" value="post请求" id="post" />
  </body>
  <script src="js/axios.min.js"></script>
  <script>
    /*
    随机笑话接口测试
      请求地址:https://autumnfish.cn/api/joke/list
      请求方法:get
      请求参数:num(笑话条数,数字)
      响应内容:随机笑话
  */
    document.getElementById("get").onclick = function () {
      axios.get("https://autumnfish.cn/api/joke/list?num=1").then(
        function (resp) {
          //调用成功
          console.log(resp);
        },
        function (err) {
          //调用失败
          console.log(err);
        }
      );
    };

    /*
    用户注册
      请求地址:https://autumnfish.cn/api/user/reg
      请求方法:post
      请求参数:username:"用户名"
      响应内容:注册成功或失败
    */
    document.getElementById("post").onclick = function () {
      axios.post("https://autumnfish.cn/api/user/reg", { username: "张abc" }).then(
          function (resp) {
            console.log(resp);
          },
          function (error) {
            console.log(error);
          }
        );
    };
  </script>
</html>

axios总结:

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

3.3 获取笑话案例

通过vue+axios 完成一个获取笑话的案例.

接口: 随机获取一条笑话

请求地址:https://autumnfish.cn/api/joke
 请求方法:get
 请求参数:无
 响应内容:随机笑话

代码示例:

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>vue+axios获取笑话</title>
    <style>
      /*
        1.axios回调函数中,this的指向已经改变,无法访问data中的数据
        2.解决方案: 将this进行保存
      */
    </style>
  </head>
  <body>
    <div id="app">
      <input type="button" value="点击获取一个笑话" @click="getJoke" />
      <p>{{joke}}</p>
    </div>
  </body>

  <script src="../js/vue.min.js"></script>
  <script src="../js/axios.min.js"></script>
  <script>
    /*
        请求地址:https://autumnfish.cn/api/joke
        请求方法:get
        请求参数:无
        响应内容:随机笑话
    */
    var VM = new Vue({
      el: "#app",
      data: {
        joke: "笑口常开",
      },
      methods: {
        getJoke: function () {
          //把this进行保存
          var that = this;

          //异步访问
          axios.get("https://autumnfish.cn/api/joke").then(
            function (resp) {
              console.log(resp.data);
              //在回调函数内部 ,this无法正常使用,需要提前保存起来
              console.log(that.joke); //undefined
              that.joke = resp.data;
            },
            function (error) {}
          );
        },
      },
    });
  </script>
</html>

3.4 天气查询案例

功能分析:

回车查询

1.输入内容,点击回车 (v-on.enter)

2.访问接口,查询数据 (axios v-model)

3.返回数据,渲染数据

接口文档

image.png

需要额外的写一个自己的js文件,在main.js写方法

作为一个标准的应用程序,我们将创建VUE实例的代码,抽取到main.js 文件中

main.js

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

var VM = new Vue({
  el: "#app",
  data: {
    city: "",
    //定义数组保存 天气信息
    weatherList: [],
  },
  //编写查询天气的方法
  methods: {
    searchWeather: function () {
      console.log("天气查询");
      console.log(this.city);

      var that = this;

      //调用接口
      axios.get("http://wthrcdn.etouch.cn/weather_mini?city=" + this.city).then(
        function (resp) {
          console.log(resp.data.data.forecast);
          //获取天气信息 保存到weatherList
          that.weatherList = resp.data.data.forecast;
        },
        function (error) {}
      );
    },
  },
});

主体

<body>
    <div class="wrap" id="app" v-cloak>
      <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">回车查询</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>
      </ul>
    </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>
    <!-- 自己的js -->
    <script src="./js/main.js"></script>
  </body>



天气案例总结

  1. 应用的逻辑代码,建议与页面进行分离,使用单独的JS编写
  2. axios回调函数中的 this的指向改变,无法正常使用, 需要另外保存一份
  3. 服务器返回的数据比较的复杂时,获取数据时要注意层级结构

解决BUG:页面闪烁问题

v-cloak指令

作用: 解决插值表达式闪烁问题

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

<style>
 /* 通过属性选择器,设置 添加了v-cloak */
 [v-cloak] {
 display: none;
 }
 </style>

然后在id为"app"的div中写下:

<div class="wrap" id="app" v-cloak>

四.Vue进阶

4.1 computed 计算属性

什么是计算属性 在Vue应用中,在模板中双向绑定一些数据或者表达式,但是表达式如果过长,或者逻辑更为复杂 时,就会变得臃肿甚至难以维护和阅读,比如下面的代码:

写在双括号中的表达式太长了,不利于阅读 {{text.split(',').reverse().join(',')}}

.将这段操作text.split(',').reverse().join(',')  放到计算属性中,最终返回一个结果值就可以

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

代码示例:

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=<device-width>, initial-scale=1.0" />
    <title>Document</title>
    <style>
      /*
        1.计算属性可以 减少运算次数,用于重复相同的计算
        2.定义函数也可以实现与计算属性相同的效果,但是计算属性可以简化运算
      */
    </style>
  </head>
  <body>
    <div id="app">
      <!-- <h1>{{a*b}}</h1>
      <h1>{{a*b}}</h1> -->
      <!-- 
      <h1>{{res()}}</h1>
      <h1>{{res()}}</h1> -->

      <h1>{{res2}}</h1>
      <h1>{{res2}}</h1>
    </div>
  </body>
  <script src="./js/vue.min.js"></script>
  <script>
    var VM = new Vue({
      el: "#app",
      data: {
        a: 10,
        b: 20,
      },
      methods: {
        res: function () {
          console.log("res方法执行了! !");
          return this.a + this.b;
        },
      },
      //使用计算属性 进行优化,减少运算次数,用于重复的运算
      computed: {
        res2: function () {
          console.log("res2方法执行了! !");
          return this.a + this.b;
        },
      },
    });
  </script>
</html>

computed总结

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

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

4.2 filter 过滤器

什么是过滤器:

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

Vue中过滤器分为全局过滤器和局部过滤器

过滤器的使用位置:

1.插值表达式内:

{{ msg | filterA }}  msg是需要处理的数据, filterA是过滤器, | 这个竖线是管道,通过这个管道
将数据传输给过滤器进行过滤 加工操作
  1. v-bind里:
<h1 v-bind:id=" msg | filterA"> {{ msg }} </h1>

(1)全局过滤器:

全局过滤器只需要把过滤器的表达式放在创建Vue实例的语句前就会形成全局过滤

需求: 将用户名开头字母大写

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
    <style>
      /*
        需求: 将用户名开头字母大写
        总结:
          1.过滤器经常被用来处理文本格式化操作
          2.过滤器使用的两个位置: {{}} 插值表达式中, v-bind表达式中
          3.过滤器是通过管道传输数据的 |
      */
    </style>
  </head>
  <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) {
      //将姓名的开头字母大写
      return value.charAt(0).toUpperCase() + value.slice(1);
    });

    var VM = new Vue({
      el: "#app",
      data: {
        user: { name: "jack" },
      },
    });

   
  </script>
</html>

(2)局部过滤器:

局部过滤需要把过滤器的表达式放在Vue实例里面

需求:将用户名开头字母大写

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
  </head>
  <body>
    <div id="app">
      <!-- 使用插值表达式,调用过滤器 -->
      <p>电脑价格: {{price | addIcon}}</p>
      <h1 v-bind:id=" msg | filterA"> {{ msg }} </h1>
    </div>
  </body>
  <script src="./js/vue.min.js"></script>
  <script>
    //局部过滤器 在vue实例的内部创建filter
    var VM = new Vue({
      el: "#app", //挂载点
      data: {
        //model
        price: 200,
      },
      methods: {
        //方法
      },
      computed: {
        //计算属性
      },

      //局部过滤器
      filters: {
        //定义处理函数 value = price
        addIcon(value) {
          return "$" + value;
        },
      },
    });
  </script>
</html>

过滤器总结:

  1. 过滤器常用来处理文本格式化的操作。过滤器可以用在两个地方:双花括号插值和 v-bind 表达式

  2. 过滤器应该被添加在 JavaScript 表达式的尾部,由“管道”符号指示

4.3 监听器

什么是监听器

Vue.js 提供了一个方法 watch,它用于观察Vue实例上的数据变动。

作用: 当你有一些数据需要随着其它数据变动而变动时,可以使用侦听属性

案例展示;

(实时显示姓名)

image.png

在文本框里输入时 在文本框右边会同步显示 这就是监听器的作用:

<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
  </head>
  <body>
    <div id="app">
      <label>名:<input type="text" v-model="fristName" /></label>
      <label>姓:<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: {
        fristName: "",
        lastName: "",
        fullName: "",
      },
      //侦听器
      watch: {
        fristName: function (nval, oval) {
          //参数 1.新值,2.旧值
          this.fullName = nval + " " + this.lastName;
        },
        lastName: function (nval, oval) {
          this.fullName = this.fristName + " " + nval;
        },
      },
    });
  </script>
</html>

4.4 Component组件

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

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

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

vue的组件有两种: 全局组件 和 局部组件

全局组件:

语法格式:

写在Vue实例外面

组件的命名规则: 一般用短横线进行连接,左边是公司名 右边组件的作用名称

Vue.component("组件名称", {
 template: "html代码",  // 组件的HTML结构代码
data(){ //组件数据
return {}
 },
 methods: {  // 组件的相关的js方法
方法名(){
 // 逻辑代码
}
 }
 })

注意:

  1. 组件名以小写开头,采用短横线分割命名: 例如 hello-Word
  2. 组件中的data 必须是一个函数,注意与Vue实例中的data区分
  3. 在template模板中, 只能有一个根元素

代码示例:

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
  </head>
  <body>
    <div id="app">
      <!-- 使用组件 -->
      <lagou-header></lagou-header>
    </div>
  </body>
  <script src="./js/vue.min.js"></script>
  <script>
    //定义全局组件
    //组件的命名规则: 一般用短横线进行连接,左边是公司名 右边组件的作用名称
    Vue.component("lagou-header", {
      template: "<div>HTML <h1 @click='hello'>{{msg}}</h1> </div>", //template模板中 只能有一个根元素
      //组件中的data是一个函数
      data() {
        return {
          msg: "这lagou-header是组件中的数据部分",
        };
      },
      methods: {
        hello() {
          alert("你好");
        },
      },
    });

    var VM = new Vue({
      el: "#app",
      data: {},
      methods: {},
    });
  </script>
</html>

局部组件:

相比起全局组件,局部组件只能在同一个实例内才能被调用。局部组件的写法和全局组件差不多。 唯一不同就是:局部组件要写在Vue实例里面。

语法格式:

 new Vue({
    el: "#app",
    components: {
        组件名: {
            // 组件结构
            template: "HTML代码",
            // data数据
            data() { return { msg:"xxxx" };},
        },
    },
 });

注意: 创建局部组件,注意 components,注意末尾有 ‘s’,而全局组件是不用+ ‘s’ 的。这意味着, components里可以创建多个组件

代码示例:

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
  </head>
  <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:"开发ing...",
              msg2:"开发完成!"
            }
          },
        }
      }

    })
  </script>
</html>

4.5 组件与模板分离

由于把html语言写在组件里面很不方便,也不太好看所以将它们分开写。

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
  </head>
  <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: "点击查询",
            };
          },
          methods: {
            show() {
              alert("正在查询,请稍后...");
            },
          },
        },
      },
    });
  </script>
</html>

总结:

  1. 上面这种写法,浏览器会把 html 里的 template 标签过滤掉。所以 template 标签的内容是不会 在页面中展示的。直到它被 JS 中的 Vue 调用。
  2. 在 html 中,template 标签一定要有一个 id,因为通过 id 是最直接被选中的。 data 和 methods 等 参数,全部都要放到 Vue 实例里面写

五.Vue生命周期

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

image.png

image.png

5.1 钩子函数介绍

生命周期中的钩子函数

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

image.png 代码示例:

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
  </head>
  <body>
    <div id="app">
      <h2 id="msg">{{message}}</h2>
      <button @click="next">获取下一句</button>
    </div>
  </body>
  <script src="./js/vue.min.js"></script>
  <script>
    var VM = new Vue({
      el: "#app",
      data: {
        message: "想当年,金戈铁马",
      },
      methods: {
        show() {
          alert("show方法执行了!");
        },
        next() {
          this.message = "气吞万里如虎!";
        },
      },
      // beforeCreate() {
      //   alert("1.beforeCreate函数,在Vue对象实例化之前执行");
      //   console.log(this.message); //undefined
      //   this.show(); //this.show is not a function
      // },
      // created() {
      //   alert("2.created函数执行时,组件的实例化完成,但是DOM页面还未生成")
      //   console.log(this.message);
      //   this.show();
      // },
      // beforeMount() {
      //   alert(
      //     "3.beforeMount函数执行时,模板已经在内存中编辑完成了,但是还没有被渲染到页面中"
      //   );
      //   console.log(
      //     "页面显示的内容" + document.getElementById("msg").innerText
      //   );
      //   console.log("data中的数据: " + this.message);
      // },
      // mounted() {
      //   alert("4.mounted函数执行时,模板已经被渲染到页面,执行完就会显示页面");
      //   console.log(
      //     "页面显示的内容" + document.getElementById("msg").innerText
      //   );
      // },
      // beforeUpdate() {
      //   alert("5.beforeUpdate执行时,内存中的数据已经更新,但是还没有渲染到页面");
      //   console.log(
      //     "页面显示的内容" + document.getElementById("msg").innerText
      //   );
      //   console.log("data中的数据: " + this.message);
      // },
      updated() {
        alert("6.updated执行时,内存中的数据已经更新,此方法执行完显示页面");
        console.log(
          "页面显示的内容" + document.getElementById("msg").innerText
        );
        console.log("data中的数据: " + this.message);
      },
    });
  </script>
</html>

六.Vue Router 路由

什么是路由?

在Web开发中,路由是指根据URL分配到对应的处理程序。 路由允许我们通过不同的 URL 访问不同的 内容。

通过 Vue.js 可以实现多视图单页面web应用(single page web application,SPA)

image.png

什么是SPA ?

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

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

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

单页面应用的好处

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

6.1 路由相关的概念

image.png

6.2 使用路由

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

HTML代码

<body>
 <div id="app">
 <h1>渣浪.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>

js代码:

<script src="./vue.min.js"></script>
 <script src="./vue-router.min.js"></script>
 <script>
 //1.定义路由所需的组件
const home = { template: "<div>首页</div>" };
 const news = { template: "<div>新闻</div>" };
 //2.定义路由 每个路由都有两部分 path和component
 const routes = [
 { path: "/home", component: home },
 { path: "/news", component: news },
 ];
 //3.创建router路由器实例,对路由对象routes进行管理.
 const router = new VueRouter({
 routes: routes,
 });
 //4.创建Vue实例, 调用挂载mount函数,让整个应用都有路由功能
const VM = new Vue({
 router,
 }).$mount("#app"); //$mount是手动挂载代替el
 </script>

运行结果: 未点击链接之前: image.png

点击链接之后:

image.png

路由总结

  1. router是Vue中的路由管理器对象,用来管理路由.
  2. route是路由对象,一个路由就对应了一条访问路径,一组路由用routes表示
  3. 每个路由对象都有两部分 path(路径)和component (组件)
  4. router-link 是对a标签的封装,通过to属性指定连接
  5. router-view 路由访问到指定组件后,进行页面展示