Vue学习

1、vue介绍

Vue属于JS框架,快速构建前端界面的技术。目前主流版本Vue2和Vue3。

Vue核心思想:不操作dom,通过控制数据(数据驱动),就可以完成页面的所有操作。

学习Vue框架:需要与前面学习的HTML、CSS、JS(DOM)进行对比,知道框架到底帮助我们将哪些技术进行封装(不用书写),哪些技术进行改变。

官网:https://cn.vuejs.org/

2、BS和CS架构

软件设计架构中有两种架构方式:

BS架构:Browser Server :浏览器与服务器模型架构

主要基于浏览器编写网页(HTML、CSS、JS)

CS架构:Client Server : 客户端与服务器模型架构

主要基于H5C3等技术,最终可以生成安卓,苹果等平台的App。

3、设计模式

设计模式:对各种问题的一个有效解决方案。

单例设计模式:保证程序中的对象唯一性。

目标:理解MVVM、MVC、MVP

MV系列技术框架:

  • M:model,模型层(数据、后台返回的、页面获取的、通过表达式运算结果)
  • V:View ,视图层(页面)

MVC:

  • M:model,模型层(数据、后台返回的、页面获取的、通过表达式运算结果)
  • V:View ,视图层(页面)
  • C:Controller,控制器(层),逻辑代码

MVP:

  • M:model,模型层(数据、后台返回的、页面获取的、通过表达式运算结果)
  • V:View ,视图层(页面)
  • P:Presenter:表示器,用于连接M层、V层,完成Model层与View层的交互,还可以进行业务逻辑的处理。

MVVM:目前主流的前端框架底层设计思想

  • M:model,模型层(数据、后台返回的、页面获取的、通过表达式运算结果)
  • V:View ,视图层(页面)
  • VM:ViewModel,视图模型,数据的双向绑定(当Model中的数据发生改变时View就感知到,当View中的数据发生变化时Model也能感知到),是MVVM模式的核心。ViewModel 层把 Model 层和 View 层的数据同步自动化了,解决了 MVP 框架中数据同步比较麻烦的问题,不仅减轻了 ViewModel 层的压力,同时使得数据处理更加方便——只需告诉 View 层展示的数据是 Model 层中的哪一部分即可。

4、Vue体验

4.1、vue入门

# vue2的写法
DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Documenttitle>
head>
<body>
    <div id="app">
        {{count}}
        <button @click="add">数据++button>
    div>
    
    
    
    <script src="./js/vue.js">script>
    <script>
        new Vue({
            el:"#app",
            data:{
                count:0
            },
            methods:{
                add:function(){
                    this.count++;
                }
            }
        })
        
    script>
body>
html>
# vue3的写法
DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Documenttitle>
head>
<body>
    
    <div id="app">
        {{count}}
        <button @click="add">++button>
    div>
    <script src="./js/vue3.js">script>
    <script>
        // vue3不能直接new Vue,需要从Vue底层解构出createApp的函数
        let { createApp } = Vue;
        // 通过createApp函数来完成vue的创建(app实例)
        let app = createApp({
            // 这里书写的data必须是一个函数
            // data:function(){}
            // es6中函数的简化方式
            data(){
                // let  obj = {}
                return {
                    count:0
                };
            },
            methods:{
                add(){
                    console.log("add....");
                    this.count++;
                }
            }
        });
        // console.log(app);
        app.mount("#app");

    script>
body>
html>

5、Vue的基础法语

Vue2与Vue3的基础语法基本相同

5.1、模版语法

模版:在HTML中使用vue相关的语法和指令。

5.1.1、插值表达式(胡须表达式)

在html中可以使用 双大括号完成数据渲染{{ 变量、调用语句、表达式、简单的运算 }}

DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Documenttitle>
head>
<body>
    <div id="app">
        
        <h3>插值表达式:h3>
        
        <p>姓名:{{ username }}p>
        <p>年龄:{{ age }}p>
        <p>性别:{{ sex }}p>
        
        
        <p>加法运算:{{ 1+2 }}p>
        <p>比较运算:{{ 1 < 4 }}p>
        <p>三目运算:{{ age < 18 ? "未成年" : "成年" }}p>
        <button @click="age--">修改年龄button>
        
        <p>{{ addSum }}p>
        
        <p>{{ addSum(2,4) }}p>
    div>
    <script src="./js/vue3.js">script>
    <script>
        let { createApp } = Vue;
        // 创建app对象
        const app = createApp({
            // 使用data定义数据
            data(){
                return{
                    username:"张无忌",
                    age:23,
                    sex:"男"
                }
            },
            methods:{
                addSum(a,b){
                    console.log("a,b", a, b);
                    // return a + b;
                }
            }
        });
        // 让app与页面view进行绑定
        app.mount("#app");
    script>
