(一)学习Vue - 数据驱动界面改变

480 阅读10分钟

简介

MVVM设计模式:

  • model: 数据模型(处理数据的业务逻辑)
  • view: 视图(展现数据,与用户交互)
  • view-model: 数据模型与视图的桥梁

Vue中的MVVM划分:

  • model: 实例对象中的数据
  • view: 被控制的区域
  • view-model: Vue的实例对象

Vue中的数据单向传递的过程:

  • model --> view-model --> view

Vue数据的双向绑定:

  • 使用v-model来绑定数据
  • 修改元素内容数据,model中的数据也随之改变
  • 仅支持双向绑定的三个标签:
    • input
    • textarea
    • select

指令

什么是指令?

  • 指令就是Vue里自定义的一些属性,这些自定义的属性封装着一些方法,可以通过这些指令来完成一些任务

Vue数据绑定的特点:

  • 数据绑定的特点是,当数据发生改变的时候,视图也会立即改变,反之亦然.并且只有三个标签才可以双向绑定

Vue数据绑定过程:

  1. 先从数据和视图进行绑定
  2. 生成绑定好的模型
  3. 交给浏览器渲染

v-once:

  • 因为Vue数据绑定的特性,使用v-once绑定以后视图或数据只发生一次变动

v-cloak:

因为浏览器渲染时,会先渲染HTML标签,再将Vue绑定好的模板交给浏览器渲染,有时候网速较慢时就会看到原始页面,为了避免这个不足,v-cloak就可以把HTML标签先隐藏,等Vue模板渲染好以后直接显示出来Vue的view视图

```!
v-cloak必须要配合CSS才能有效果,一定要加上 [v-cloak] { display: none }
```

```
示例:

    [v-cloak] {
      display: none;
    }

    <div v-cloak>内容</div>
```

v-text与v-html:

  • v-text: 把数据插入到标签中,会覆盖原有内容,不会解析HTML标签
  • v-html: 把数据插入到标签中,会覆盖原有内容,会解析HTML标签
  • 插值方式:把数据内容插到指定位置,不会修改标签内部原有内容
    <p v-text="name">+++</p>   // name
    <p v-html="name">+++</p>   // name
    <p>+++{{ name }}</p>       // +++name
    

v-if和v-show:

  • 都是满足条件就渲染数据

  • v-if:

    • 特点:
      1. 如果条件没有满足,就不会加载该元素
      2. 不仅仅可以填data内的值,还可以在v-if="" 引号中写表达式
      <p v-if="age >= 18">
      
      1. 有v-else与其配合,但是v-if一定要跟在v-if下面,中间不可以有别的标签存在
          // 如果条件满足就渲染a,不满足就渲染b
          <p v-if="age >= 18"> {{a}} </p>   
          <p v-else="age < 18"> {{b}} </p>
      
    • 注意点:
      1. 如果条件没有满足,就不会加载该元素
      2. v-if和v-else一定要连在一起,中间不可以添加元素

  • v-show:功能和v-if一样

  • 两者区别:

    • v-if: 只要条件不满足,元素就不会被创建
    • v-show: 无论是否满足条件,元素都会被创建渲染,但是false状态下的数据 display = none

v-for

  • 格式:
    <p v-for="(value,key) in obj">{{ value }}  :  {{ key }}</p>
    
    let vue = new Vue({
        el: "#app",
        data:{
           obj: {
               name: "zs",
               age: 18,
               gander: "man",
               class : "3班"
           }
        }
    })
    
    // 输出结果:创建了4个li标签,并通过 value , key添加到了标签中
    
  • 注意点:
    • 不仅仅可以遍历obj,in后面还可以遍历数组,数字,字符串,但是无论是遍历谁,都有value和index

v-bind

  • 什么是v-bind:
    • 给任意元素的任意属性绑定数据,但是添加类比较特殊,需要用特定的格式
  • v-bind格式:
    <input type="text" v-bind:value="name">     // 整体写法
    <input type="text" :value="name">           // 简写
    
  • v-bind和插值/v-text/v-html的区别:
    • v-text/v-html/插值绑定 都是给元素绑定数据
    • v-bind是给元素的属性绑定数据
  • v-bind绑定类名:
    • 格式:
      1. 因为vue是先从model中找数据渲染,所以绑定类名时要把类名放到数组中用单引号包起来,才会让vue去style中找数据
        <p :class="['size','color','bgc']">我绑定了类名</p>
        
      2. 也可以把类写到model中,来让vue渲染,格式如下:
            
            <p :class="obj">我绑定了类名</p>
        
            let vue = new Vue({
            el: "#app",
            data:{
               obj: {
                   size: true,
                   color: false,
                   bgc: true
               }
            }
        })
        
    • 注意点:
      • 绑定类名时要么存在model中,以 类名: true/false 的形式来保存,要么就存在数组中,以单引号包裹起来保存

