Vue.js的概念

什么是Vue.js

Vue.js 是前端的主流框架之一,和 Angular.js、React.js 一起,并称为前端三大主流框架
Vue.js 是一套构建用户界面的框架,只关注视图层,他不仅易于上手,还便于与第三方库或既有项目整合。

框架和库的区别

  • 框架:是一套完整的解决方案;对项目的侵入性较大,项目如果需要更换框架,则需要重新架构整个项目 。
  • 库(插件):提供某一个小功能,对项目的侵入性较小,如果某个库无法完成某些需求,可以很容易切换到其他库实现需求

Node(后端)中的 MVC 与前端中的 MVVM 之间的区别

  • MVC 是后端的分层开发概念
  • MVVM是前端视图层的概念,主要关注于 视图层分离,也就是说:MVVM吧前端的视图层,分为了三部分 Model, View, VM ViewModel,其中 VM是 MVVM思想的核心:因为VM是M和V之间的调度者
  • M保存的是每个页面中单独的数据
  • V 就是每个页面中的HTML结构
  • VM 是一个调度者,分割了M和V 使M和V互相不能调用。当V层想要获取后保存数据的时候,都要由VM做中间的处理。

Vue 代码

Vue.js基本代码

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

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
    <!-- 1. 导入vue的包 -->
    <script src="lib/vue.js"></script>
</head>

<body>
    <!-- 将来 new 的 vue 实例,会控制这个 元素中的所有内容 -->
    <!-- Vue 实例所控制的这个元素区域,就是 V -->
    <div id="app">
        <p>{{ msg }}</p>
    </div>

    <script>
        //2.创建一个Vue的实例
        //当导入包之后,在浏览器的内存中,就多了 Vue 构造函数
        // 注意:new 出来的这个 VM 对象 就是 MVVM中的 VM调度者
        var vm = new Vue({
            el: '#app', //表示,当前 new 的这个 Vue实例,要控制页面上的哪个区域
            // 这里的 data 就是 MVVM中的 M 专门用来保存 每个页面的数据
            data: { //data 属性中,存放的是 el 中要用的数据
                msg: '欢迎学习vue' //通过 vue 提供的指令,很方便的就能把数据渲染到页面上,程序员不再手动操作DOM元素了【前端的vue之类的框架,不提倡手动操作DOM元素了】
            }
        })
    </script>
</body>

</html>

v-cloak、v-text、v-html、v-bind和v-on

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

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

</head>

<body>
    <div id="app">
        <!-- 使用 v-cloak 能够解决 插值表达式闪烁问题 -->
        <p v-cloak>{{ msg }}</p>
        <h4 v-text="msg"></h4>
        <!-- 默认 v-text 是没有闪烁问题的 -->
        <!-- v-text 会覆盖元素中原本的内容,但是 插值表达式 只会替换自己的占位符,不会把整个元素的内容清空 -->
        <div>{{ msg2 }}</div>
        <div v-text="msg2"></div>
        <div v-html="msg2">121212</div>

        <!-- v-bind: 是 Vue 中,提供的用于绑定属性的指令 -->
        <!-- 注意:v-bind: 指令可以简写为 :要绑定的属性 -->
        <!-- v-bind 中,可以写合法的JS表达式 -->
        <!-- Vue 中提供了 v-on: 事件绑定机制 -->
        <!-- <input type="button" value="按钮" v-bind:title="mytitle + '123'" v-on:click="alert('hello')"> -->



        <input type="button" value="按钮" v-on:click="show">
    </div>

    <script src="lib/vue.js"></script>
    <script>
        var vm = new Vue({
            el: '#app',
            data: {
                msg: '123',
                msg2: '<h1>我是一个H1</h1>',
                mytitle: '这是一个自己定义的title'
            },
            methods: { //这个 methods属性中定义了当前 vue实例所有可用的方法
                show: function() {
                    alert('hello');
                }
            }
        })


        // document.getElementById('btn').onclick = function() {
        //     alert('Hello');
        // }
    </script>
</body>

</html>
  1. 如何定义一个基本的vue代码结构
  2. 插值表达式和 v-text的区别
  3. v-cloak
  4. v-html
  5. v-bind vue提供的属性绑定机制 缩写是 :
  6. v-on vue提供的事件绑定机制 缩写是 @

案例:跑马灯效果制作

案例分析:

  1. 给 浪起来 按钮,绑定一个点击事件 v-on @
  2. 在按钮的事件处理函数中,写相关的业务逻辑代码:拿到 msg字符串,然后 调用字符串的 substring 来进行字符串的截取操作,把 第一个字符截取出来,放到最后一个位置即可
  3. 为了实现点击按钮,自动截取的功能,需要把第2步骤中的代码放入一个定时器中去。
  4. 代码:
<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
    <script src="lib/vue.js"></script>
</head>

