基本使用

使用Vue的步骤

  1. 需要提供标签用于填充数据
  2. 引入VUE.js文件
  3. 可以使用vue的语法做功能
  4. 把vue提供的数据填充到标签里
<body>
    <div id="app">
        <!-- 插值表达式 可以做简单的运算 -->
        <h1>{{title}}</h1>
    </div>
    <script src="../js/vue.js"></script>
    <script>
        new Vue({
            // 元素挂载的位置,可以是CSS选择器或者DOM元素
            el: '#app',
            // 模型数据
            data: {
                title: 'xiaokang'
            }
        })
    </script>
</body>

image-20201101085009406

指令

v-cloak

https://cn.vuejs.org/v2/api/#v-cloak

作用:用于解决当vue没有渲染时显示两个大括号等问题。

指令用法:

  1. 提供样式

    <style>
        [v-cloak] {
            display: none;
        }
    </style>
  2. 在插值表达式所在的标签中添加v-cloak指令

    <h1 v-cloak>{{title}}</h1>

数据绑定

将数据填充到标签中。

  • v-text

    此指令没有闪动问题,插入内容为纯文本内容

  • v-html

    填充HTML片段,存在安全问题。

  • v-pre

    显示原始信息,跳过编译过程

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>

<body>
    <div id="app">
        <!-- 插值表达式 可以做简单的运算 -->
        <h1>{{title}}</h1>
        <div v-text='text'></div>
        <div v-html='html'></div>
        <div v-pre='pre'>{{pre}}</div>
    </div>
    <script src="../js/vue.js"></script>
    <script>
        new Vue({
            // 元素挂载的位置,可以是CSS选择器或者DOM元素
            el: '#app',
            // 模型数据
            data: {
                title: 'xiaokang',
                text: 'v-text 纯文本内容',
                html: '<h1>v-html 填充html</h1>',
                pre: 'v-pre显示原始信息,跳过编译过程'
            }
        })
    </script>
</body>

</html>

image-20201101090556170

数据响应式

v-once指令可以使数据只渲染一次,即数据不再是响应式。

<body>
    <div id="app">
        <!-- 插值表达式 可以做简单的运算 -->
        <h1>{{title}}</h1>
        <h1 v-once>{{msg}}</h1>
    </div>
    <script src="../js/vue.js"></script>
    <script>
        let app = new Vue({
            // 元素挂载的位置,可以是CSS选择器或者DOM元素
            el: '#app',
            // 模型数据
            data: {
                title: 'xiaokang',
                msg: 'once只渲染一次',
            }
        })
    </script>
</body>

image-20201101091330644

双向数据绑定

双向数据绑定使用v-model命令。

4b52bf92-ca42-42b1-a3cb-ba67c14292e0

<body>
    <div id="app">
        <!-- 插值表达式 可以做简单的运算 -->
        <p>{{msg}}</p>
        <input type="text" v-model='msg'>
    </div>
    <script src="../js/vue.js"></script>
    <script>
        let app = new Vue({
            // 元素挂载的位置,可以是CSS选择器或者DOM元素
            el: '#app',
            // 模型数据
            data: {
                msg: 'once只渲染一次',
            }
        })
    </script>
</body>

原理:通过v-bind绑定属性,v-on:input绑定输入事件,以此改变属性的值。

事件绑定

https://cn.vuejs.org/v2/guide/events.html

事件绑定通过v-on指令,v-on指令可以简写为@,例如:

<button @click='num++'>点击</button>

835c22b8-f2b4-486d-8ba8-ca205ae06413

<body>
    <div id="app">
        <div>{{num}}</div>
        <button v-on:click='add()'>加1</button>
        <button v-on:click='min()'>减1</button>
    </div>
    <script src="../js/vue.js"></script>
    <script>
        let app = new Vue({
            // 元素挂载的位置,可以是CSS选择器或者DOM元素
            el: '#app',
            // 模型数据
            data: {
                num: 0,
            },
            // 定义方法,用于事件绑定
            methods: {
                add() {
                    this.num++
                },
                min() {
                    this.num--
                }
            },
        })
    </script>