body>
html>

5.1.2、v-cloak

v-cloak : 用来屏蔽插值表达式在网络等原因导致数据无法渲染的时候,页面会出现{{ name }}

DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Documenttitle>
    <style>
        [v-cloak]{
            display: none;
        }
    style>
head>

<body>
    
    <div id="app">
        <p v-cloak>{{name}}p>
    div>
    <script src="./js/vue3.js">script>
    <script>
        let { createApp } = Vue;
        // 创建app对象
        const app = createApp({
            data(){
                return {
                    name:"杭州"
                }
            }
        });
        // 让app与页面view进行绑定
        app.mount("#app");
    script>
body>

html>

5.2、文本类指令

在vue中提供了大量的指令(一共13个),快速帮助我们完成数据与页面的绑定、渲染等操作。

vue中提供的指令,都是以v-开始,如果某个指令使用频率特别高,会有简化写法。

回顾,在dom中,如果需要获取或者设置标签中的文本数据,可以通过innerHTML、innerText、textContent。

document.querySelector(“.box”).innerHTML += “”

5.2.1、v-html和v-text

v-text : 渲染的数据中包含html标签,标签不会被解析渲染,标签会原样显示在页面上

v-html:渲染的数据中包含html标签,标签被解析渲染

v-text和v-html,他们会将标签中默认的数据全部覆盖(替换)

{{ }} 将数据插入插值表达式所在的位置上

<body>
    <div id="app">
        
        <p>姓名:{{ name }}p>
        
        
        <p v-text="name2">这个数据您看不到p>
        
        <p v-html="name2">p>
    div>
    <script src="./js/vue3.js">script>
    <script>
        let { createApp } = Vue;
        // 创建app对象
        const app = createApp({
            data(){
                return{
                    name:"灭绝小甜甜",
                    name2:"灭绝小甜甜"
                }
            }
        });
        // 让app与页面view进行绑定
        app.mount("#app");
    script>
body>

5.2.2、v-pre

元素内具有 v-pre,所有 Vue 模板语法都会被保留并按原样渲染。最常见的用例就是显示原始双大括号标签及内容。

<body>
    <pre>
        好好学习
        天天向上
    pre>
    <div id="app">
        <p v-pre>vue中的插值表达式格式:{{ name }}p>
    div>
    <script src="./js/vue3.js">script>
    <script>
        let { createApp } = Vue;
        // 创建app对象
        const app = createApp({

        });
        // 让app与页面view进行绑定
        app.mount("#app");
    script>
body>

5.3、属性绑定

5.3.1、v-bind基本使用

v-bind:用于将标签上的属性名或属性值转成vue中的动态的数据

v-bind:属性名=“变量名 | 表达式 | 调用语句”

v-bind:[属性名]=“变量名 | 表达式 | 调用语句”

v-bind可以简化成:

<body>
    <div id="app">
        
         <div v-bind:name="value">123213div>
         <div v-bind:name="1+1">123213div>
         <div v-bind:name="msg()">123213div>
         
         <div v-bind:[attrname]="attrValue">123213div>
         <hr>
         <img v-bind:src="img1" alt="" width="100">
         <img v-bind:src="img2" alt="" width="100">
         
         <img :src="img3" alt="" width="100">
    div>
    <script src="./js/vue3.js">script>
    <script>
        let { createApp } = Vue;
        // 创建app对象
        const app = createApp({
            data(){
                return {
                    value:"李四",
                    attrname:"age",
                    attrValue:23,
                    img1:"https://img13.360buyimg.com/babel/s1180x940_jfs/t20260529/111640/23/37858/94517/6475c864F5396934a/0bd76f0443ad5fca.png.avif",
                    img2:"https://img1.baidu.com/it/u=1960110688,1786190632&fm=253&fmt=auto&app=138&f=JPEG?w=500&h=281",
                    img3:'https://img2.baidu.com/it/u=1906732828,3160455141&fm=253&fmt=auto&app=138&f=JPEG?w=500&h=666'
                }
            },
            methods:{
                msg(){
                    return "hello";
                }
            }
        });
        // 让app与页面view进行绑定
        app.mount("#app");
    script>
body>

5.3.2、特殊使用

如果一个对象中的所有数据都需要绑定的某个标签的属性中,这是可以进行v-bind的简化属性