<body>
    <div id="app">
        <input type="button" value="浪起来" @click="lang">
        <input type="button" value="低调" @click="stop">
        <h4>{{ msg }}</h4>
    </div>

    <script>
        //注意:在VM实例中,如果想要调用 data 上的数据,或者 想要调用 methods 中的方法,必须通过 this 数据属性名,或者 this.方法名 来进行访问,这里的 this 表示 new 的 VM实例对象
        var vm = new Vue({
            el: '#app',
            data: {
                msg: '孟鹤堂,周九良~~!',
                intervalId: null //在data 上定义 定时器id
            },
            methods: {
                lang() {
                    // console.log(this.msg);

                    if (this.intervalId != null) return;

                    this.intervalId = setInterval(() => {
                            //获取到头的第一个字符
                            var start = this.msg.substring(0, 1);
                            //获取到 后面的所有字符
                            var end = this.msg.substring(1);
                            //重新拼接得到新的字符串,并复制给this.msg
                            this.msg = end + start;

                        }, 400)
                        //注意: vm实例,会监听自己身上 data 中所有数据的变化,只要数据发生改变,就自动把最新数据,从data 上同步到页面中去

                },
                stop() {
                    clearInterval(this.intervalId);
                    //每当清除了定时器之后,需要重新把this.intervalId = null;
                    this.intervalId = null;
                }
            }
        })


    </script>
</body>

</html>

事件修饰符

  • stop 阻止冒泡
  • prevent 阻止默认事件
  • capture 添加事件侦听器时使用事件捕获模式
  • self 只当事件在该元素本身(比如不是子元素)触发时触发回调
  • once 事件只触发一次
<!-- 使用 .stop 来阻止冒泡 -->
        <!-- <div class="inner" @click="divHandler">
            <input type="button" value="戳他" @click.stop="btnHandler">
        </div> -->


        <!-- 使用 .prevent 阻止默认行为 -->
        <!-- <a href="http://www.baidu.com" @click.prevent="linkClick">有问题去百度</a> -->


        <!-- 使用 .capture 实现捕获触发事件的机制
        <div class="inner" @click.capture="divHandler">
            <input type="button" value="戳他" @click="btnHandler">
        </div> -->

        <!-- 使用 .self 实现只有点击当前元素的时候,才会触发机制
        <div class="inner" @click.self="divHandler">
            <input type="button" value="戳他" @click="btnHandler">
        </div> -->

        <!-- 使用 .once 只触发一次事件处理函数
        <a href="http://www.baidu.com" @click.prevent.once="linkClick">有问题去百度</a> -->

v-model 和 双向数据绑定

简易计算器案例

<body>
    <div id="app">
        <input type="text" v-model="n1">
        <select v-model="opt">
            <option value="0">+</option>
            <option value="1">-</option>
            <option value="2">×</option>
            <option value="3">÷</option>
        </select>
        <input type="text" v-model="n2">
        <input type="button" value="=" @click="calc">
        <input type="text" v-model="result">
    </div>


    <script>
        var vm = new Vue({
            el: '#app',
            data: {
                n1: 0,
                n2: 0,
                opt: '0',
                result: 0
            },
            methods: {
                calc() {
                    switch (this.opt) {
                        case '0':
                            this.result = parseInt(this.n1) + parseInt(this.n2);
                            break;
                        case '1':
                            this.result = parseInt(this.n1) - parseInt(this.n2);
                            break;
                        case '2':
                            this.result = parseInt(this.n1) * parseInt(this.n2);
                            break;
                        case '3':
                            this.result = parseInt(this.n1) / parseInt(this.n2);
                            break;

                        default:
                            break;
                    }
                }
            }
        })
    </script>
</body>

在vue中使用样式

使用class样式

  1. 数组
    <h1 :class="['red', 'thin']"></h1>
  2. 数组中使用三元表达式
    <h1 :class="['red','thin',isactive?'active':'']"></h1>
  3. 数组中嵌套对象
    <h1 :class="['red','thin',isactive?'active':'']"></h1>
  4. 直接使用对象
    <h1 :class="{red:true, italic:true, active:true, thin:true}"></h1>
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
    <script src="lib/vue.js"></script>
    <style>
        .red {
            color: red;
        }
        
        .thin {
            font-weight: 200;
        }
        
        .italic {
            font-style: italic;
        }
        
        .active {
            letter-spacing: 0.5em;
        }
    </style>
</head>