</body>

参数传递

  1. 直接调用函数,不传递参数

    <button v-on:click="fn">test</button>

    此种情况在methods中接受的第一个参数为事件对象。

    methods: {
        fn(e) {
            console.log(e);
        }
    },

    image-20201031144142085

  2. 传递参数

    <button v-on:click="fn(1,2,3,$event)">按钮 - {{title}}</button>

    此时无论传递多少个参数,传递事件对象时必须使用$event名称且只能放在最后一个位置。

    methods: {
        fn(a, b, c, d) {
            console.log("a: ", a);
            console.log("b: ", b);
            console.log("c: ", c);
            console.log("d: ", d);
        }
    }

    image-20201031144401317

事件修饰符

  • .stop

    阻止事件继续传播

  • .prevent

    阻止默认事件

  • .capture

    是否是以捕获模式

  • .self

    是否是自己触发的

  • .once

    只触发一次

  • .passive

<!-- 阻止单击事件继续传播 -->
<a v-on:click.stop="doThis"></a>

<!-- 提交事件不再重载页面 -->
<form v-on:submit.prevent="onSubmit"></form>

<!-- 修饰符可以串联 -->
<a v-on:click.stop.prevent="doThat"></a>

<!-- 只有修饰符 -->
<form v-on:submit.prevent></form>

<!-- 添加事件监听器时使用事件捕获模式 -->
<!-- 即内部元素触发的事件先在此处理,然后才交由内部元素进行处理 -->
<div v-on:click.capture="doThis">...</div>

<!-- 只当在 event.target 是当前元素自身时触发处理函数 -->
<!-- 即事件不是从内部元素触发的 -->
<div v-on:click.self="doThat">...</div>

使用修饰符时,顺序很重要;相应的代码会以同样的顺序产生。因此,用 v-on:click.prevent.self 会阻止所有的点击,而 v-on:click.self.prevent 只会阻止对元素自身的点击。

b1fe6135-e483-4fae-9b00-6235b15151d2

<body>
    <div id="app">
        <a href="https://xiaokang.me" target="_blank" @click.prevent='fn'>小康</a>
    </div>
    <script src="../js/vue.js"></script>
    <script>
        let app = new Vue({
            // 元素挂载的位置,可以是CSS选择器或者DOM元素
            el: '#app',
            // 定义方法,用于事件绑定
            methods: {
                fn() {
                    console.log('点击a标签了。');
                }
            },
        })
    </script>
</body>

按键修饰符

按键修饰符

00f7b330-b079-42dd-ab20-153f84df8b3c

<body>
    <div id="app">
        <input type="text" v-model='username' @keyup.delete='fn'>
        <input type="text" v-model='password' @keyup.enter='fn2'>
    </div>
    <script src="../js/vue.js"></script>
    <script>
        let app = new Vue({
            // 元素挂载的位置,可以是CSS选择器或者DOM元素
            el: '#app',
            data: {
                username: '',
                password: ''
            },
            // 定义方法,用于事件绑定
            methods: {
                fn() {
                    console.log('按下了delete键');
                    this.username = ''
                },
                fn2() {
                    console.log('按下了回车键');
                }
            },
        })
    </script>
</body>

虽然VUE提供了自定义按键修饰符的方法,但此方法已经被废弃。keyCode

案例:简单计算器

image-20201101100152302

<body>
    <div id="app">
        数值A: <input type="text" v-model='a'><br>
        数值B: <input type="text" v-model='b'><br>
        <button @click='fn'>计算</button>
        <p>计算结果:{{result}}</p>
    </div>
    <script src="../js/vue.js"></script>
    <script>
        let app = new Vue({
            // 元素挂载的位置,可以是CSS选择器或者DOM元素
            el: '#app',
            data: {
                a: '',
                b: '',
                result: ''
            },
            // 定义方法,用于事件绑定
            methods: {
                fn() {
                    this.result = parseInt(this.a) + parseInt(this.b)
                }
            },
        })
    </script>
