Vue基础

 一、Mustache语法(模板语法)

语法格式:{{}}

我们可以像下面这样来使用,并且数据是响应式的

image-20210427152053393

示例代码:

<head>
    <meta charset="UTF-8">
    <title>Mustache语法</title>
    <script src="../static/vue.js"></script>
</head>
<body>
<div id="app">
    <h2>{{ message }}</h2>
    <h2>{{ message }}, xxx</h2>

    <!--mustache语法中,不仅仅可以直接写变量,也可以写简单的表达式-->
    <h2>{{ firstName + lastName}}</h2>
    <h2>{{ firstName + ' ' + lastName}}</h2>
    <h2>{{ firstName }} {{ lastName }}</h2>
    <h2>{{ counter * 2}}</h2>
    <h2>三目运算符:{{ 10>20?'是':'否' }}</h2>
    <h2>字符串 {{ link1 }}</h2>
</div>
<script>
    const app = new Vue({
        el: '#app',
        data: {
            message: 'hello world',
            firstName: 'chen',
            lastName: 'alex',
            counter: 100,
            link1: '<a href="https://www.baidu.com">百度一下 你就知道</a>'
        },
    })
</script>
</body>
 

二、指令

文本指令

指令释义
v-once 元素和组件(组件后面才会学习)只渲染一次,不会随着数据的改变而改变
v-html 让HTML渲染成页面
v-text 标签内容显示js变量对应的值
v-show 放1个布尔值:为真 标签就显示;为假 标签就不显示
v-if 放1个布尔值:为真 标签就显示;为假 标签就不显示

v-show与 v-if的区别:

  • v-show:标签还在,只是不显示了(display: none)
  • v-if:直接操作DOM,删除/插入 标签

v-once :只渲染一次,不会随数据的改变而改变

  • 在某些情况下,我们可能不希望界面随意的跟随改变
  • 这个时候,我们就可以使用一个Vue的指令:v-once
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>v-once指令</title>
  <script src="../js/vue.js"></script>
</head>
<body>

<div id="app">
    <h2>{{message}}</h2>
    <h2 v-once>{{message}}</h2>
</div>
<script>
    const app = new Vue({
        el: '#app',
        data: {
            message: 'hello world'
        }
    })
</script>

</body>
</html>
 

v-html:让HTML渲染成页面

某些情况下,我们从服务器请求到的数据本身就是一个HTML代码

  • 如果我们直接通过{{}}来输出,会将HTML代码也一起输出。
  • 但是我们可能希望的是按照HTML格式进行解析,并且显示对应的内容。

可以使用v-html指令

  • 该指令后面往往会跟上一个string类型
  • 会将string的html解析出来并且进行渲染
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>

<div id="app">
    <h2>{{url}}</h2>
    <h2 v-html="url"></h2>
</div>

<script src="../js/vue.js"></script>
<script>
    const app = new Vue({
        el: '#app',
        data: {
            message: '你好啊',
            url: '<a href="http://www.baidu.com">百度一下</a>'
        }
    })
</script>

</body>
</html>
 

image-20210427160724040

v-text:标签内容显示js变量对应的值

  • v-text作用和Mustache比较相似:都是用于将数据显示在界面中
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.6.1/jquery.js"></script>
    <script src="js/vue.js"></script>
</head>
<body>
<div id="app">
    <p>{{message}},alex!</p>
    <p v-text="message">再见</p>
</div>
<script>
    var vm=new Vue({
        el:'#app', 
        data:{
            message:'hello',
        },
    })
</script>
</body>
</html>

 

 

v-pre

  • v-pre用于跳过这个元素和它子元素的编译过程,用于显示原本的Mustache语法。
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.6.1/jquery.js"></script>
    <script src="js/vue.js"></script>
</head>
<body>
<div id="app">
    <p>{{message}},alex!</p>
    <p v-pre>{{message}}</p>
</div>
<script>
    var vm=new Vue({
        el:'#app',
        data:{
            message:'hello',
        },
    })
</script>
</body>
</html>

 

 

v-cloak

  • 在某些情况下,我们浏览器可能会直接显然出未编译的Mustache标签。
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Title</title>
  <style>
    [v-cloak] {
      display: none;
    }
  </style>
</head>
<body>

<div id="app" v-cloak>
  <h2>{{message}}</h2>
</div>

<script src="../js/vue.js"></script>
<script>
  // 在vue解析之前, div中有一个属性v-cloak
  // 在vue解析之后, div中没有一个属性v-cloak
  setTimeout(function () {
    const app = new Vue({
      el: '#app',
      data: {
        message: '你好啊'
      }
    })
  }, 1000)
</script>

</body>
</html>
 

v-show:显示/隐藏内容

# v-on:事件名='函数'
 可以简写成:
    @事件名='函数'

# 函数必须写在methods的配置项中
    methods:{
            'handleClick':function (){
                console.log(this)  // this 就是当前vue实例,就是vm实例
                this.show=!this.show
            },  
        }
    -点击button就会触发绑定函数(handleClick)的执行
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>v-show</title>
    <script src="https://cdn.bootcdn.net/ajax/libs/vue/2.6.12/vue.min.js"></script>
</head>
<body>

<div id="box">
    <h3>案例:控件通过按钮来控制显示和小事</h3>
    <button @click="handleClick()">点我</button>
    <br>
    <div v-show="isShow">isShow</div>
</div>