v-on

  • v-on的作用:

    • 用于给元素添加事件监听的
  • v-on的格式:

    1. 完整版:
    <button v-on:click="myFn()">我是按钮</button>
    
    1. 简写版: 用@代表v-on
        <button @click="myFn()">我是按钮</button>
    
        let vue = new Vue({
        el: "#app",
        methods:{
            myFn(){
                alert("你成功了")
            }
        }
    })
    
  • v-on的修饰符:

    • 修饰符是用来应对一些监听事件的特殊情况的解决办法
      1. .once: 监听事件只执行一次(由于监听的回调函数默认是只要触发就会一直执行,.once的修饰符就是让该事件只触发一次)
      2. .stop: 阻止事件冒泡
      3. .prevent: 阻止元素的默认行为(例如a标签点击以后会跳转页面)
      4. .self 当本身元素触发事件时再执行
      5. .capture 事件冒泡是从内向外,该修饰符可以让事件从外向内执行

    • 修饰符的格式:
        <button @click.once="myFn()">我是按钮</button>
        
        // 点击完按钮,弹了一次框以后,再点击按钮就不弹框了
    
  • v-on的注意点:

    • 如果用到了data内的数据,要加上this
  • v-on按键修饰符:

    • 什么是按键修饰符:
      • 监听键盘的一些事件,触发事件以后执行methods中的对应函数
        <input type="text" @keyup.enter="myfn">
        // 当按下enter键时,触发myfn函数
    
    • 默认支持监听哪些按键:
      • enter
      • tab
      • delete(捕获删除和退格(backspace))
      • esc
      • up
      • down
      • left
      • right
    • 自定义设置键盘修饰符
      // 先设置一个全局变量.赋予Vue
      Vue.config.keyCode.f2 = 113
      // 再通过新定义的名字,来触发按钮
      <input type="text" @keyup.f2="myfn">   // 当f2被按下的时候,触发myfn
      

自定义全局指令

```
Vue.directive("指令名称",{
    生命周期.function(ele){
        ele.具体操作;
    }
})
```
  • 自定义指令时有不同的生命周期(称之为钩子函数)

    • bind: 当自定义的指令被绑定到元素上时触发

    • inserted: 当被绑定的元素被创建渲染时触发(被添加到父元素时被触发)

    • 代码示例:

    <div id="app">
        <input type="text" v-focus>
    </div>
    
    // 定义了一加载好页面就把input聚焦的指令
    
        Vue.directive("focus",{
            inserted: function (ele) {
                ele.focus();
            }
        });
        let vue = new Vue({
            el: "#app",
        })
        
    

    注意!: 定义自定义全局指令是在View-model上面定义的,并不是在model模型中定义!!

  • 指令钩子函数会被传入以下参数:

    • el:指令所绑定的元素,可以用来直接操作 DOM 。
    • binding:一个对象,包含以下属性:
      • name:指令名,不包括 v- 前缀。
      • value:指令的绑定值

    示例:

     <p v-color="'red'">我是段落</p>
     
     
        Vue.directive("color",{
        bind:function (el, obj) {
            el.style.color = obj.value;
        }
    });
    
    // 改段代码使得P标签被渲染时可以动态设置参数
    

自定义局部指令

  • 局部自定义变量和全局自定义变量的区别:
    • 全局自定义变量是写在view-model外面------ 局部变量写在view-model中
    • 全局自定义变量是directive-------------------局部自定义变量是directives
  • 代码示例:

    因为directives写在app2的实例中,   所以只有段落2颜色改变

    <div id="app1">
        <p v-color="'red'">我是段落1</p>
    </div>
    <div id="app2">
        <p v-color="'purple'">我是段落2</p>
    </div>

    let vue2 = new Vue({
        el: "#app2",
        data:{

        },
        methods:{

        },
        directives:{
            color:{
                bind:function (el, obj) {
                    el.style.color = obj.value;
                }
            }
        }
    })