</body>

属性绑定

属性绑定通过v-bind实现,这个属性也可以存在两种写法:全写与简写

<a v-bind:href="href">{{href}}</a>
<a :href="href">{{href}}</a>

例如:通过数据动态控制a标签中href属性的值。

c827dd89-21d6-420e-addd-a4123a9383c3

<body>
    <div id="app">
        <a v-bind:href="href">{{href}}</a>
        <button @click='fn'>切换</button>
    </div>
    <script src="../js/vue.js"></script>
    <script>
        let app = new Vue({
            // 元素挂载的位置,可以是CSS选择器或者DOM元素
            el: '#app',
            data: {
                href: 'https://xiaokang.me'
            },
            // 定义方法,用于事件绑定
            methods: {
                fn() {
                    this.href = 'https://www.antmoe.com'
                }
            },
        })
    </script>
</body>

样式绑定

<!-- 左边为class名,右边为属性 -->
<div :class='{active:isActive}'></div>
<div :class='[activeClass,errorClass]'></div>
<head>
    <style>
        .active {
            border: 1px solid red;
            width: 100px;
            height: 100px;
        }
    </style>
</head>

<body>
    <div id="app">
        <!-- 左边为class名,右边为属性 -->
        <div :class='{active:isActive}'></div>
    </div>
    <script src="../js/vue.js"></script>
    <script>
        let app = new Vue({
            // 元素挂载的位置,可以是CSS选择器或者DOM元素
            el: '#app',
            data: {
                isActive: true
            },
        })
    </script>
</body>

image-20201101103818361

通过isActive属性控制类是否生效

通过数组方式添加类名:

<div :class='[activeClass,errorClass]'></div>
<script>
    let app = new Vue({
        // 元素挂载的位置,可以是CSS选择器或者DOM元素
        el: '#app',
        data: {
            activeClass: 'active',
            errorClass: 'error'
        },
    })
</script>

在数组中同样可以添加对象,即两者结合使用

<div :class='[activeClass,errorClass,{test:"isTest"}]'></div>

或者也可以通过如下方式:

<div :class='myClass'></div>
<script>
    let app = new Vue({
        // 元素挂载的位置,可以是CSS选择器或者DOM元素
        el: '#app',
        data: {
            myClass:['activeClass','errorClass',{test:"isTest"}]
        },
    })
</script>

关于样式绑定,如果元素存在默认的class,那么默认class会被保留

通过style绑定样式

<body>
    <div id="app">
        <div :style='{border:boderStyle,height:heightStyle,width:widthStyle}'></div>
    </div>
    <script src="../js/vue.js"></script>
    <script>
        let app = new Vue({
            // 元素挂载的位置,可以是CSS选择器或者DOM元素
            el: '#app',
            data: {
                boderStyle: '1px solid red',
                heightStyle: '100px',
                widthStyle: '100px'
            },
        })
    </script>
</body>

关于样式也可以通过对象的方式

<div :style='objStyle'></div>
let app = new Vue({
    // 元素挂载的位置,可以是CSS选择器或者DOM元素
    el: '#app',
    data: {
        objStyle: {
            border: '1px solid red',
            height: '100px',
            width: '100px',
        }
    },
})

直接操作值就会改变样式。

分支循环

<div v-if='score>=90'>优秀</div>
<div v-else-if='score<90&&score>=80'>良好</div>
<div v-else='score<90&&score>=80'>垃圾</div>

image-20201101111047174

此指令只会渲染一个div,然而v-show会渲染多个div,即控制display来决定是否显示。

<div v-show='flag'>测试</div>

image-20201101111223710

<body>
    <div id="app">
        <div v-if='score>=90'>优秀</div>
        <div v-else-if='score<90&&score>=80'>良好</div>
        <div v-else='score<90&&score>=80'>垃圾</div>
        <div v-show='flag'>测试</div>
    </div>
    <script src="../js/vue.js"></script>
    <script>
        let app = new Vue({
            // 元素挂载的位置,可以是CSS选择器或者DOM元素
            el: '#app',
            data: {
                score: 99,
                flag: false
            },

        })
    </script>