</body>
<script>
    let vm = new Vue({
        el: '#box',
        data: {
            isShow: true,
        },
    // 函数必须写在methods配置项中 methods: {     handleClick(){ this.isShow = !this.isShow // this指的是当前的vue对象 }, } }) </script> </html>

img

三、动态绑定属性

指令释义
v-bind 直接写js的变量或语法(不推荐)
: 直接写js的变量或语法(推荐)

v -bind 基本使用

前面我们学习的指令主要作用是将值插入到我们模板的内容当中。

但是,除了内容需要动态来决定外,某些属性我们也希望动态来绑定。

  • 比如动态绑定a元素的href属性
  • 比如动态绑定img元素的src属性

这个时候,我们可以使用v-bind指令:

  • 作用:动态绑定属性
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Title</title>
</head>
<body>

<div id="app">
  <!-- 错误的做法: 这里不可以使用mustache语法-->
  <!--<img src="{{imgURL}}" alt="">-->
  <!-- 正确的做法: 使用v-bind指令 -->
  <img v-bind:src="imgURL" alt="">
  <a v-bind:href="aHref">百度一下</a>
  <!--<h2>{{}}</h2>-->

  <!--语法糖的写法-->
  <img :src="imgURL" alt="">
  <a :href="aHref">百度一下</a>
</div>

<script src="../js/vue.js"></script>
<script>
  const app = new Vue({
    el: '#app',
    data: {
      message: '你好啊',
      imgURL: 'https://img11.360buyimg.com/mobilecms/s350x250_jfs/t1/20559/1/1424/73138/5c125595E3cbaa3c8/74fc2f84e53a9c23.jpg!q90!cc_350x250.webp',
      aHref: 'http://www.baidu.com'
    }
  })
</script>

</body>
</html>
 

image-20210427172154301

V -bind 魔法糖

v-bind有一个对应的语法糖,也就是简写方式

简写方式::

image-20210427173150436

数据的绑定

语法

:属性名=js变量/js语法

  • :class=’js变量、字符串、js数组’

class:三目运算符、数组、对象{red: true}

  • :style=’js变量、字符串、js数组’

style:三目运算符、数组[{backgreound: ‘red’},]、对象{background: ‘red’}

控制标签class类名

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script src="js/vue.js"></script>
    <style>
    .box1{
        color: red;
        border: 1px solid #000;
    }
    .box2{
        background-color: orange;
        font-size: 32px;
    }
    </style>
</head>
<body>
    <div id="box">
        <!--- 添加class类名,值是一个对象
        {
         class1:布尔值变量1,
         class2:布尔值变量2,
        }
         -->
        <p :class="{box1:myclass1}">一个段落</p>
        <p @click="myclass3=!myclass3" :class="{box1:myclass2,box2:myclass3}">一个段落</p>
    </div>
    <script>
        let vm1=new Vue({
            el:"#box",
            data:{
                myclass1:false, // 布尔值变量如果是false,则不会添加对象的属性名作为样式
                myclass2:true,  // 布尔值变量如果是true,则不会添加对象的属性名作为样式
                myclass3:false,
            },
        })
    </script>

    <!-- 上面的代码可以:class的值保存到data里面的一个变量,然后使用该变量作为:class的值 -->
    <style>
    .box4{
        background-color: red;
    }
    .box5{
        color: green;
    }
    </style>
    <div id="app">
        <button @click="mycls.box4=!mycls.box4">改变背景</button>
        <button @click="mycls.box5=!mycls.box5">改变字体颜色</button>
        <p :class="mycls">第二个段落</p>
    </div>
    <script>
        let vm2 = new Vue({
            el:"#app",
            data:{
                mycls:{
                    box4:false,
                    box5:true
                },
            }
        })
    </script>

    <!-- 批量给元素增加多个class样式类 -->
    <style>
    .box6{
        background-color: red;
    }
    .box7{
        color: green;
    }
    .box8{
        border: 1px solid yellow;
    }
    </style>
    <div id="app2">
            <p :class="[mycls1,mycls2]">第三个段落</p>
    </div>
    <script>
        let vm3 = new Vue({
            el:"#app2",
            data:{
                mycls1:{
                    box6:true,
                    box7:true,
                },
                mycls2:{
                    box8:true,
                }
            }
        })
    </script>
</body>
</html>
 

代码执行效果:

img

小结:

1. 给元素绑定class类名,最常用的就是第二种。
    vue对象的data数据:
        data:{
          myObj:{
            complete:true,
            uncomplete:false,
          }
        }

		html元素:    
    		<div class="box" :class="myObj">2222</div>
    最终浏览器效果:
		    <div class="box complete">2222</div>
 

控制标签style样式

# 格式1:值是json对象,对象写在元素的:style属性中
    标签元素:
        <div :style="{color: activeColor, fontSize: fontSize + 'px' }"></div>
    data数据如下:
        data: {
            activeColor: 'red',
            fontSize: 30
        }
    
# 格式2:值是对象变量名,对象在data中进行声明
    标签元素:
        <div v-bind:style="styleObject"></div>
    data数据如下:
        data: {
            styleObject: {
                color: 'red',
                fontSize: '13px'
            }
        }

# 格式3:值是数组
    标签元素:
        <div v-bind:style="[style1, style2]"></div>
    data数据如下:
        data: {
            style1:{
                color:"red"
            },
            style2:{
                background:"yellow",
                fontSize: "21px"
            }
        }
    }

示例-vue版本选项卡

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <style>
        #card {
            width: 500px;
            height: 350px;
        }

        .title {
            height: 50px;
        }

        .title span {
            width: 100px;
            height: 50px;
            background-color: #ccc;
            display: inline-block;
            line-height: 50px; /* 设置行和当前元素的高度相等,就可以让文本内容上下居中 */
            text-align: center;
        }

        .content .list {
            width: 500px;
            height: 300px;
            background-color: yellow;
            display: none;
        }

        .content .active {
            display: block;
        }

        .title .current {
            background-color: yellow;
        }
    </style>
    <script src="js/vue.js"></script>
</head>
<body>

<div id="card">
    <div class="title">
        <span @click="num=0" :class="num==0 ? 'current' : ''">国内新闻</span>
        <span @click="num=1" :class="num==1 ? 'current' : ''">国际新闻</span>
        <span @click="num=2" :class="num==2 ? 'current' : ''">银河新闻</span>
        <!--<span>{{num}}</span>-->
    </div>
    <div class="content">
        <div class="list" :class="num==0 ? 'active' : ''">国内新闻列表</div>
        <div class="list" :class="num==1 ? 'active' : ''">国际新闻列表</div>
        <div class="list" :class="num==2 ? 'active' : ''">银河新闻列表</div>
    </div>
</div>
<script>
    // 需求: 当用户点击标题栏的按钮[span]时,显示对应索引下标的内容块[.list]
    // 思路:利用标题栏每一个标题和内容对应的序号来记录和控制它们的显示和隐藏
    // 代码实现:
    var card = new Vue({
        el: "#card",
        data: {
            num: 0,
        },
    });
</script>

</body>
</html>

 

展示图:

测试

四、条件指令

v-if:显示/隐藏内容

标签元素:
    <!-- vue对象最终会把条件的结果变成布尔值 -->
        <h1 v-if="ok">Yes</h1>
data数据:
    data:{
        ok:false    // true则是显示,false是隐藏
    }
 

代码示例

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>v-if</title>
    <script src="https://cdn.bootcdn.net/ajax/libs/vue/2.6.12/vue.min.js"></script>
</head>
<body>

<div id="box">
    <h3>案例:控件通过按钮来控制显示和消失</h3>
    <button @click="handleClick()">点我</button>
    <br>
    <div v-if="isCreated">isCreated</div>
</div>

</body>
<script>
    let vm = new Vue({
        el: '#box',
        data: {
            isCreated:true
        },
        methods: {
            handleClick(){
              this.isCreated = !this.isCreated    // this指的是当前的vue对象
            },
        }
    })
</script>
</html>
 
 

img

v-if与v-show的异同:

  • v-show 、v-if 用于控制标签是否展示,true 表示展示,false 表示不展示
  • 最好是用变量来表示,便于后面控制
  • 俩者不同的是,v-show 为 false 时,会给元素添加 display: none;而 v-if 为 false 时,会操作 DOM 直接将元素标签删除。

 

v-else

v-else指令来表示 v-if 的“else 块”,v-else 元素必须紧跟在带 v-if 或者 v-else-if 的元素的后面,否则它将不会被识别。

标签元素:
    <h1 v-if="ok">Yes</h1>
    <h1 v-else>No</h1>
data数据:
    data:{
        ok:false    // true则是显示,false是隐藏
    }
 

登录退出功能展示示例:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script src="https://cdn.bootcdn.net/ajax/libs/vue/2.6.11/vue.min.js"></script>
</head>
<body>