v-bind='对象变量名名'

<body>
    <div id="app">
        
        <img :src="imgObj.src" v-bind:alt="imgObj.alt" :width="imgObj.width">
        
        <img v-bind="imgObj">
    div>
    <script src="./js/vue3.js">script>
    <script>
        let { createApp } = Vue;
        // 创建app对象
        const app = createApp({
            data(){
                return {
                    imgObj:{
                        width:"100",
                        src: 'https://img2.baidu.com/it/u=1906732828,3160455141&fm=253&fmt=auto&app=138&f=JPEG?w=500&h=666',
                        alt:"图片"
                    }
                }
            }
        });
        // 让app与页面view进行绑定
        app.mount("#app");
    script>
body>

5.3.3、练习

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-c4k3xN50-1686296270819)(课堂笔记.assets/image-20230605163025697.png)]

<body>
    <div id="app">
        <input type="text" placeholder="请输入验证码">
        <button :disabled="disabled" v-on:click="changeTime">{{btnTitle}}button>
    div>
    <script src="./js/vue3.js">script>
    <script>
        let { createApp } = Vue;
        // 创建app对象
        const app = createApp({
            data() {
                return {
                    disabled: false,
                    btnTitle: "获取验证码",
                }
            },
            methods: {
                changeTime() {
                    // 在vue的其他配置项中,如果需要使用别的配置项中的数据,必须通过this来获取
                    this.disabled = true;
                    let t = 60;
                    let timerID = setInterval(() => {
                        console.log(this);
                        this.btnTitle = t;
                        if (t <= 0) {
                            clearInterval(timerID);
                            this.disabled = false;
                            this.btnTitle = "获取验证码";
                        }
                        t--;
                    }, 1000);

                }
            }
        });
        // 让app与页面view进行绑定
        app.mount("#app");
    script>
body>

5.4、事件绑定

回顾事件(event):页面上发生的具体某个动作,基于这个动作需要给出相应的处理函数。

事件源target:事件具体在哪个位置(物体、标签)上发生

事件对象event:在事件源上发生具体的某个动作,然后将与动作有关系的数据封装成一个对象,传递给事件处理函数

事件处理函数:事件发生之后,对应的一段js代码(函数)

事件类型:在事件源上发生的具体是什么事件(click、mouseover、scroll、resize等)

绑定事件:

  • 在标签上直接绑定

    <button onclick="" >
        按钮
    button>
    
    
  • 通过dom对象绑定事件

    <button >按钮button>
    <script>
       let btn = document.querySelector("button")
       btn.onClick = function(){}
    script>
    
    
  • 使用事件的绑定函数addEventListener

    <button >按钮button>
    <script>
       let btn = document.querySelector("button")
       btn.addEventListener("事件名",function(){})
    script>
    
    

复习:什么是事件委派,事件委派解决什么问题?

5.4.1、vue中的事件绑定

在vue中绑定使用v-on指令。可以简化为@

重点:掌握事件绑定时传递参数与事件对象

<body>
    <div id="app">
        
        <button v-on:click="show">按钮button>
        
        <button v-on:click="show2(11,22,33)">按钮button>
        
        <button v-on:click="show3">按钮button>
        <input type="text" v-on:keyup="demo">
        
        <div class="box" v-on:mouseover="fn(11,22,$event)">我是divdiv>
    div>
    <script src="./js/vue3.js">script>
    <script>
        let { createApp } = Vue;
        // 创建app对象
        const app = createApp({
            methods:{
                show:function(){
                    console.log("show");
                },
                show2(a,b,c){
                    console.log("show2:a,b,c",a,b,c);
                },
                show3(event) {
                    console.log(event);
                },
                demo(e){
                    console.log(e);
                },
                fn(a,b,c){
                    console.log("fn a,b:",a,b);
                    console.log(c);
                }
            }
        });
        // 让app与页面view进行绑定
        app.mount("#app");
    script>
body>

5.4.2、事件修饰符

在处理事件时调用 event.preventDefault()event.stopPropagation() 是很常见的。尽管我们可以直接在方法内调用,但如果方法能更专注于数据逻辑而不用去处理 DOM 事件的细节会更好。

为解决这一问题,Vue 为 v-on 提供了事件修饰符。修饰符是用 . 表示的指令后缀,包含以下这些:

  • .stop : 阻止事件冒泡
  • .prevent :阻止事件默认行为
  • .self : 事件只能通过当前标签触发才执行
  • .capture : 捕获事件
  • .once : 事件只执行一次
  • .passive
DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Documenttitle>
    <style>
        .box{
            width: 300px;
            height: 300px;
            background-color: deeppink;
        }
        .box2{
           width: 200px;
            height: 200px;
            background-color: #0a0;
        }
        .box3{
           width: 100px;
            height: 100px;
            background-color: #0af;
        }
    style>
head>

<body>
    <div id="app">
        <a href="https://www.baidu.com" @click.prevent>baidua>
        <div class="box" @click="box1">
            
            <div class="box2" @click.stop.self="box2">
                
                <div class="box3" @click.top="box3">div>
            div>
        div>
    div>
    <script src="./js/vue3.js">script>
    <script>
        let { createApp } = Vue;
        // 创建app对象
        const app = createApp({
            methods:{
               box3(e){
                console.log("box3");
                // e.stopPropagation(); 
               },
               box2(){
                console.log("box2");
               },
               box1(){
                console.log("box1");
               }
            }
        });
        // 让app与页面view进行绑定
        app.mount("#app");
    script>
body>

html>

5.4.3、按键修饰符

vue3中测试中发现,键盘码失效了

在监听键盘事件时,我们经常需要检查特定的按键。Vue 允许在 v-on@ 监听按键事件时添加按键修饰符。

Vue 为一些常用的按键提供了别名:

  • .enter
  • .tab
  • .delete (捕获“Delete”和“Backspace”两个按键)
  • .esc
  • .space
  • .up
  • .down
  • .left
  • .right
<body>
    <div id="app">
        <input type="text" v-on:keyup.enter="demo">
        <input type="text" v-on:keyup.ctrl.enter="demo">
    div>
    <script src="./js/vue3.js">script>
    <script>
        let { createApp } = Vue;
        // 创建app对象
        const app = createApp({
            methods:{
                demo(e){
                    console.log(e);
                }
            }
        });
        // 让app与页面view进行绑定
        app.mount("#app");
    script>
body>

后期还需要研究表单相关的修饰符。

5.5、v-if指令

5.5.1、v-if基本使用

vue中也提供类似于if、if-else、if else if else 等这样的页面上进行判断的结构

DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Documenttitle>
    <style>
        .box{
            width: 100px;
            height: 100px;
            background-color: #0a0;
        }
        .box2{
            width: 100px;
            height: 100px;
            background-color: #fa0;
        }
    style>
head>

<body>
    <div id="app">
        <p>flag:{{flag}}p>
        <button @click="changeFlag">切换button>
        <div class="box" v-if="flag">div>
        <div class="box2" v-else="flag">div>
    div>
    <script src="./js/vue3.js">script>
    <script>
        let { createApp } = Vue;
        // 创建app对象
        const app = createApp({
            data(){
                return {
                    flag:false
                }
            },
            methods:{
                changeFlag(){
                    this.flag = !this.flag; 	
                }
            }
        });
        // 让app与页面view进行绑定
        app.mount("#app");
    script>
body>

html>

5.5.2、选项卡练习

DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Documenttitle>
    <style>
        .item1{
            width: 200px;
            height: 100px;
            background-color: #fa0;
        }
        .item2{
            width: 200px;
            height: 100px;
            background-color: deeppink;
        }
        .item3{
            width: 200px;
            height: 100px;
            background-color: #0af;
        }
    style>
head>

<body>
    <div id="app">
        <div class="btns">
            <button @click="changeDiv('新闻')">新闻button>
            <button  @click="changeDiv('八卦')">八卦button>
            <button  @click="changeDiv('体育')">体育button>
        div>
        <div class="cotent-list">
            <div class="item1" v-if="title=='新闻'">新闻列表div>
            <div class="item2" v-if="title=='八卦'">八卦内容div>
            <div class="item3" v-if="title=='体育'">体育竞技div>
        div>
    div>
    <script src="./js/vue3.js">script>
    <script>
        let { createApp } = Vue;
        // 创建app对象
        const app = createApp({
            data(){
                return {
                    title:"新闻"
                }
            },
            methods:{
                changeDiv(val){
                    console.log(val);
                    this.title = val;
                }
            }
        });
        // 让app与页面view进行绑定
        app.mount("#app");
    script>
body>

html>

5.6、v-show指令

v-show:可以控制某个标签是否显示,默认使用的display:none样式来控制。

v-if:他是通过控制dom,来完成标签是否渲染在页面上。

在安全方向:v-if比v-show安全。

性能方式:v-if操作dom,性能较差。

拓展:重绘和重排