计算属性

  • 计算属性和定义函数方法的区别:
    • 计算属性的特点: 只要return的值没有发生改变,计算属性就只会被执行一次
    • 函数方法的特点: 每次调用都会被执行
    • 如何选择两个方法:
      • 如果绑定的数据不经常改变的话,就使用计算属性
      • 如果绑定的数据经常发生变化的话,就用methods里定义的函数
  • 格式:
    <p>{{ msg }}</p>

    let vue = new Vue({
        el: "#app",
        data:{
           // model,存储数据的
        },
        methods:{
            // 专门用来保存事件监听回调函数的
        },
        directive:{
            // 用来定义局部自定义指令的
        },
        computed:{
            // 用来计算属性的
            msg: function () {
                let res = "abcde".split("").reverse().join("");
                return res;
            }
        }
    })

过滤器

全局过滤器

如何制定一个全局过滤器

  • 通过Vue.filter("过滤器名称",处理数据函数)

使用过滤器:

    // 从model中抽取name,交给过滤器formatStr处理数据
    // 如果有两个过滤器,那么从左到右依次处理数据(name)
    <p>{{ name | formatStr}}</p>
    // 定义一个全局过滤器,value就是html中的name
    // 过滤器处理完数据以后return 就是把值交给浏览器渲染
    Vue.filter("formatStr",function (value) {
    value = value.replace(/学院/g,"大学");
    return value;
});

局部过滤器:

  • 和自定义局部指令一样,写在view-model中

过渡动画

如何定义过度动画:

  • 使用类名类定义过渡动画
  • 配合css第三方库来使用过渡动画:animate
  • 使用钩子函数操作DOM
  • 配合js第三方库来使用过度动画:Velocity

1. 添加类名来定义过渡动画

  • 把需要显示(v-show)或者渲染(v-if)的组件放到transition标签中
  • 定义显示或者消失的状态

六个类名状态:

  • 显示
    • .v-enter : 表示显示前元素的状态
    • .v-enter-to : 表示显示元素的目标状态
    • .v-enter-active : 填写transition属性 -隐藏
    • v-leave: 表示隐藏前元素的状态
    • v-leave-to: 表示隐藏元素的目标状态
    • v-leave-active : 填写transition属性

使用注意点:

  • 一个transition组件,只支持一个元素的过度动画
  • 自动触发过渡效果: 给元素对应的transition标签添加 appear属性
        <transition appear>
            <div class="box" v-show="isShow"></div>
        </transition>
    
  • 当多个需要过渡动画的元素要执行不同的动画时,可以给transition定义一个name,把类名中的v-改成name中的参数,这样就可以指定不同的动画了

.one-enter{
    opacity: 0;
}
.one-enter-to{
    margin-left: 500px;
    opacity: 1;
}
.one-enter-active{
    transition: all 3s;
}
.two-enter{
    opacity: 0;
}
.two-enter-to{
    margin-top: 500px;
    opacity: 1;
}
.two-enter-active{
    transition: all 3s;
}

    <transition appear name="one">
        <div class="box" v-show="isShow"></div>
    </transition>
    
    <transition appear name="two">
        <div class="box" v-show="isShow"></div>
    </transition>

2. 使用钩子函数定义动画

  • 未掌握

3. 配合css第三方库使用过渡动画:animate

  • 在transition标签中使用 animated+动画名称
    <transition 
                appear 
                enter-class="" 
                enter-to-class="animated  jello">
                
        <div class="box"></div>
    </transition>

列表动画

  • 遍历数据,批量创建li
<transition-group appear>
<li v-for="(person,index) in persons" :key="person.id">
    <input type="checkbox">
    <span>{{ person.name}}</span>
</li>
</transition-group>
let vue = new Vue({
el : "#app",
data:{
    persons : [
        {name:"yqy",id:1},
        {name:"zs",id: 2},
        {name:"管事新",id:3},
    ],
    id: 4,
    name:""
},
methods:{
    add: function () {
        let newPerson = {name: this.name, id: this.id};
        this.id++;
        this.persons.unshift(newPerson);
        this.name = ""
    },
    del: function () {

    }
}
})

注意点:

  • 一个transition只能包裹一个标签
  • 如果需要包裹很多标签的话,需要使用transition-group包裹
  • transition-group默认把标签加载到'<span>'元素中,需要添加tag属性来指定把包裹的标签添加到什么元素里
  • 例如
<transition-group appear tag="div">
<li v-for="(person,index) in persons" :key="person.id">
    <input type="checkbox">
    <span>{{ person.name}}</span>
</li>
</transition-group>

如图所示,当transition-group的tag属性设置为div后,包裹的li都被div所包裹