<div id="card">
    <p v-if="is_login">欢迎回到路飞学城! <a href="#" @click="is_login=!is_login">退出</a></p>
    <p v-else><a href="#" @click="is_login=!is_login">登录</a></p>
</div>
<script>
    var vm = new Vue({
        el: "#card",
        data: {
            is_login: false,  // 登录状态
        },
    });
</script>

</body>
</html>
 

效果测试图:

测试

v-else-if

可以出现多个v-else-if语句,但是v-else-if之前必须有一个v-if开头。后面可以跟着v-else,也可以没有。

标签元素:
    <h1 v-if="num==1">num的值为1</h1>
    <h1 v-else-if="num==2">num的值为2</h1>
    <h1 v-else>num的值是{{num}}</h1>
data数据:
    data:{
        num:2
    }

展示今天是星期几代码示例:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script src="https://cdn.bootcdn.net/ajax/libs/vue/2.6.11/vue.min.js"></script>
</head>
<body>

<div id="card">
    <li v-if="num==1">星期一</li>
    <li v-else-if="num==2">星期二</li>
    <li v-else-if="num==3">星期三</li>
    <li v-else-if="num==4">星期四</li>
    <li v-else-if="num==5">星期五</li>
    <li v-else-if="num==6">星期六</li>
    <li v-else>星期天</li>
</div>
<script>
    var vm = new Vue({
        el: "#card",
        data: {
            num: new Date().getDay(),
        },
    });
</script>
</body>
</html>

条件渲染案例

我们来做一个简单的小案例:

  • 用户再登录时,可以切换使用用户账号登录还是邮箱地址登录。

image-20210428173439129

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Title</title>
</head>
<body>

<div id="app">
  <span v-if="isUser">
    <label for="username">用户账号</label>
    <input type="text" id="username" placeholder="用户账号">
  </span>
  <span v-else>
    <label for="email">用户邮箱</label>
    <input type="text" id="email" placeholder="用户邮箱">
  </span>
  <button @click="isUser = !isUser">切换类型</button>
</div>

<script src="../js/vue.js"></script>
<script>
  const app = new Vue({
    el: '#app',
    data: {
      isUser: true
    }
  })
</script>

</body>
</html>
 

测试

小问题:

如果我们在有输入内容的情况下,切换了类型,我们会发现文字依然显示之前的输入的内容。

但是按道理讲,我们应该切换到另外一个input元素中了。

问题解答:

这是因为Vue在进行DOM渲染时,出于性能考虑,会尽可能的复用已经存在的元素,而不是重新创建新的元素。

在上面的案例中,Vue内部会发现原来的input元素不再使用,直接作为else中的input来使用了。

解决方案:

  • 如果我们不希望Vue出现类似重复利用的问题,可以给对应的input添加key
  • 并且我们需要保证Key的不同
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Title</title>
</head>
<body>

<div id="app">
  <span v-if="isUser">
    <label for="username">用户账号</label>
    <input type="text" id="username" placeholder="用户账号" key="username">
  </span>
  <span v-else>
    <label for="email">用户邮箱</label>
    <input type="text" id="email" placeholder="用户邮箱" key="email">
  </span>
  <button @click="isUser = !isUser">切换类型</button>
</div>

<script src="../js/vue.js"></script>
<script>
  const app = new Vue({
    el: '#app',
    data: {
      isUser: true
    }
  })
</script>

</body>
</html>
 

测试

五、计算属性

基本使用

我们知道,在模板中可以直接通过插值语法显示一些data中的数据。

但是在某些情况,我们可能需要对数据进行一些转化后再显示,或者需要将多个数据结合起来进行显示

  • 比如我们有firstName和lastName两个变量,我们需要显示完整的名称。
  • 但是如果多个地方都需要显示完整的名称,我们就需要写多个{{firstName}} {{lastName}}

我们可以将上面的代码换成计算属性:

  • OK,我们发现计算属性是写在实例的computed选项中的。

image-20210427220440907

代码:

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Title</title>
</head>
<body>

<div id="app">
  <h2>{{firstName + ' ' + lastName}}</h2>
  <h2>{{firstName}} {{lastName}}</h2>

  <h2>{{getFullName()}}</h2>

  <h2>{{fullName}}</h2>
</div>

<script src="../js/vue.js"></script>
<script>
  const app = new Vue({
    el: '#app',
    data: {
      firstName: 'Lebron',
      lastName: 'James'
    },
    // computed: 计算属性()
    computed: {
      fullName: function () {
        return this.firstName + ' ' + this.lastName
      }
    },
    methods: {
      getFullName() {
        return this.firstName + ' ' + this.lastName
      }
    }
  })
</script>

</body>
</html>
 

计算属性的复杂操作:

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Title</title>
</head>
<body>

<div id="app">
  <h2>总价格: {{totalPrice}}</h2>
  <h2>总价格: {{totalPrice}}</h2>
  <h2>总价格: {{totalPrice}}</h2>
  <h2>总价格: {{totalPrice}}</h2>

  <h2>总价格: {{getTotalPrice()}}</h2>
  <h2>总价格: {{getTotalPrice()}}</h2>
  <h2>总价格: {{getTotalPrice()}}</h2>
  <h2>总价格: {{getTotalPrice()}}</h2>
</div>

<script src="../js/vue.js"></script>
<script>
  const app = new Vue({
    el: '#app',
    data: {
      books: [
        {id: 110, name: 'Unix编程艺术', price: 119},
        {id: 111, name: '代码大全', price: 105},
        {id: 112, name: '深入理解计算机原理', price: 98},
        {id: 113, name: '现代操作系统', price: 87},
      ]
    },
    methods: {
      getTotalPrice: function () {
        let result = 0
        for (let i=0; i < this.books.length; i++) {
          result += this.books[i].price
        }
        return result
      }
    },
    computed: {
      totalPrice: function () {
        let result = 0
        for (let i=0; i < this.books.length; i++) {
          result += this.books[i].price
        }
        return result

        // for (let i in this.books) {
        //   this.books[i]
        // }
        //
        // for (let book of this.books) {
        //
        // }
      }
    }
  })
</script>

</body>
</html>
 

小练习:两个数值相加,计算出结果

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script src="https://cdn.bootcdn.net/ajax/libs/vue/2.6.11/vue.min.js"></script>
</head>
<body>
<div id="app">
    <input type="text" v-model="num1">+
    <input type="text" v-model="num2">=
    <span>{{total}}</span>
</div>

<script>
    let vm = new Vue({
        el: '#app',  // vm的模板对象
        data: {      // vm的数据
            num1: 0, 
            num2: 0,
        },
        methods: {},  // vm的方法
        computed: {   // 计算属性,相当于创建一个新的变量保存数据计算的结果
            total() {
                // parseFloat 把数据转换成浮点数
                // parseInt   把数据转换成整数
                return parseFloat(this.num1) + parseFloat(this.num2);
            }
        }
    });
</script>
</body>
</html>
 

计算属性的setter和getter

计算属性默认只有 getter,不过在需要时你也可以提供一个 setter:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>

<div id="app">
    <h2>{{fullName}}</h2>