作业:实现表格隔行变色,鼠标悬停在某行上高亮。:nth-child(2n) :nth-child(2n-1) :hover

<body>
    <div id="app">
        
        <button @click="flag=!flag">切换button> 
        <p>flag:{{flag}}p>
        <h3 v-show="flag">flag:{{flag}}h3>
        <h3 v-if="flag">flag:{{flag}}h3>
    div>
    div>
    <script src="./js/vue3.js">script>
    <script>
        // 解构出createApp方法
        let { createApp } = Vue;
        // 创建app的实例
        const app = createApp({
            data(){
                return{
                    flag:false
                }
            }
        });
        app.mount("#app");
    script>
body>

v-if vs v-show

v-if 是“真实的”按条件渲染,因为它确保了在切换时,条件区块内的事件监听器和子组件都会被销毁与重建。

v-if 也是惰性的:如果在初次渲染时条件值为 false,则不会做任何事。条件区块只有当条件首次变为 true 时才被渲染。

相比之下,v-show 简单许多,元素无论初始条件如何,始终会被渲染,只有 CSS display 属性会被切换。

总的来说,v-if 有更高的切换开销,而 v-show 有更高的初始渲染开销。因此,如果需要频繁切换,则使用 v-show 较好;如果在运行时绑定条件很少改变,则 v-if 会更合适。

5.7、v-for列表渲染

我们可以使用 v-for 指令基于一个数组(对象、字符串、数字)来渲染一个列表。v-for 指令的值需要使用 item in items 形式的特殊语法,其中 items 是源数据的数组,而 item 是迭代项的别名

<body>
    <div id="app">
        
        
        <h3>v-for遍历数组h3>
        
        <p v-for="item in arr">{{item}}p>
        
        <p v-for="(item , index) in arr">{{item}}-----{{index}}p>
        <h3>商品数据:h3>
        <p v-for="item in goods">
            名称:{{item.name}}
            单价:{{item.price}}
            数量:{{item.count}}
            小计:{{item.price * item.count}}
        p>
        <hr>
        <h3>遍历对象h3>
        
        <p v-for="(value , key) in student">{{key}}::::{{value}}p>
        <h3>遍历字符串h3>
        <span v-for="item in str">{{ item }}span>
        <br>
        
        <p v-for="(item,index) in str">{{ item }}====={{index}}p>
        <br>
        <h3>提供普通的循环,从1开始到指定的数字结束h3>
        <p v-for="x in 10">{{x}}p>
        <br><br><br><br><br><br><br><br><br><br>
    div>
    div>
    <script src="./js/vue3.js">script>
    <script>
        // 解构出createApp方法
        let { createApp } = Vue;
        // 创建app的实例
        const app = createApp({
            data() {
                return {
                    arr: [11, 22, 33, 44, 55],
                    goods: [
                        { id: 1, name: "西瓜", price: 3.8, count: 10 },
                        { id: 2, name: "苹果", price: 5.8, count: 4 },
                        { id: 3, name: "桃子", price: 1.8, count: 7 },
                        { id: 4, name: "香蕉", price: 2.8, count: 9 },
                    ],
                    student:{
                        name:"小明",
                        age:18,
                        sex:"不详",
                        score:99,
                        address:"杭州"
                    },
                    str:"别睡觉啦~~,要下课了~~~"
                }
            }
        });
        app.mount("#app");
    script>
body>

5.8、v-for中的key属性

v-for指令中,建议添加key属性,用于进行唯一标识(给vue的底层进行虚拟dom对比的时候使用)

<body>
    <div id="app">
        
        <h3>商品数据:h3>
        <p v-for="(item,index) in goods" :key="index">
            名称:{{item.name}} 
            单价:{{item.price}}
            数量:{{item.count}}
            小计:{{item.price * item.count}}
        p>
        
        <br><br><br><br><br><br><br><br><br><br>
    div>
    div>
    <script src="./js/vue3.js">script>
    <script>
        // 解构出createApp方法
        let { createApp } = Vue;
        // 创建app的实例
        const app = createApp({
            data() {
                return {
                    goods: [
                        { id: 1, name: "西瓜", price: 3.8, count: 10 },
                        { id: 2, name: "苹果", price: 5.8, count: 4 },
                        { id: 3, name: "桃子", price: 1.8, count: 7 },
                        { id: 4, name: "香蕉", price: 2.8, count: 9 },
                    ],
                }
            }
        });
        app.mount("#app");
    script>
body>

5.9、表单v-model指令

v-model 还可以用于各种不同类型的输入,