• 2.Vue系列 基础语法


    模板语法

    一、插值操作

    将值插入到html的内容当中

    Mustache(就是双大括号)
    <!DOCTYPE html>
    <html lang="en">
    <head>
        <title>Vue demo</title>
    </head>
    <body>
        <div id="app">
            <h2>hello {{name}}</h2>  //插入到标签中
            <h2>{{first_name}} {{last_name}</h2>  使用了两个mustache
            <h2>{{counter**2}}</h2>  //也可以是一个表达式
        </div>
        
    </body>
    <script src="vue.js"></script>
    <script>
        let app = new Vue({
            el: '#app',
            data: {
                name: 'Vue',
                first_name: 'kang',
                last_name: 'pc',
                counter: 10
            }
        })
    </script>
    </html>

    v-once

    该指令后面不需要跟任何表达式(比如之前的v-for后面是由跟表达式的)

    该指令表示元素和组件(组件后面才会学习)只渲染一次,不会随着数据的改变而改变。

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <title>Vue demo</title>
    </head>
    <body>
        <div id="app">
            <h2>hello {{name}}</h2>
            <h2 v-once>hello {{name}}</h2>
        </div>
        
    </body>
    <script src="vue.js"></script>
    <script>
        let app = new Vue({
            el: '#app',
            data: {
                name: 'kang'
            }
        })
    </script>
    </html>

    v-html : 使用v-html指令,解析出HTML展示

    该指令后面往往会跟上一个string类型

    会将string的html解析出来并且进行渲染

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <title>Vue demo</title>
    </head>
    <body>
        <div id="app">
            <h2>{{url}}</h2>
            <h2 v-html="url"></h2>
        </div>
        
    </body>
    <script src="vue.js"></script>
    <script>
        let app = new Vue({
            el: '#app',
            data: {
                url: '<a href="https://www.baidu.com">百度一下</a>'
            }
        })
    </script>
    </html>

    v-text 比较少用,因为不灵活

    v-text作用和Mustache比较相似:都是用于将数据显示在界面中

    v-text通常情况下,接受一个string类型

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <title>Vue demo</title>
    </head>
    <body>
        <div id="app">
            <h2>{{message}}, kang</h2>
            // message会把, kang覆盖
            <h2 v-text="message">, kang</h2>
        </div>
        
    </body>
    <script src="vue.js"></script>
    <script>
        let app = new Vue({
            el: '#app',
            data: {
                message: '你好啊'
            }
        })
    </script>
    </html>

    v-pre 比较少用

    v-pre用于跳过这个元素和它子元素的编译过程,用于显示原本的Mustache语法。比如下面的代码:

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <title>Vue demo</title>
    </head>
    <body>
        <div id="app">
            <h2>{{message}}</h2>
            <h2 v-pre>{{message}}</h2>
        </div>
        
    </body>
    <script src="vue.js"></script>
    <script>
        let app = new Vue({
            el: '#app',
            data: {
                message: '你好啊'
            }
        })
    </script>
    </html>

    第一个h2元素中的内容会被编译解析出来对应的内容

    第二个h2元素中会直接显示{{message}}

    v-cloak 斗篷 ,少用

    在某些情况下,我们浏览器可能会直接显然出未编译的Mustache标签。

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <title>Vue demo</title>
        <style>
            [v-cloak] {
                display: none;
            }
        </style>
    </head>
    <body>
        <div id="app">
            <h2>{{message}}</h2>
            <h2 v-cloak>{{message}}</h2>
        </div>
        
    </body>
    <script src="vue.js"></script>
    <script>
        setTimeout(() => {
            let app = new Vue({
            el: '#app',
            data: {
                message: '你好啊'
                }
            })
        },5000)
    </script>
    </html>

    二、绑定属性

    v-bind

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

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

    1. 比如动态绑定a元素的href属性
    2. 比如动态绑定img元素的src属性

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

    作用:动态绑定属性

    缩写::

    预期:any (with argument) | Object (without argument)

    参数:attrOrProp (optional)

    v-bind用于绑定一个或多个属性值,或者向另一个组件传递props值(这个学到组件时再介绍).

    在开发中,有哪些属性需要动态进行绑定呢?还是有很多的,比如图片的链接src、网站的链接href、动态绑定一些类、样式等等.

    比如通过Vue实例中的data绑定元素的src和href,代码如下:

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <title>Vue demo</title>
    </head>
    <body>
        <div id="app">
            //v-bind语法糖
            <a :href="url">百度一下</a><br>
            <img v-bind:src="img_url" alt="">
        </div>
        
    </body>
    <script src="vue.js"></script>
    <script>
        let app = new Vue({
            el: '#app',
            data: {
                img_url: 'https://i0.hdslb.com/bfs/sycp/creative_img/202104/9a5cf4c28ff903549de5702668892dfd.jpg',
                url: 'https://i0.hdslb.com/bfs/feed-admin/6e73bf15d0348ee1313c15b3812b88a7a998513e.jpg',
            }
        })
    </script>
    </html>

    v-bind绑定class

    很多时候,我们希望动态的来切换class,比如:

    1. 当数据为某个状态时,字体显示红色。

    2. 当数据另一个状态时,字体显示黑色。

    绑定class有两种方式:

    1. 对象语法

    2. 数组语法

    绑定方式:对象语法

    对象语法的含义是:class后面跟的是一个对象。

    对象语法有下面这些用法:

    用法一:直接通过{}绑定一个类
    <h2 :class="{active: isActive}">Hello World</h2>
    
    用法二:也可以通过判断,传入多个值
    <h2 :class="{active: isActive, line: isLine}">Hello World</h2>
    
    用法三:和普通的类同时存在,并不冲突
    注:如果isActive和isLine都为true,那么会有title/active/line三个类
    <h2 class="title" :class="{active: isActive, line: isLine}">Hello World</h2>
    
    用法四:如果过于复杂,可以放在一个methods或者computed中
    注:classes是一个计算属性
    <h2 class="title" :class="classes">Hello World</h2>

    示例代码:

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <title>Vue学习demo</title>
        <style>
            .isActive{
                color: red;
            }
        </style>
    </head>
    <body>
        <div id="app">
            <!-- <h2 class="title" :class="{active: isActive,line:isLine}">{{message}}</h2> -->
            <!-- <button @click="f">按钮</button> -->
            <h3 class="title" :class="classStyle">{{message}}</h3>
            <button @click="btn_click">点一下</button>
        </div>
        
    </body>
    <script src="vue.js"></script>
    <script>
        let app = new Vue({
            el: '#app',
            data: {
                message: '你好呀',
                lst: [1,2],
                classStyle: {
                    isActive: true,
                    isLine: true,  
                }      
            },
            methods: {
                // f: function(){
                //     this.isActive = !this.isActive;
                // },
                btn_click () {
                    this.classStyle.isActive =  !this.classStyle.isActive;
                    this.classStyle.isLine =  !this.classStyle.isLine
    
                    this.lst
                }
            }
        })
    </script>
    </html>
    绑定方式:数组语法 比较少用

    数组语法的含义是:class后面跟的是一个数组。

    数组语法有下面这些用法:

    用法一:直接通过{}绑定一个类
    <h2 :class="['active']">Hello World</h2>
    
    用法二:也可以传入多个值
    <h2 :class=“[‘active’, 'line']">Hello World</h2>
    
    用法三:和普通的类同时存在,并不冲突
    注:会有title/active/line三个类
    <h2 class="title" :class=“[‘active’, 'line']">Hello World</h2>
    
    用法四:如果过于复杂,可以放在一个methods或者computed中
    注:classes是一个计算属性
    <h2 class="title" :class="classes">Hello World</h2>

    示例代码:

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <title>Vue学习demo</title>
    </head>
    <body>
        <div id="app">
            <h2 class="title" :class="['active','line']">{{message}}</h2>
            <h2 class="title" :class="[active,line]">{{message}}</h2>
            <h3 :class="get_classes()">{{message}}</h3>
        </div>
        
    </body>
    <script src="vue.js"></script>
    <script>
        let app = new Vue({
            el: '#app',
            data: {
                message: '你好呀',
                active: 'aaa',
                line: 'bbb',        
            },
            methods: {
                get_classes: function () {
                    return [this.active,this.line]  
                }
            }
        })
    </script>
    </html>
    作业:点击列表中的哪一项,那么该项的文字变成红色
    <!DOCTYPE html>
    <html lang="en">
    <head>
        <title>Vue demo</title>
        <style>
            .active {
                color: red;
            }
        </style>
    </head>
    <body>
        <div id="app">
            <ul>
                <li v-for="(item, index) in movies" 
                :class="{active: current_index === index}" 
                @click="li_click(index)">
                {{index}}. {{item}}
            </li>
            </ul>
        </div>
        
    </body>
    <script src="vue.js"></script>
    <script>
        let app = new Vue({
            el: '#app',
            data: {
                movies: ['智能时代','异类','三体','数学之美','阅读和表达讲义'],
                current_index: 0
            },
            methods: {
                li_click (index) {
                    this.current_index = index
                }
            }
        })
    </script>
    </html>
    v-bind绑定style

    我们可以利用v-bind:style来绑定一些CSS内联样式。

    在写CSS属性名的时候,比如font-size

    1. 我们可以使用驼峰式 (camelCase) fontSize

    2. 或短横线分隔 (kebab-case,记得用单引号括起来) ‘font-size’

    绑定class有两种方式:

    1. 对象语法

    2. 数组语法

    绑定方式一:对象语法
    :style="{color: currentColor, fontSize: fontSize + 'px'}"
    style后面跟的是一个对象类型
    对象的key是CSS属性名称
    对象的value是具体赋的值,值可以来自于data中的属性

    示例代码:

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <title>Vue学习demo</title>
    </head>
    <body>
        <div id="app">
            <!-- <h3 v-for="(movie, index) in movies" :style="{color:color,fontSize:fontSize + 'px'}">{{index}}-{{movie}}</h3> -->
            <h3 v-for="(movie, index) in movies" :style="getStyles()">{{index}}-{{movie}}</h3>
        </div>
        
    </body>
    <script src="vue.js"></script>
    <script>
        const app = new Vue({
            el: '#app',
            data: {
                movies: ['海贼王','犬夜叉','围棋少年','秦时明月','哪吒'],
                color: 'red',
                fontSize: 20,
            },
            methods: {
                getStyles: function () {
                    return {color: this.color, fontSize: this.fontSize + 'px'}
                }
            }
        })
    </script>
    </html>
    绑定方式二:数组语法
    <div v-bind:style="[baseStyles, overridingStyles]"></div>
    style后面跟的是一个数组类型
    多个值以,分割即可

    示例代码:

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <title>Vue学习demo</title>
    </head>
    <body>
        <div id="app">
            <h3 :style="[a, b]">{{message}}</h3>
            <h3 :style="getStyles()">{{message}}</h3>
        </div>
        
    </body>
    <script src="vue.js"></script>
    <script>
        const app = new Vue({
            el: '#app',
            data: {
                message: '你好呀',
                a: {backgroundColor: 'red'},
                b: {fontSize: '50px'},
            },
            methods: {
                getStyles: function () {
                    return [this.a, this.b]
                }
            }
        })
    </script>
    </html>

    三、计算属性

    基础操作

    在模板中可以直接通过插值语法显示一些data中的数据,但是在某些情况,我们可能需要对数据进行一些转化后再显示,或者需要将多个数据结合起来进行显示。

    比如我们有firstName和lastName两个变量,我们需要显示完整的名称。

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

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

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <title>Vue学习demo</title>
    </head>
    <body>
        <div id="app">
            <h2>{{first_name + ' ' + last_name}}</h2>
            <h2>{{first_name}} {{last_name}}</h2>
            <h2>{{get_full_name()}}</h2>
            <h2>{{full_name}}</h2>
        </div>
        
    </body>
    <script src="vue.js"></script>
    <script>
        const app = new Vue({
            el: '#app',
            data: {
                first_name: 'Lebron',
                last_name: 'James',
            },
            computed: {
                full_name: function () {
                    return this.first_name + ' ' + this.last_name;
                }
            },
            methods: {
                get_full_name: function () {
                    return this.first_name + ' ' + this.last_name
                }
            }
        })
    </script>
    </html>
    复杂操作
    <!DOCTYPE html>
    <html lang="en">
    <head>
        <title>Vue学习demo</title>
    </head>
    <body>
        <div id="app">
            <h2>总价格(RMB):{{total_price}}</h2>  
        </div>
        
    </body>
    <script src="vue.js"></script>
    <script>
        const app = new Vue({
            el: '#app',
            data: {
                books: [
                    {id: 1, name: 'Unix编程艺术', price: 140},
                    {id: 2, name: '代码大全', price: 130},
                    {id: 3, name: '深入理解计算机原理', price: 120},
                    {id: 4, name: '现代操作系统', price: 110},
                ]
            },
            computed: {
                total_price: function () {
                    let result = 0
                    for (let i = 0; i < this.books.length; i++) {
                        result += this.books[i].price
                    }
                    return result
                }
            }
        })
    </script>
    </html>
    计算属性的setter和getter

    每个计算属性都包含一个getter和一个setter

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <title>Vue学习demo</title>
    </head>
    <body>
        <div id="app">
            <h2>总价格(RMB):{{total_price}}</h2>
        </div>
        
    </body>
    <script src="vue.js"></script>
    <script>
        const app = new Vue({
            el: '#app',
            data: {
                first_name: 'Kobe',
                last_name: 'Bryant'
            },
            computed: {
                // full_name: {
                //     get: function () {
                //         return this.first_name + ' ' + this.last_name
                //     }
                // },
                full_name: function () {  //computed属性是一个对象集,里面的属性也是一个对象,这里这样写其实是简写,原貌其实是上面的样子
                    return this.first_name + ' ' + this.last_name
                }
            }
        })
    </script>
    </html>

    计算属性一般没有set方法,这样叫只读属性,
    特殊的也可以有set方法,代码如下:

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <title>Vue学习demo</title>
    </head>
    <body>
        <div id="app">
            <h2>{{full_name}}</h2>
        </div>
        
    </body>
    <script src="vue.js"></script>
    <script>
        const app = new Vue({
            el: '#app',
            data: {
                first_name: 'Kobe',
                last_name: 'Bryant'
            },
            computed: {
                full_name: {
                    set: function(new_value) {
                        const names = new_value.split(' ');
                        this.first_name = names[0];
                        this.last_name = names[1];
                        console.log('调用set', new_value);
                    },
                    get: function () {
                        return this.first_name + ' ' + this.last_name
                    }
                },
                // full_name: function () {  //computed属性是一个对象集,里面的属性也是一个对象,这里这样写其实是简写,原貌其实是上面的样子
                //     return this.first_name + ' ' + this.last_name
                // }
            }
        })
    </script>
    </html>
    计算属性的缓存

    methods和computed看起来都可以实现我们的功能,

    那么为什么还要多一个计算属性这个东西呢?

    原因:计算属性会进行缓存,如果多次使用时,计算属性只会调用一次,而methods则不然,每一次调用都是执行一次。

    所以,考虑性能,我们更提倡多用计算属性computed

    示例代码:

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <title>Vue学习demo</title>
    </head>
    <body>
        <div id="app">
            <h2>总价格(RMB):{{total_price}}</h2>
            <h2>总价格(RMB):{{total_price}}</h2>
            <h2>总价格(RMB):{{total_price}}</h2>
            
            <h2>总价格(RMB):{{get_total_price()}}</h2>
            <h2>总价格(RMB):{{get_total_price()}}</h2> 
            <h2>总价格(RMB):{{get_total_price()}}</h2> 
        </div>
        
    </body>
    <script src="vue.js"></script>
    <script>
        const app = new Vue({
            el: '#app',
            data: {
                books: [
                    {id: 1, name: 'Unix编程艺术', price: 140},
                    {id: 2, name: '代码大全', price: 130},
                    {id: 3, name: '深入理解计算机原理', price: 120},
                    {id: 4, name: '现代操作系统', price: 110},
                ]
            },
            computed: {
                total_price: function () {
                    console.log('调用total_price');
                    let result = 0
                    for (let i = 0; i < this.books.length; i++) {
                        result += this.books[i].price
                    }
                    return result
                }
            },
            methods: {
                get_total_price: function () {
                    console.log('调用get_total_price');
                    let result = 0
                    for (let i = 0; i < this.books.length; i++) {
                        result += this.books[i].price
                    }
                    return result               
                }
            }
        })
    </script>
    </html>

    四、事件监听

    在前端开发中,我们需要经常和用于交互。

    这个时候,我们就必须监听用户发生的时间,比如点击、拖拽、键盘事件等等

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

    v-on介绍

    v-on 可以用来监听DOM事件、组件间自定义事件.

    作用:绑定事件监听器

    缩写:@

    预期:Function | Inline Statement | Object

    参数:event

    v-on基础使用
    <!DOCTYPE html>
    <html>
    <head>
        <title>Vue demo</title>
    </head>
    <body>
        <div id="app">
            <h2>当前计数:{{counter}}</h2>
            <button @click="increment">+</button>  
            <button @click="decrement">-</button>  
        </div>
        
    </body>
    <script src="vue.js"></script>
    <script>
        const app = new Vue({
            el: '#app',
            data:{
                counter:0,
            },
            methods:{
                increment() {
                    this.counter++
                },
                decrement() {
                    this.counter--
                }
            }
        })
    </script>
    </html>
    v-on修饰符
    .stop 调用 event.stopPropagation()

    直接上代码

    <!DOCTYPE html>
    <html>
    <head>
        <title>Vue demo</title>
    </head>
    <body>
        <div id="app" @click="btn_click">
            --这里是div--
            <!-- 1..stop修饰符 -->
            <!-- <button @click="btn_click">按钮1</button> -->
            <button @click.stop="btn_click">按钮1</button>
        </div>
        
    </body>
    <script src="vue.js"></script>
    <script>
        const app = new Vue({
            el: '#app',
            data:{
                message: 'hello'
            },
            methods:{
                btn_click() {
                    console.log("btn_click");
                },
    
            }
        })
    </script>
    </html>
    <button @click="btn_click">按钮1</button>

    button点击后的click事件会传递给div的click,然后执行2次btn_click,有时我们并不想要这样的效果,那么可以在button监听的click事件这里加上.stop修饰符即可。

    <button @click.stop="btn_click">按钮1</button>
    .prevent 调用 event.preventDefault()
    <!DOCTYPE html>
    <html>
    <head>
        <title>Vue demo</title>
    </head>
    <body>
        <div id="app">
            --这里是div--
            <form action="https://www.baidu.com">
                <!-- <input type="submit" value="提交" @click="submit_click">  //这里会有2个动作1.打印submit_click,2.提交(跳转到baidu) -->
                <input type="submit" value="提交" @click.prevent="submit_click">  //可以看到打印了打印submit_click,但是没有提交
            </form>
        </div>
        
    </body>
    <script src="vue.js"></script>
    <script>
        const app = new Vue({
            el: '#app',
            data:{
                message: 'hello'
            },
            methods:{
                submit_click() {
                    console.log('submit_click');
                }
            }
        })
    </script>
    </html>

    为什么要用.prevent?

    有的时候我们并不想使用默认的submit事件去提交数据,而是希望我们自己做一些数据处理,然后再手动提交,那么就可以用上.prevent。

    监听键盘按键的点击事件
    <!DOCTYPE html>
    <html>
    <head>
        <title>Vue demo</title>
    </head>
    <body>
        <div id="app">
            --这里是div--
                <!-- <input type="text" @keyup="key_up">  //监听所有按键 -->
                <!--仅监听ENTER键-->
            <input type="text" @keyup.enter="key_up">  
    
        </div>
        
    </body>
    <script src="vue.js"></script>
    <script>
        const app = new Vue({
            el: '#app',
            data:{
                message: 'hello'
            },
            methods:{
                key_up() {
                    console.log("key_up");
                },
            }
        })
    </script>
    </html>
    .once 仅第一次点击有效
    <!DOCTYPE html>
    <html>
    <head>
        <title>Vue demo</title>
    </head>
    <body>
        <div id="app">
            --这里是div--
            <input type="text" @keyup.once="xclick">  
            <button @click.once="xclick">仅点第一次有效</button>
        </div>
        
    </body>
    <script src="vue.js"></script>
    <script>
        const app = new Vue({
            el: '#app',
            data:{
                message: 'hello'
            },
            methods:{
                xclick() {
                    console.log("key_up");
                },
            }
        })
    </script>
    </html>

    五、条件判断

    v-if、v-else-if、v-else

    • 这三个指令与JavaScript的条件语句if、else、else if类似。

    • Vue的条件指令可以根据表达式的值在DOM中渲染或销毁元素或组件

    v-if的原理:

    v-if后面的条件为false时,对应的元素以及其子元素不会渲染。也就是根本不会有对应的标签出现在DOM中

    <!DOCTYPE html>
    <html>
    <head>
        <title>Vue demo</title>
    </head>
    <body>
        <div id="app">
            <!-- <h2 v-if="score>=90">优秀</h2>
            <h2 v-else-if="score>=80">良好</h2>
            <h2 v-else-if="score>=60">及格</h2>
            <h2 v-else>不及格</h2> -->
            <h2>{{result}}</h2>
        </div>
        
    </body>
    <script src="vue.js"></script>
    <script>
        const app = new Vue({
            el: '#app',
            data:{
                score:90
            },
            computed: {
                result(){
                    let show_message = '';
                    if (this.score >= 90) {
                        show_message = '优秀'
                    }else if (this.score >= 80) {
                        show_message = '良好'
                    }else if (this.score >= 60) {
                        show_message = '及格'
                    }else {
                        show_message = '不及格'
                    }
                    return show_message
                }
            },
            methods:{
    
            }
        })
    </script>
    </html>
    条件渲染案例

    用户登录时,可以切换使用用户账号登录还是邮箱登录

    <!DOCTYPE html>
    <html>
    <head>
        <title>Vue demo</title>
    </head>
    <body>
        <div id="app">
            <span v-if="is_user">
                <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="is_user = !is_user">切换登录方式</button>
        </div>
        
    </body>
    <script src="vue.js"></script>
    <script>
        const app = new Vue({
            el: '#app',
            data:{
                is_user:true
            }
        })
    </script>
    </html>
    1. Vue不会直接把元素无脑的渲染到浏览器页面上,而是会经过一个虚拟DOM来加载到内存,代码 -> 虚拟DOM -> 浏览器页面。

    2. 在切换操作中,Vue在进行渲染时,出于性能考虑,会尽可能复用已经存在的元素,而不是重新创建新的元素

    3. 如果我们不希望Vue出现类似重复利用的问题,可以给对应的元素添加唯一key

    <!DOCTYPE html>
    <html>
    <head>
        <title>Vue demo</title>
    </head>
    <body>
        <div id="app">
            <span v-if="is_user">
                <label for="username">用户账号</label> 《!--for:label和input绑定-->
                <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="is_user = !is_user">切换登录方式</button>
        </div>
        
    </body>
    <script src="vue.js"></script>
    <script>
        const app = new Vue({
            el: '#app',
            data:{
                is_user:true
            }
        })
    </script>
    </html>
    v-show

    v-show的用法和v-if非常相似,也用于决定一个元素是否渲染.

    1. v-show当条件为false时,仅仅是将元素的display属性设置为none而已

    2. v-if当条件为false时,元素不会存在于DOM中

    3. 既然如此,那如何选择?

      当需要在显示与隐藏之间切片很频繁时,使用v-show

      当只有一次切换时,通过使用v-if

    <!DOCTYPE html>
    <html>
    <head>
        <title>Vue demo</title>
    </head>
    <body>
        <div id="app">
            <h2 v-if="is_show">{{message}}</h2>
            <h2 v-show="is_show">{{message}}</h2>
        </div>
        
    </body>
    <script src="vue.js"></script>
    <script>
        const app = new Vue({
            el: '#app',
            data:{
                message:'hello world!',
                is_show: true
            }
        })
    </script>
    </html>

    六、循环遍历

    v-for遍历数组
    <!DOCTYPE html>
    <html lang="en">
    <head>
        <title>Vue demo</title>
    </head>
    <body>
        <div id="app">
            <ul>
                <li>hello {{names}}</li><br>
                <li v-for = "name in names">{{name}}</li><br>
                <li v-for = "(name,index) in names">{{index}}.{{name}}</li>
            </ul>
    
        </div>
        
    </body>
    <script src="vue.js"></script>
    <script>
        let app = new Vue({
            el: '#app',
            data: {
                names: ['zhangsan','lisi','wangwu','kang']
            }
        })
    </script>
    </html>
    v-for遍历对象
    <!DOCTYPE html>
    <html lang="en">
    <head>
        <title>Vue demo</title>
    </head>
    <body>
        <div id="app">
            <ul>
                <!--一个item是获取value-->
                <li v-for="item in info">{{item}}</li><br>
                <!--同时拿到key和value-->
                <li v-for="(value,key) in info">{{key}}: {{value}}</li><br>
                <!--获取key,value,index-->
                <li v-for="(value,key,index) in info">{{index}}.{{key}}: {{value}}</li>
            </ul>
    
        </div>
        
    </body>
    <script src="vue.js"></script>
    <script>
        let app = new Vue({
            el: '#app',
            data: {
                info: {
                    name: 'kang',
                    age: 18,
                    salary: 30000
                }
            }
        })
    </script>
    </html>
    组件的key属性

    官方推荐我们在使用v-for时,给对应的元素或组件添加上一个:key属性

    • 为什么需要这个key属性呢(了解)?

      ​ 这个其实和Vue的虚拟DOM的Diff算法有关系。

      ​ 这里我们借用React’s diff algorithm中的一张图来简单说明一下:

    • 当某一层有很多相同的节点时,也就是列表节点时,我们希望插入一个新的节点

      ​ 我们希望可以在B和C之间加一个F,Diff算法默认执行起来是这样的。

      ​ 即把C更新成F,D更新成C,E更新成D,最后再插入E,是不是很没有效率?

    • 所以我们需要使用key来给每个节点做一个唯一标识

      ​ Diff算法就可以正确的识别此节点

      ​ 找到正确的位置区插入新的节点。

    所以一句话,key的作用主要是为了高效的更新虚拟DOM

    检测数组更新

    因为Vue是响应式的,所以当数据发生变化时,Vue会自动检测数据变化,视图会发生对应的更新。

    Vue中包含了一组观察数组编译的方法,使用它们改变数组也会触发视图的更新。

    • push()

    • pop()

    • shift()

    • unshift()

    • splice()

    • sort()

    • reverse()

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <title>Vue demo</title>
    </head>
    <body>
        <div id="app">
            <ul>
                <li v-for="item in letters">{{item}}</li>
            </ul>
            <button @click="btnclick">点一下</button>
    
        </div>
        
    </body>
    <script src="vue.js"></script>
    <script>
        let app = new Vue({
            el: '#app',
            data: {
                letters: ['A','B','C','D','E']
            },
            methods: {
                btnclick(){
                    // //非响应式操作:通过索引添加元素
                    // this.letters[0] = 'X'
                    // //在最后插入
                    // this.letters.push('F','G')
                    // //在开头插入
                    // this.letters.unshift('XYZ','oo','yy')
                    // //删除最后一个元素
                    // this.letters.pop()
                    // //删除第一个元素
                    // this.letters.shift()
                    // //插入、删除、替换
                    // this.letters.splice(2,this.letters.length-2)  //从第二个元素开始,删除后面全部元素(第三个、第四个...最后一个)
                    // this.letters.splice(2,3,'m','n','l')  //替换CDE为mnl
                    // this.letters.splice(1,0,'x')  //在第一个后面插入charuyuansu
                    this.letters.splice(0,1,'x')  //在第一个元素前面插入x
                    //Vue.set(this.letters,1,9)  // Vue内置函数:set(要修改的对象,索引值,修改后的值)
                    // //排序
                    // this.letters.sort()
                    // //反转
                    // this.letters.reverse()
                    
                }
            }
        })
    </script>
    </html>

    七、阶段案例

    图书购物车

    index.html

    <!DOCTYPE html>
    <html lang="en">
    <head>
      <meta charset="UTF-8">
      <title>Title</title>
      <link rel="stylesheet" href="style.css">
    </head>
    <body>
    
    <div id="app">
      <div v-if="books.length">
        <table>
          <thead>
            <tr>
                <th></th>
                <th>书籍名称</th>
                <th>出版日期</th>
                <th>价格</th>
                <th>购买数量</th>
                <th>操作</th>
            </tr>
          </thead>
          <tbody>
            <tr v-for="(item, index) in books">
                <td>{{item.id}}</td>
                <td>{{item.name}}</td>
                <td>{{item.date}}</td>
                <td>{{item.price | showPrice}}</td>
                <td>
                    <button @click="decrement(index)" v-bind:disabled="item.count <= 1">-</button>
                    {{item.count}}
                    <button @click="increment(index)">+</button>
                </td>
                <td>
                    <button @click="removeHandle(index)">移除</button>
                </td>
            </tr>
          </tbody>
        </table>
        <h2>总价格: {{totalPrice | showPrice}}</h2>
      </div>
      <h2 v-else>购物车为空</h2>
    </div>
    
    <script src="../vue.js"></script>
    <script src="main.js"></script>
    </body>
    </html>

    main.js

    const app = new Vue({
      el: '#app',
      data: {
        books: [
          {
            id: 1,
            name: '《算法导论》',
            date: '2006-9',
            price: 85.00,
            count: 1
          },
          {
            id: 2,
            name: '《UNIX编程艺术》',
            date: '2006-2',
            price: 59.00,
            count: 1
          },
          {
            id: 3,
            name: '《编程珠玑》',
            date: '2008-10',
            price: 39.00,
            count: 1
          },
          {
            id: 4,
            name: '《代码大全》',
            date: '2006-3',
            price: 128.00,
            count: 1
          },
        ]
      },
      methods: {
        // getFinalPrice(price) {
        //   return '¥' + price.toFixed(2)
        // }
        increment(index) {
          this.books[index].count++
        },
        decrement(index) {
          this.books[index].count--
        },
        removeHandle(index) {
          this.books.splice(index, 1)
        }
      },
      computed: {
        totalPrice() {
          //写法1
          // let totalPrice = 0
          // for (let i = 0; i < this.books.length; i++) {
          //   totalPrice += this.books[i].price * this.books[i].count
          // }
          // return totalPrice
    
          //写法2
          return this.books.reduce(function(preValue, book){
            return preValue + book.price * book.count
          }, 0)
        }
      },
      filters: {
        showPrice(price) {
          return '¥' + price.toFixed(2)
        }
      }
    })

    style.css

    table {
      border: 1px solid #e9e9e9;
      border-collapse: collapse;
      border-spacing: 0;
    }
    
    th, td {
      padding: 8px 16px;
      border: 1px solid #e9e9e9;
      text-align: left;
    }
    
    th {
      background-color: #f7f7f7;
      color: #5c6b77;
      font-weight: 600;
    }

    八、javascript for补充

    books: [
          {
            id: 1,
            name: '《算法导论》',
            date: '2006-9',
            price: 85.00,
            count: 1
          },
          {
            id: 2,
            name: '《UNIX编程艺术》',
            date: '2006-2',
            price: 59.00,
            count: 1
          },
          {
            id: 3,
            name: '《编程珠玑》',
            date: '2008-10',
            price: 39.00,
            count: 1
          },
          {
            id: 4,
            name: '《代码大全》',
            date: '2006-3',
            price: 128.00,
            count: 1
          },
        ]
    
    for(let i of books){console.log(i.price)}

    九、v-model

    双向绑定 基本使用

    v-model绑定的变量,无论输入什么,赋值的时候都是当作字符串处理

    <html lang="en">
    <head>
        <title></title>
    </head>
    <body>
        <div id="app">
            <input type="text" v-model="message">
            {{message}}
        </div>
        
    </body>
    <script src="vue.js"></script>
    <script>
        let app = new Vue({
            el: '#app',
            data: {
                message: 'hello world!'
            }
        })
    </script>
    </html>
    > app.message
    <· "hello world!"
    
    可以看到在控制台修改app.message = 'good',页面上会随着改变,当然这是我们前面的内容mustache语法已经可以实现的效果
    > app.message = 'good'
    <· "good"
    > app.message
    <· "good"
    
    但是你在页面上的input里面输入一个内容,然后在控制台输出下app.message,会发现,Vue里面的数据也改变了,这样就形成了双向绑定,这里不同于mustache的能力
    > app.message
    <· "good night"

    v-model其实是下面这段代码的高级实现,如果不用v-model,下面这段代码也是一样的实现

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <title></title>
    </head>
    <body>
        <div id="app">
            <!--<input type="text" v-model="message" @input="valueChange">-->
            <!--或者一般我们更常用这种写法:不写methods,这样写-->
            <input type="text" :value="message" @input="message = $event.target.value">
            <h2>{{message}}</h2>
        </div>
        
    </body>
    <script src="vue.js"></script>
    <script>
        let app = new Vue({
            el: '#app',
            data: {
                message: 'hello world!'
            },
            //methods: {
                //valueChange (event) {
                    //this.message = event.target.value;
                //}
           //}
        })
    </script>
    </html>
    原理

    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">
    radio v-model结合radio的使用
    <!DOCTYPE html>
    <html lang="en">
    <head>
        <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>
            <h2>你选择的性别是: {{sex}}</h2>
        </div>
        
    </body>
    <script src="vue.js"></script>
    <script>
        let app = new Vue({
            el: '#app',
            data: {
                sex: '男'  //默认选择男
            },
        })
    </script>
    </html>

    加name是为了让两个radio互斥,要么男要么女

    <input type="radio" id="male" name="sex" value="男">男
    <input type="radio" id="female" value="女" v-model="sex">女

    如果我们用了v-model,就不需要name,他们也已经是互斥

    <input type="radio" id="male"value="男" v-model="sex">男
    checkbox v-model结合checkbox使用

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

    • 单个勾选框:

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

    • 多个复选框:

      当是多个复选框时,因为可以选中多个,所以对应的data中属性是一个数组

      当选中某一个时,就会将input的value添加到数组中。

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <title></title>
    </head>
    <body>
        <div id="app">
            <!--单选框-->
            <!-- <label for="licence">  label的好处是点文字也可以选中 -->
                <!-- <input type="checkbox" id="licence" v-model="licence">同意协议 -->
            <!-- </label> -->
            <!-- <h2>你选择的是: {{licence}}</h2> -->
            <!-- <button :disabled="!licence">同意协议,进行下一步</button> -->
            <br><br><br>
            <!--多选框-->
            <input type="checkbox" value="篮球" v-model="likes">篮球<br>
            <input type="checkbox" value="足球" v-model="likes">足球<br>
            <input type="checkbox" value="乒乓球" v-model="likes">乒乓球<br>
            <input type="checkbox" value="羽毛球" v-model="likes">羽毛球
            <h2>你的爱好是: {{likes}}</h2>
            
        </div>
        
    </body>
    <script src="vue.js"></script>
    <script>
        let app = new Vue({
            el: '#app',
            data: {
                licence: false,
                likes: []
            },
        })
    </script>
    </html>
    select v-model结合select的使用

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

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

    • 多选:可以选中多个值。
      v-model绑定的是一个数组。
      当选中多个值时,就会将选中的option对应的value添加到数组fruits中

    <!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.选择多个: multiple属性可以选择多个值-->
      <select name="abc" v-model="fruits" multiple>
        <option value="苹果">苹果</option>
        <option value="香蕉">香蕉</option>
        <option value="榴莲">榴莲</option>
        <option value="葡萄">葡萄</option>
      </select>
      <h2>您选择的水果是: {{fruits}}</h2>
    </div>
    </body>
    <script src="vue.js"></script>
    <script>
      const app = new Vue({
        el: '#app',
        data: {
          message: '你好啊',
          fruit: '香蕉',
          fruits: []
        }
      })
    </script>
    </html>
    值绑定 v-bind结合input的使用

    通过v-bind:value,动态的给value赋值,以下动态绑定有3处(:for,:value,:id),还有一处mustache绑定({{item}})

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <title></title>
    </head>
    <body>
        <div id="app">
            <input type="checkbox" value="篮球" v-model="likes">篮球<br>
            <input type="checkbox" value="足球" v-model="likes">足球<br>
            <input type="checkbox" value="乒乓球" v-model="likes">乒乓球<br>
            <input type="checkbox" value="羽毛球" v-model="likes">羽毛球
    
            <h2>你的爱好是: {{likes}}</h2>
            
            <label v-for="item in origin_likes" :for="item">  <!--遍历origin_likes把每项存到likes数组-->
                <input type="checkbox" :value="item" :id="item" v-model="likes">{{item}}
            </label>
        </div>
        
    </body>
    <script src="vue.js"></script>
    <script>
        let app = new Vue({
            el: '#app',
            data: {
                likes: [],
                origin_likes: ["篮球","足球","乒乓球","羽毛球"]
            },
        })
    </script>
    </html>
    修饰符

    lazy修饰符:
    默认情况下,v-model默认是在input事件中同步输入框的数据的,也就是说,一旦有数据发生改变对应的data 中的数据就会自动发生改变。lazy修饰符可以让数据在失去焦点或者回车时才会更新
    number修饰符:
    默认情况下,在输入框中无论我们输入的是字母还是数字,都会被当做字符串类型进行处理,但是如果我们希 望处理的是数字类型,那么最好直接将内容当做数字处理,number修饰符可以让在输入框中输入的内容自动转成数字类型
    trim修饰符:
    如果输入的内容首尾有很多空格,通常我们希望将其去除,trim修饰符可以过滤掉内容左右两边的空格

    <!DOCTYPE html>
    <html lang="en">
    <head>
      <meta charset="UTF-8">
      <title>Title</title>
    </head>
    <body>
    
    <div id="app">
      <!--1.修饰符: lazy,让数据在失去焦点或者回车时才会更新data中对应的变量-->
      <input type="text" v-model.lazy="message">
      <h2>{{message}}</h2>
    
    
      <!--2.修饰符: number,让在输入框中输入的内容自动转成数字类型-->
      <input type="number" v-model.number="age">
      <h2>{{age}}-{{typeof age}}</h2>  <!--typeof age:获取age的类型-->
    
      <!--3.修饰符: trim,过滤掉内容左右两边的空格-->
      <input type="text" v-model.trim="name">
      <h2>您输入的名字:{{name}}</h2>
    </div>
    
    <script src="vue.js"></script>
    <script>
      const app = new Vue({
        el: '#app',
        data: {
          message: '你好啊',
          age: 0,
          name: ''
        }
      })
    
      var age = 0
      age = '1111'
      age = '222'
    </script>
    
    </body>
    </html>
  • 相关阅读:
    浴谷夏令营2017.8.1数论的整理
    BZOJ1483: [HNOI2009]梦幻布丁
    NOIP2014-11-3模拟赛
    BZOJ3884: 上帝与集合的正确用法
    BZOJ4869: [Shoi2017]相逢是问候
    计蒜客NOIP2017提高组模拟赛(三)day1
    NOIP2014-9-6模拟赛
    NOIP2014-7-7模拟赛
    zoj Little Keng(快速幂)
    多校Key Set (快速幂)
  • 原文地址:https://www.cnblogs.com/kknote/p/16103467.html
Copyright © 2020-2023  润新知