</div>

<script src="../js/vue.js"></script>
<script>
    const app = new Vue({
        el: '#app',
        data: {
            firstName: 'Kobe',
            lastName: 'Bryant'
        },
        computed: {
            // fullName: function () {
            //   return this.firstName + ' ' + this.lastName
            // }
            // name: 'coderwhy'
            // 计算属性一般是没有set方法, 只读属性.
            fullName: {
              
                get: function () {
                    return this.firstName + ' ' + this.lastName
                },

                set: function (newValue) {
                    // console.log('-----', newValue);
                    const names = newValue.split(' ');
                    this.firstName = names[0];
                    this.lastName = names[1];
                },

            },

            // fullName: function () {
            //   return this.firstName + ' ' + this.lastName
            // }
        }
    })
</script>

</body>
</html>
 

在某些情况下,你也可以提供一个setter方法(不常用)

image-20210427231254677

计算属性的缓存

我们可能会考虑这样的一个问题:

  • methods和computed看起来都可以实现我们的功能,
  • 那么为什么还要多一个计算属性这个东西呢?

原因:计算属性会进行缓存,如果多次使用时,计算属性只会调用一次。

image-20210427232318452

image-20210427232329942

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Title</title>
</head>
<body>

<div id="app">
  <!--1.直接拼接: 语法过于繁琐-->
  <h2>{{firstName}} {{lastName}}</h2>

  <!--2.通过定义methods-->
  <!--<h2>{{getFullName()}}</h2>-->
  <!--<h2>{{getFullName()}}</h2>-->
  <!--<h2>{{getFullName()}}</h2>-->
  <!--<h2>{{getFullName()}}</h2>-->

  <!--3.通过computed-->
  <h2>{{fullName}}</h2>
  <h2>{{fullName}}</h2>
  <h2>{{fullName}}</h2>
  <h2>{{fullName}}</h2>
</div>

<script src="../js/vue.js"></script>
<script>
  // angular -> google
  // TypeScript(microsoft) -> ts(类型检测)
  // flow(facebook) ->
  const app = new Vue({
    el: '#app',
    data: {
      firstName: 'Kobe',
      lastName: 'Bryant'
    },
    methods: {
      getFullName: function () {
        console.log('getFullName');
        return this.firstName + ' ' + this.lastName
      }
    },
    computed: {
      fullName: function () {
        console.log('fullName');
        return this.firstName + ' ' + this.lastName
      }
    }
  })

</script>

</body>
</html>
 

六、事件监听

V-on介绍

在前端开发中,我们需要经常和用于交互。
这个时候,我们就必须监听用户发生的时间,比如点击、拖拽、键盘事件等等

在Vue中如何监听事件呢?使用v-on指令