<body>
    <div id="app">
        <!-- <h1 class="red thin">这是一个H1,这是一个H1</h1> -->


        <!-- 第一种使用方式,直接传递一个数组,注意:这里的 class 需要使用 v-bind 做数据绑定 -->
        <!-- <h1 :class="['thin', 'italic']">这是一个H1,这是一个H1</h1> -->


        <!-- 在数组中使用三元表达式 -->
        <!-- <h1 :class="['thin', 'italic',flag?'active':'']">这是一个H1,这是一个H1</h1> -->


        <!-- 在数组中使用 对象来代替三元表达式,提高代码的可读性 -->
        <!-- <h1 :class="['thin', 'italic',{'active':flag}]">这是一个H1,这是一个H1</h1> -->


        <!-- 在为 class 使用 v-bind 绑定对象的时候,对象的属性是类名,由于对象的属性可用引号,也可以不带引号,所以这里不写引号,属性的值 是一个标识符 -->
        <h1 :class="classobj">这是一个H1,这是一个H1</h1>
    </div>
    <script>
        var vm = new Vue({
            el: '#app',
            data: {
                flag: true,
                classobj: {
                    red: true,
                    thin: true,
                    italic: false,
                    active: false
                }
            },
            methods: {}
        })
    </script>
</body>

使用内联样式

  1. 直接在元素上通过 :style 的形式,书写样式对象
  2. 将样式对象,定义到data中,并直接引用到 :style 中
  3. 在 :style 中通过数组,引用多个 data 上的样式对象
<body>
    <div id="app">
        <!-- 对象就是无序赋值对的集合 -->
        <h1 :style="[styleObj1,styleObj2]">这是一个H1</h1>
    </div>

    <script>
        var vm = new Vue({
            el: '#app',
            data: {
                styleObj1: {
                    color: 'red',
                    'font-weight': '200'
                },
                styleObj2: {
                    'font-style': 'italic'
                }

            },
            methods: {},
        })
    </script>
</body>

Vue指令之 v-for 和 key 属性

迭代数组

  1. 迭代普通数组
<body>
    <div id="app">
        <!-- <p v-for="item in list">{{item}}</p> -->
        <p v-for="(item,i) in list">索引值:{{i}} --- 每一项:{{item}}</p>
    </div>
    <script>
        var vm = new Vue({
            el: '#app',
            data: {
                list: [1, 2, 3, 4, 5, 6]
            },
            methods: {

            },
        })
    </script>
</body>
  1. 迭代对象数组
<body>
    <div id="app">
        <p v-for="(user,i) in list">索引:{{i}} --- ID:{{user.id}} --- 名字:{{user.name}}</p>
    </div>
    <script>
        var vm = new Vue({
            el: '#app',
            data: {
                list: [{
                    id: 1,
                    name: 'zs1'
                }, {
                    id: 2,
                    name: 'zs2'
                }, {
                    id: 3,
                    name: 'zs3'
                }, {
                    id: 4,
                    name: 'zs4'
                }, {
                    id: 5,
                    name: 'zs5'
                }, ]
            },
            methods: {

            },
        })
    </script>
</body>

迭代对象中的属性

<div id="app">
    <!-- 注意:在遍历对象身上的键值对的时候,出了 有 val  key  ,在第三个位置还有一个 索引 -->
    <p v-for="(val,key,i) in user">值:{{val}} --- 键:{{key}} --- 索引:{{i}}</p>
</div>
<script>
    var vm = new Vue({
        el: '#app',
        data: {
            user: {
                id: 1,
                name: 'tony',
                gender: '男'
            }
        },
        methods: {

        },
    })
</script>

注意:当在组件中使用 v-for 时,key 是必须写的

<div id="app">

    <div>
        <label for="">Id:
            <input type="text" v-model="id">
        </label>
        <label for="">Name:
            <input type="text" v-model="name">
        </label>

        <input type="button" value="添加" @click="add">
    </div>

    <!-- 注意: v-for循环的时候,key 属性只能使用 number获取string -->
    <!-- 注意:key 在使用的时候,必须使用 v-bind 属性绑定的形式,指定 key 的值 -->
    <!-- 在组件中,使用v-for循环的时候,或者在一些特殊情况中,如果 v-for 有问题,必须 在使用 v-for 的同时,指定唯一的字符串/数字,类型:key 值 -->
    <p v-for="item in list" :key="item.id">
        <input type="checkbox">{{item.id}} --- {{item.name}}
    </p>
</div>
<script>
    var vm = new Vue({
        el: '#app',
        data: {
            id: '',
            name: '',
            list: [{
                id: 1,
                name: '李斯'
            }, {
                id: 2,
                name: '嬴政'
            }, {
                id: 3,
                name: '赵高'
            }, {
                id: 4,
                name: '韩非'
            }, {
                id: 5,
                name: '荀子'
            }]
        },
        methods: {
            add() { //添加方法
                // this.list.push({
                //     id: this.id,
                //     name: this.name
                // })
                this.list.unshift({
                    id: this.id,
                    name: this.name
                })
            }
        },
    })
</script>

迭代数字


这是第 {{count}} 次循环


Vue指令之 v-if 和 v-show

v-if 的特点:每次都会重新删除或创建元素
v-show 的特点:每次不会重新进行DOM的删除和创建,只是切换了元素的 display:none 样式
v-if 有较高的切换性能消耗
v-show 有较高的初始渲染消耗
如果元素涉及到频繁的切换,最好不要使用v-if
如果元素可能永远也不会被显示出来被用户看到,则推荐使用 v-if