</body>

循环结构

<body>
    <div id="app">
        <ul>
            <li v-for='(item,index) of fruits'>{{index}}---{{item}}</li>
        </ul>
    </div>
    <script src="../js/vue.js"></script>
    <script>
        let app = new Vue({
            // 元素挂载的位置,可以是CSS选择器或者DOM元素
            el: '#app',
            data: {
                fruits: ['apple', 'orange', 'banana']
            },

        })
    </script>
</body>

image-20201101111803212

为了保证没一条记录的唯一性,最好通过唯一值为每一个元素绑定key属性。

分支与循环结合使用

<body>
    <div id="app">
        <ul>
            <li v-if='flag' v-for='item of obj'>
                {{item.id}}---{{item.name}}---{{item.age}}
            </li>
        </ul>
    </div>
    <script src="../js/vue.js"></script>
    <script>
        let app = new Vue({
            // 元素挂载的位置,可以是CSS选择器或者DOM元素
            el: '#app',
            data: {
                obj: [
                    {
                        id: 1,
                        name: 'a',
                        age: 12
                    },
                    {
                        id: 2,
                        name: 'b',
                        age: 13
                    },
                    {
                        id: 3,
                        name: 'c',
                        age: 14
                    },
                ],
                flag: false
            },

        })
    </script>
</body>

image-20201101113239670

案例:Tab选项卡

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <title>Document</title>
    <style type="text/css">
        .tab ul {
            overflow: hidden;
            padding: 0;
            margin: 0;
        }

        .tab ul li {
            box-sizing: border-box;
            padding: 0;
            float: left;
            width: 100px;
            height: 45px;
            line-height: 45px;
            list-style: none;
            text-align: center;
            border-top: 1px solid blue;
            border-right: 1px solid blue;
            cursor
        }

        .tab ul li:first-child {
            border-left: 1px solid blue;
        }

        .tab ul li.active {
            background-color: orange;
        }

        .tab div {
            width: 500px;
            height: 300px;
            display: none;
            text-align: center;
            font-size: 30px;
            line-height: 300px;
            border: 1px solid blue;
            border-top: 0px;
        }

        .tab div.current {
            display: block;
        }
    </style>
</head>

<body>
    <div id="app">
        <div class="tab">
            <ul>
                <li v-on:click='change(index)' :class='currentIndex==index?"active":""' :key='item.id'
                    v-for='(item,index) in list'>{{item.title}}</li>
            </ul>
            <div :class='currentIndex==index?"current":""' :key='item.id' v-for='(item, index) in list'>
                <img :src="item.path">
            </div>
        </div>
    </div>
    <script type="text/javascript" src="../js/vue.js"></script>
    <script type="text/javascript">
        /*
          
        */
        var vm = new Vue({
            el: '#app',
            data: {
                currentIndex: 0, // 选项卡当前的索引
                list: [{
                    id: 1,
                    title: '第一个',
                    path: 'https://cdn.jsdelivr.net/gh/blogimg/picbed@master/2020/04/13/5005109d1aa2ffd28984c2b02b8cbfbe.png'
                }, {
                    id: 2,
                    title: '第二个',
                    path: 'https://cdn.jsdelivr.net/gh/blogimg/picbed@master/2020/04/13/163a2ade4361d1ed705ed523091af67e.png'
                }, {
                    id: 3,
                    title: '第三个',
                    path: 'https://cdn.jsdelivr.net/gh/blogimg/picbed@master/2020/04/13/d8ccc2fd66f340c46b8fb98ed7148223.png'
                }]
            },
            methods: {
                change: function (index) {
                    // 在这里实现选项卡切换操作:本质就是操作类名
                    // 如何操作类名?就是通过currentIndex
                    this.currentIndex = index;
                }
            }
        });
    </script>
</body>

</html>

3b37e63f-fb69-4d20-a3be-5e8f1655772b

案例:TODO

DEMO:https://tzk.acs.pw/2020-11/01/Stable/todos.html