指令释义
v-on 触发事件(不推荐)
@ 触发事件(推荐
@[event] 触发event事件(可以是其他任意事件

v-on:click 可以缩写成@click

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>事件指令</title>
    <script src="https://cdn.bootcdn.net/ajax/libs/vue/2.6.12/vue.min.js"></script>
</head>
<body>

<div id="box">
    <button v-on:click="handleClick1">点我1</button>
    <!-- 下面这个用的多 -->
    <button @click="handleClick2">点我2</button>
    <!-- 如果不传参数,是没有区别的 -->
    <button @click="handleClick3()">点我3-1(带括号)</button>
    <!-- 如果要传参数 -->
    <button @click="handleClick3(1,22,333)">点我3-2(带括号+参数)</button>
    <!-- 传入事件 -->
    <button @click="handleClick4($event)">点我4(带事件参数)</button>
</div>

</body>
<script>
    let vm = new Vue({
        el: '#box',
        data: {

        },
        methods: {
            handleClick1() {
                console.log('点我1')
            },
            handleClick2() {
                console.log('点我2')
            },
            handleClick3(a,b,c) {
                console.log(a,b,c)
            },
            handleClick4(event) {
                console.log(event)
            },
        }
    })
</script>
</html>

img

v-on参数

当通过methods中定义方法,以供@click调用时,需要注意参数问题:

情况一:如果该方法不需要额外参数,那么方法后的()可以不添加。

  • 但是注意:如果方法本身中有一个参数,那么会默认将原生事件event参数传递进去

情况二:如果需要同时传入某个参数,同时需要event时,可以通过$event传入事件。

image-20210428155355505

image-20210428155400551

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Title</title>
</head>
<body>

<div id="app">
  <!--1.事件调用的方法没有参数-->
  <button @click="btn1Click()">按钮1</button>
  <button @click="btn1Click">按钮1</button>

  <!--2.在事件定义时, 写方法时省略了小括号, 但是方法本身是需要一个参数的, 这个时候, Vue会默认将浏览器生产的event事件对象作为参数传入到方法-->
  <!--<button @click="btn2Click(123)">按钮2</button>-->
  <!--<button @click="btn2Click()">按钮2</button>-->
  <button @click="btn2Click">按钮2</button>

  <!--3.方法定义时, 我们需要event对象, 同时又需要其他参数-->
  <!-- 在调用方式, 如何手动的获取到浏览器参数的event对象: $event-->
  <button @click="btn3Click(abc, $event)">按钮3</button>
</div>

<script src="../js/vue.js"></script>
<script>
  const app = new Vue({
    el: '#app',
    data: {
      message: '你好啊',
      abc: 123
    },
    methods: {
      btn1Click() {
        console.log("btn1Click");
      },
      btn2Click(event) {
        console.log('--------', event);
      },
      btn3Click(abc, event) {
        console.log('++++++++', abc, event);
      }
    }
  })

  // 如果函数需要参数,但是没有传入, 那么函数的形参为undefined
  // function abc(name) {
  //   console.log(name);
  // }
  //
  // abc()
</script>

</body>
</html>

v-on修饰符

在某些情况下,我们拿到event的目的可能是进行一些事件处理。

Vue提供了修饰符来帮助我们方便的处理一些事件:

  • .stop - 调用 event.stopPropagation()
  • .prevent - 调用 event.preventDefault()
  • .{keyCode | keyAlias} - 只当事件是从特定键触发时才触发回调。
  • .native - 监听组件根元素的原生事件
  • .once - 只触发一次回调

image-20210428161522801

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Title</title>
</head>
<body>

<div id="app">
  <!--1. .stop修饰符的使用-->
  <div @click="divClick">
    aaaaaaa
    <button @click.stop="btnClick">按钮</button>
  </div>

  <!--2. .prevent修饰符的使用-->
  <br>
  <form action="baidu">
    <input type="submit" value="提交" @click.prevent="submitClick">
  </form>

  <!--3. .监听某个键盘的键帽-->
  <input type="text" @keyup.enter="keyUp">

  <!--4. .once修饰符的使用-->
  <button @click.once="btn2Click">按钮2</button>
</div>

<script src="../js/vue.js"></script>
<script>
  const app = new Vue({
    el: '#app',
    data: {
      message: '你好啊'
    },
    methods: {
      btnClick() {
        console.log("btnClick");
      },
      divClick() {
        console.log("divClick");
      },
      submitClick() {
        console.log('submitClick');
      },
      keyUp() {
        console.log('keyUp');
      },
      btn2Click() {
        console.log('btn2Click');
      }
    }
  })
</script>

</body>
</html>
 

侦听属性

侦听属性,可以帮助我们侦听data某个数据的变化,从而做相应的自定义操作。

侦听属性是一个对象,它的键是要监听的对象或者变量,值一般是函数,当侦听的data数据发生变化时,会自定执行的对应函数,这个函数在被调用时,vue会传入两个形参,第一个是变化前的数据值,第二个是变化后的数据值。

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script src="https://cdn.bootcdn.net/ajax/libs/vue/2.6.11/vue.min.js"></script>
</head>
<body>
<div id="app">
    <button @click="num++">({{num}})</button>
</div>

<script>
    let vm = new Vue({
        el: '#app',  // vm的模板对象
        data: {      // vm的数据
            num: 0,
        },
        watch: {
            // 侦听属性,监听指定变量的值是否发生变化,当发生变化时调用对应的方法
            num(v1, v2) {
                if (this.num >= 5){
                    this.num = 5;
                }
                console.log(this.num,"修改后num="+v1,"修改前num="+v2);
            }
        }
    });
</script>
</body>
</html>
 

七、过滤器

过滤器,就是vue允许开发者自定义的文本格式化函数,可以使用在两个地方:输出内容和操作数据中。

定义过滤器的方式有两种。

使用Vue.filter()进行全局定义

// 使用: 一般用作js外部文件导入使用
// 注意: 如果需要展示数据而实例化Vue对象数据之前.  也就是说js文件的导入, 要先与过滤展示数据的Vue对象实例化之前.
Vue.filter('format', function (money) {
    return money.toFixed(2) + '元';   // js中提供了一个toFixed方法可以保留2位小鼠. (四舍五入)
});
 

代码示例:

html代码

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script src="https://cdn.bootcdn.net/ajax/libs/vue/2.6.11/vue.min.js"></script>
    <script src="filters.js"></script>
</head>
<body>
<div id="app">
    <p>{{price}}</p>
    <!-- price会当作参数传给format函数, 最终以函数的返回值作为最终的返回结果 -->
    <p>{{price|format}}</p>
</div>

<script>
    let vm = new Vue({
        el: '#app',  // vm的模板对象
        data: {      // vm的数据
            price: 8.156333,
        },
        methods: {}  // vm的方法
    });
</script>
<!--注意: 不能放到这个位置-->    
<!--<script src="filters.js"></script>-->
</body>
</html>
 
  • filters.js文件中代码
// 全局过滤器
Vue.filter('format', function(money) {
    return money.toFixed(2) + '元';   // js中提供了一个toFixed方法可以保留2位小鼠. (四舍五入)
});

vue对象中通过filters属性来定义

// 注意: 局部过滤器, 只能争对其Vue实例化的对象数据进行的过滤
filters: {
    format(money) {
        return `${money.toFixed(2)}元`;
    }
}
 

代码示例:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script src="https://cdn.bootcdn.net/ajax/libs/vue/2.6.11/vue.min.js"></script>
</head>
<body>
<div id="app">
    <p>{{price}}</p>
    <p>{{price|format}}</p>
    <p>{{price|format1}}</p>
</div>

<script>
    let vm = new Vue({
        el: "#app",  // vm的模板对象
        data: {      // vm的数据
            price: 8.156333,
        },
        methods: {}, // vm的方法

        // 局部过滤器只能在当前vm对象中使用
        filters: {
            format(money) {
                return `${money.toFixed(2)}元`;
            }
        }
     });

    // 注意: 局部过滤器, 只能争对其Vue实例化的对象数据进行的过滤
    let vm1 = new Vue({
       el: '#app',
       data: {},
       filters: {
            format1(money) {
                return `${money.toFixed(2)}元`;
            }
        }
    });
</script>
</body>
</html>

小结

# Vue对象提供的属性功能
    # 提示: 过滤器, 一定要指定返回值,如果返回true,则被过滤出来的结果赋值给参数

    # 全局过滤器: 定义在被过滤对象Vue实例化之前. 一般作为js文件导入.
    Vue.filter('过滤器名', fuction(参数1, 参数2, ...) {
        过滤数据的逻辑代码
        return 过滤以后的结果;
    })


    # 局部过滤器: 定义在Vue对象内部. 只能争对当前所在的Vue对象实例化以后vm对象的数据进行过滤
    let vm = new Vue({
        el: '',
        data: {},
        methods: {},
        filters: {
            过滤器名(参数1, 参数2, ...) {
                过滤数据的逻辑代码
                return 过滤以后的结果;
            }
        }
    });

八、V-for循环遍历

当我们有一组数据需要进行渲染时,我们就可以使用v-for来完成。

v-for的语法类似于JavaScript中的for循环。

格式如下:item in items的形式。

v-for遍历数组

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Title</title>
</head>
<body>

<div id="app">
  <!--1.在遍历的过程中,没有使用索引值(下标值)-->
  <ul>
    <li v-for="item in names">{{item}}</li>
  </ul>

  <!--2.在遍历的过程中, 获取索引值-->
  <ul>
    <li v-for="(item, index) in names">
      {{index+1}}.{{item}}
    </li>
  </ul>
</div>

<script src="../js/vue.js"></script>
<script>
  const app = new Vue({
    el: '#app',
    data: {
      names: ['why', 'kobe', 'james', 'curry']
    }
  })
</script>

</body>
</html>

v-for遍历对象

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Title</title>
</head>
<body>

<div id="app">
  <!--1.在遍历对象的过程中, 如果只是获取一个值, 那么获取到的是value-->
  <ul>
    <li v-for="item in info">{{item}}</li>
  </ul>


  <!--2.获取key和value 格式: (value, key) -->
  <ul>
    <li v-for="(value, key) in info">{{value}}-{{key}}</li>
  </ul>


  <!--3.获取key和value和index 格式: (value, key, index) -->
  <ul>
    <li v-for="(value, key, index) in info">{{value}}-{{key}}-{{index}}</li>
  </ul>
</div>

<script src="../js/vue.js"></script>
<script>
  const app = new Vue({
    el: '#app',
    data: {
      info: {
        name: 'why',
        age: 18,
        height: 1.88
      }
    }
  })
</script>

</body>
</html>
 

组件的Key属性

vue中使用的是虚拟DOM,会和原生的DOM进行比较,然后进行数据的更新,提高数据的刷新速度(虚拟DOM用了diff算法)

  • v-for循环数组、对象时,建议在控件/组件/标签写1个key属性,属性值唯一
  • 页面更新之后,会加速DOM的替换(渲染)
  • :key="变量"

v-for 使用过程中添加key

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Title</title>
</head>
<body>

<div id="app">
  <ul>
    <li v-for="item in letters" :key="item">{{item}}</li>
  </ul>
</div>

<script src="../js/vue.js"></script>
<script>
  const app = new Vue({
    el: '#app',
    data: {
      letters: ['A', 'B', 'C', 'D', 'E']
    }
  })
</script>

</body>
</html>

数组更新与检测

可以检测到变动的数组操作:

push:最后位置添加
pop:最后位置删除
shift:第一个位置删除
unshift:第一个位置添加
splice:切片
sort:排序
reverse:反转

检测不到变动的数组操作:

filter():过滤
concat():追加另一个数组
slice():
map():

原因:

作者重写了相关方法(只重写了一部分方法,但是还有另一部分没有重写)

解决方法:

// 方法1:通过 索引值 更新数组(数据会更新,但是页面不会发生改变)
vm.arrayList[0]
"Alan"
vm.arrayList[0]='Darker'
"Darker"

// 方法2:通过 Vue.set(对象, index/key, value) 更新数组(数据会更新,页面也会发生改变)
Vue.set(vm.arrayList, 0, 'Darker')
 

示例代码:

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Title</title>
</head>
<body>

<div id="app">
  <ul>
    <li v-for="item in letters">{{item}}</li>
  </ul>
  <button @click="btnClick">按钮</button>
</div>

<script src="../js/vue.js"></script>
<script>
  const app = new Vue({
    el: '#app',
    data: {
      letters: ['a', 'b', 'c', 'd']
    },
    methods: {
      btnClick() {
        // 1.push方法
        // this.letters.push('aaa')
        // this.letters.push('aaaa', 'bbbb', 'cccc')

        // 2.pop(): 删除数组中的最后一个元素
        // this.letters.pop();

        // 3.shift(): 删除数组中的第一个元素
        // this.letters.shift();

        // 4.unshift(): 在数组最前面添加元素
        // this.letters.unshift()
        // this.letters.unshift('aaa', 'bbb', 'ccc')

        // 5.splice作用: 删除元素/插入元素/替换元素
        // 删除元素: 第二个参数传入你要删除几个元素(如果没有传,就删除后面所有的元素)
        // 替换元素: 第二个参数, 表示我们要替换几个元素, 后面是用于替换前面的元素
        // 插入元素: 第二个参数, 传入0, 并且后面跟上要插入的元素
        // splice(start)
        // splice(start):
        this.letters.splice(1, 3, 'm', 'n', 'l', 'x')
        // this.letters.splice(1, 0, 'x', 'y', 'z')

        // 5.sort()
        // this.letters.sort()

        // 6.reverse()
        // this.letters.reverse()

        // 注意: 通过索引值修改数组中的元素
        // this.letters[0] = 'bbbbbb';
        // this.letters.splice(0, 1, 'bbbbbb')
        // set(要修改的对象, 索引值, 修改后的值)
        Vue.set(this.letters, 0, 'bbbbbb')
      }
    }
  })


  // function sum(num1, num2) {
  //   return num1 + num2
  // }
  //
  // function sum(num1, num2, num3) {
  //   return num1 + num2 + num3
  // }
  // function sum(...num) {
  //   console.log(num);
  // }
  //
  // sum(20, 30, 40, 50, 601, 111, 122, 33)

</script>

</body>
</html>
 

九、事件处理

事件释义
input 当输入框进行输入的时候 触发的事件
change 当元素的值发生改变时 触发的事件
blur 当输入框失去焦点的时候 触发的事件

change 和 blur 最本质的区别:

如果输入框为空,失去焦点后,change不会触发,但是blur会触发

过滤案例:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>过滤案例</title>
    <script src="https://cdn.bootcdn.net/ajax/libs/vue/2.6.12/vue.min.js"></script>
</head>
<body>
<div id="box">
    <p><input type="text" v-model="myText" @input="handleInput" placeholder="请输入要筛选的内容:"></p>
<!-- <p><input type="text" v-model="myText" @change="handleInput" placeholder="请输入要筛选的内容:"></p> -->
<!-- <p><input type="text" v-model="myText" @blur="handleInput" placeholder="请输入要筛选的内容:"></p> -->
    <ul>
        <li v-for="data in newList">{{data}}</li>
    </ul>
</div>
</body>
<script>
    var vm = new Vue({
        el: '#box',
        data: {
            myText: '',
            dataList: ['a', 'at', 'atom', 'be', 'beyond', 'cs', 'csrf'],
            newList: ['a', 'at', 'atom', 'be', 'beyond', 'cs', 'csrf'],
        },
        methods: {
            handleInput() {
                this.newList = this.dataList.filter(item => {
                    // item.indexOf(this.myText):输入框中输入的字符串在筛选元素中第一次匹配到的索引
                    return item.indexOf(this.myText) > = 0   // 对应的索引大于等于0,说明能被筛选到,布尔值对应true,将筛选到的结果交给参数
                })
            },
        },
    })
</script>
</html>
 

img

事件修饰符

事件修饰符释义
.stop 只处理自己的事件,父控件冒泡的事件不处理(阻止事件冒泡)
.self 只处理自己的事件,子控件冒泡的事件不处理
.prevent 阻止a链接的跳转
.once 事件只会触发一次(适用于抽奖页面)

使用修饰符时,顺序很重要;相应的代码会以同样的顺序产生

v-on:click.prevent.self 会阻止所有的点击
v-on:click.self.prevent 只会阻止对元素自身的点击

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>事件修饰符</title>
    <script src="https://cdn.bootcdn.net/ajax/libs/vue/2.6.12/vue.min.js"></script>
</head>
<body>
<div id="box">
<!--    <ul @click="handleUl">-->
    <ul @click.self="handleUl">
<!--        <li v-for="data in dataList" @click="handleLi">{{data}}</li>-->
        <li v-for="data in dataList" @click.stop="handleLi">{{data}}</li>
        <li><a href="http://www.baidu.com">不拦截</a></li>
        <li><a href="http://www.baidu.com" @click="handleLink($event)">点击拦截</a></li>
        <li><a href="https://www.baidu.com" @click.prevent="handleLink">点击拦截</a></li>
        <li><button @click.once="test">只执行一次</button></li>
    </ul>
</div>
</body>
<script>
    var vm = new Vue({
        el: '#box',
        data: {
            dataList: ['1','22','333','4444']
        },
        methods: {
            handleUl(ev){
                console.log('ul被点击了')
            },
            handleLi(){
                console.log('li被点击了')
                ev.stopPropagation()    // 点击事件停止 冒泡(向父组件传递时间)
            },
            handleLink(ev){
                ev.preventDefault()
            },
            test(){
                alert('只触发1次')
            }
        }
    })
</script>
</html>
 

事件冒泡

事件冒泡

阻止事件冒泡

阻止事件冒泡

阻止链接跳转+只执行1次

阻止链接跳转+只执行1次

按键修饰符

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>按键修饰符</title>
    <script src="https://cdn.bootcdn.net/ajax/libs/vue/2.6.12/vue.min.js"></script>
</head>
<body>
<div id="box">
    <!--    <input type="text" v-model="myInput" @keyup="handleKey">-->
    <!--    <input type="text" v-model="myInput" @keyup.13="handleKey">-->
    <input type="text" @keyup="handleKey1">
    <input type="text" @keyup.enter="handleKey2">
</div>
</body>
<script>
    var vm = new Vue({
        el: '#box',
        data: {
            dataList: ['1', '22', '333', '4444']
        },
        methods: {
            handleKey1(ev) {
                console.log('按下了' + ev)
                // if (ev.keyCode==13){
                //     console.log('回车键被按下了')
                // }
            },
            handleKey2(ev) {
                console.log('按下了回车键')
            }
        }
    })
</script>
</html>
 

img

十、数据的双向绑定

表单控件在实际开发中是非常常见的。特别是对于用户信息的提交,需要大量的表单。

  • Vue中使用v-model指令来实现表单元素和数据的双向绑定。

基本使用:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script src="https://cdn.bootcdn.net/ajax/libs/vue/2.6.12/vue.min.js"></script>
</head>
<body>
<div id="box">
    <!--用法1-->
    <!--1.当我们在输入框输入内容时-->
    <!--因为input中的v-model绑定了message,所以会实时将输入的内容传递给message,message发生改变-->
    <!--当message发生改变时,因为上面我们使用Mustache语法,将message的值插入到DOM中,所以DOM会发生响应的改变-->
    <!--当message发生改变时,因为上面我们使用Mustache语法,将message的值插入到DOM中,所以DOM会发生响应的改变-->
    <input type="text" v-model="myText" placeholder="请输入内容">
    <br>
    <hr>
    <!--用法二-->
    <!--我们也可以将v-model用于textarea元素-->
    <textarea v-model="myText" placeholder="请输入内容"></textarea>
    <p>您输入的内容是:{{ myText }}</p>
</div>
</body>
<script>
    var vm = new Vue({
        el: '#box',
        data: {
            myText: '',
        },
    })
</script>
</html>
 

img

v-models 原理

v-model其实是一个语法糖,它的背后本质上是包含两个操作:

  • 1.v-bind绑定一个value属性
  • 2.v-on指令给当前元素绑定input事件

也就是说下面的代码:等同于下面的代码:

<input type="text" v-model="message">
等同于
<input type="text" v-bind:value="message" v-on:input="message = $event.target.value">
 

image-20210428232212313

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Title</title>
</head>
<body>

<div id="app">
  <!--<input type="text" v-model="message">-->
  <!--<input type="text" :value="message" @input="valueChange">-->
  <input type="text" :value="message" @input="message = $event.target.value">
  <h2>{{message}}</h2>
</div>

<script src="../js/vue.js"></script>
<script>
  const app = new Vue({
    el: '#app',
    data: {
      message: '你好啊'
    },
    methods: {
      valueChange(event) {
        this.message = event.target.value;
      }
    }
  })
</script>

</body>
</html>
 

十一、表单控制

v-model结合radio类型(单选)

  • 当存在多个单选框时
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Title</title>
</head>
<body>

<div id="app">
  <label for="male">
    <input type="radio" id="male" value="男" v-model="sex"></label>
  <label for="female">
    <input type="radio" id="female" value="女" v-model="sex"></label>
  <label for="female">
    <input type="radio"id="Keep secret" value="保密" v-model="sex">保密
  </label>
  <h2>您选择的性别是: {{sex}}</h2>
</div>

<script src="../js/vue.js"></script>
<script>
  const app = new Vue({
    el: '#app',
    data: {
      message: '你好啊',
      sex: '女'
    }
  })
</script>

</body>
</html>
 

checkbox选中

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>checkbox</title>
    <script src="https://cdn.bootcdn.net/ajax/libs/vue/2.6.12/vue.min.js"></script>
</head>
<body>
<div id="box">
    <input type="text" placeholder="请输入用户名:"><br>
    <input type="password" placeholder="请输入密码:"><br>
    <input type="checkbox" v-model="radio">记住用户名
</div>
</body>
<script>
    var vm = new Vue({
        el: '#box',
        data: {
            myText: '',
            textBig: '',
            radio: false,
        },
    })
</script>
</html>
 

img

v-model结合checkbox类型(多选)

复选框分为两种情况:单个勾选框和多个勾选框

单个勾选框:

  • v-model即为布尔值。
  • 此时input的value并不影响v-model的值。

多个复选框:

  • 当是多个复选框时,因为可以选中多个,所以对应的data中属性是一个数组。
  • 当选中某一个时,就会将input的value添加到数组中。

image-20210428235834137

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Title</title>
</head>
<body>

<div id="app">
  <!--1.checkbox单选框-->
  <!--<label for="agree">-->
    <!--<input type="checkbox" id="agree" v-model="isAgree">同意协议-->
  <!--</label>-->
  <!--<h2>您选择的是: {{isAgree}}</h2>-->
  <!--<button :disabled="!isAgree">下一步</button>-->

  <!--2.checkbox多选框-->
  <input type="checkbox" value="篮球" v-model="hobbies">篮球
  <input type="checkbox" value="足球" v-model="hobbies">足球
  <input type="checkbox" value="乒乓球" v-model="hobbies">乒乓球
  <input type="checkbox" value="羽毛球" v-model="hobbies">羽毛球
  <h2>您的爱好是: {{hobbies}}</h2>

  <label v-for="item in originHobbies" :for="item">
    <input type="checkbox" :value="item" :id="item" v-model="hobbies">{{item}}
  </label>
</div>

<script src="../js/vue.js"></script>
<script>
  const app = new Vue({
    el: '#app',
    data: {
      message: '你好啊',
      isAgree: false, // 单选框
      hobbies: [], // 多选框,
      originHobbies: ['篮球', '足球', '乒乓球', '羽毛球', '台球', '高尔夫球']
    }
  })
</script>

</body>
</html>
 

测试

购物车案例-结算

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>购物车结算</title>
    <script src="https://cdn.bootcdn.net/ajax/libs/vue/2.6.12/vue.min.js"></script>
    <style>
        table, td {
            border: 1px solid black;
            text-align: center;
        }
    </style>
</head>
<body>
<div id="box">
    <table>
        <tr>
            <td>商品名称</td>
            <td>价格</td>
            <td>数量</td>
            <td>选择</td>
        </tr>
        <tr v-for="item in dataList">
            <td>{{item.name}}</td>
            <td>{{item.price}}</td>
            <td>{{item.number}}</td>
            <td><input type="checkbox" :value="item" v-model="checkGroup"></td>
        </tr>
    </table>
    <br>已选商品:{{checkGroup}}
    <br>总价:{{getPrice()}}
</div>
</body>
<script>
    var vm = new Vue({
        el: '#box',
        data: {
            dataList: [
                {name: '今瓶没', price: 99, number: 2},
                {name: '西柚记', price: 59, number: 1},
                {name: '水壶转', price: 89, number: 5},
            ],
            checkGroup: [],
        },
        methods: {
            getPrice() {
                let sum_price = 0
                for (i in this.checkGroup) {    // 这里的 i 是索引
                    sum_price += this.checkGroup[i]['number'] * this.checkGroup[i]['price']
                }
                return sum_price
            }
        }
    })
</script>
</html>
 

img

购物车案例 - 全选/全不选

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>全选/全不选</title>
    <script src="https://cdn.bootcdn.net/ajax/libs/vue/2.6.12/vue.min.js"></script>
    <style>
        table, td {
            border: 1px solid black;
            text-align: center;
        }
    </style>
</head>
<body>
<div id="box">
    <table>
        <tr>
            <td>商品名称</td>
            <td>价格</td>
            <td>数量</td>
            <td>全选/全不选<input type="checkbox" v-model="allChecked" @change="checkAll"></td>
        </tr>
        <tr v-for="item in dataList">
            <td>{{item.name}}</td>
            <td>{{item.price}}</td>
            <td>{{item.number}}</td>
            <td><input type="checkbox" :value="item" v-model="checkGroup" @change="checkOne"></td>
        </tr>
    </table>
    <br>已选商品:{{checkGroup}}
    <br>总价:{{getPrice()}}
</div>
</body>
<script>
    var vm = new Vue({
        el: '#box',
        data: {
            dataList: [
                {name: '今瓶没', price: 99, number: 2},
                {name: '西柚记', price: 59, number: 1},
                {name: '水壶转', price: 89, number: 5},
            ],
            checkGroup: [],
            allChecked: false,
        },
        methods: {
            getPrice() {
                let sum_price = 0
                for (i in this.checkGroup) {    // 这里的 i 是索引
                    sum_price += this.checkGroup[i]['number'] * this.checkGroup[i]['price']
                }
                return sum_price
            },
            checkAll() {
                if (this.checkGroup.length > 0) {
                    this.checkGroup = []
                } else {
                    this.checkGroup = this.dataList
                }
            },
            checkOne() {
                // if (this.checkGroup.length === this.dataList.length) {
                //     this.allChecked = true
                // } else {
                //     this.allChecked = false
                // }
                this.allChecked = this.checkGroup.length === this.dataList.length;
            }
        }
    })
</script>
</html>
 

img

购物车案例 - 数量加减

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>控制加减</title>
    <script src="https://cdn.bootcdn.net/ajax/libs/vue/2.6.12/vue.min.js"></script>
    <link href="https://cdn.bootcdn.net/ajax/libs/twitter-bootstrap/4.5.3/css/bootstrap.min.css" rel="stylesheet">
</head>
<body>
<div class="row">
    <div id="box" class="col-md-4 offset-md-1 text-center mt-5 ">
        <table class="table table-bordered">
            <thead>
            <tr>
                <th scope="col">商品名称</th>
                <th scope="col">单价</th>
                <th scope="col">数量</th>
                <th scope="col">全选/全不选 <input type="checkbox" v-model="allChecked" @change="checkAll"></th>
            </tr>
            </thead>
            <tbody>
            <tr v-for="item in dataList">
                <td>{{item.name}}</td>
                <td>{{item.price}}</td>
                <td>
                    <button class="btn link btn-sm" @click="reduceNum(item)">-</button>
                    {{item.number}}
                    <button class="btn link btn-sm" @click="item.number++">+</button>
                </td>
                <td><input type="checkbox" :value="item" v-model="checkGroup" @change="checkOne"></td>
            </tr>
            <tr class="text-left">
                <td colspan="4">总价:{{getPrice()}}
            </tr>
            </tbody>
        </table>
    </div>
</div>
</body>
<script>
    var vm = new Vue({
        el: '#box',
        data: {
            dataList: [
                {name: '今瓶没', price: 99, number: 1},
                {name: '西柚记', price: 59, number: 1},
                {name: '水壶转', price: 89, number: 1},
            ],
            checkGroup: [],
            allChecked: false,
        },
        methods: {
            getPrice() {
                let sum_price = 0
                for (i in this.checkGroup) {
                    sum_price += this.checkGroup[i]['number'] * this.checkGroup[i]['price']
                }
                return sum_price
            },
            checkAll() {
                if (this.checkGroup.length > 0) {
                    this.checkGroup = []
                } else {
                    this.checkGroup = this.dataList
                }
            },
            checkOne() {
                // if (this.checkGroup.length === this.dataList.length) {
                //     this.allChecked = true
                // } else {
                //     this.allChecked = false
                // }
                this.allChecked = this.checkGroup.length === this.dataList.length;
            },
            reduceNum(item) {
                if (item.number === 1) {
                    item.number = 1
                } else {
                    item.number--
                }
            }
        }
    })
</script>
</html>
 

img

v-model结合select类型(单选)

和checkbox一样,select也分单选和多选两种情况。

单选:只能选中一个值。

  • v-model绑定的是一个值。
  • 当我们选中option中的一个时,会将它对应的value赋值到mySelect中

多选:可以选中多个值。

  • v-model绑定的是一个数组。
  • 当选中多个值时,就会将选中的option对应的value添加到数组mySelects中
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Title</title>
</head>
<body>

<div id="app">
  <!--1.选择一个-->
  <select name="abc" v-model="fruit">
    <option value="苹果">苹果</option>
    <option value="香蕉">香蕉</option>
    <option value="榴莲">榴莲</option>
    <option value="葡萄">葡萄</option>
  </select>
  <h2>您选择的水果是: {{fruit}}</h2>

  <!--2.选择多个-->
  <select name="abc" v-model="fruits" multiple>
    <option value="苹果">苹果</option>
    <option value="香蕉">香蕉</option>
    <option value="榴莲">榴莲</option>
    <option value="葡萄">葡萄</option>
  </select>
  <h2>您选择的水果是: {{fruits}}</h2>
</div>

<script src="../js/vue.js"></script>
<script>
  const app = new Vue({
    el: '#app',
    data: {
      message: '你好啊',
      fruit: '香蕉',
      fruits: []
    }
  })
</script>

</body>
</html>
 

测试

v-model修饰符的使用

lazy修饰符:

  • 默认情况下,v-model默认是在input事件中同步输入框的数据的。
  • 也就是说,一旦有数据发生改变对应的data中的数据就会自动发生改变。
  • lazy修饰符可以让数据在失去焦点或者回车时才会更新:

number修饰符:

  • 默认情况下,在输入框中无论我们输入的是字母还是数字,都会被当做字符串类型进行处理。

  • 如果是以数字开头,则只保留数字,后面输入的字符串不被保留

  • 非数字开头,都会保留

trim修饰符:

  • 如果输入的内容首尾有很多空格,通常我们希望将其去除
  • trim修饰符可以过滤内容左右两边的空格
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>v-model 之 lazy、number、trim</title>
    <script src="https://cdn.bootcdn.net/ajax/libs/vue/2.6.12/vue.min.js"></script>
</head>
<body>
<div id="box">
    <input type="text" v-model="myText1" placeholder="normal"> {{myText1}}
    <br>
    <input type="text" v-model.lazy="myText2" placeholder="lazy"> {{myText2}}
    <br>
    <input type="text" v-model.number="myText3" placeholder="number"> {{myText3}}
    <br>
    <input type="text" v-model.trim="myText4" placeholder="trim"> {{myText4}}
</div>
</body>
<script>
    var vm = new Vue({
        el: '#box',
        data: {
            myText1: '',
            myText2: '',
            myText3: '',
            myText4: '',
        },
    })
</script>
</html>
 

img

posted @ 2023-02-16 16:31  莫~慌  阅读(38)  评论(0编辑  收藏  举报