vue指令、过滤器、动画

开篇

  • 1.什么是Vue?

    • Vue.js是一套构建用户界面的框架,它不仅易于上手,还可以与其它第三方库整合(Swiper、IScroll、...)。
  • 2.框架和库的区别?

    • 框架:是一套完整的解决方案;对项目的侵入性较大,项目如果需要更换框架,则需要重构整个项目。
    • 库(插件):提供某一个小功能,对项目的侵入性较小,如果某个库无法完成某些需求,可以很容易切换到其它库实现需求。
      • 例如: 从jQuery 切换到 Zepto, 无缝切换
      • 从IScroll切换到ScrollMagic, 只需要将用到IScroll的代码替换成ScrollMagic代码即可
  • 3.为什么要学习框架?

    • 提升开发效率:在企业中,时间就是效率,效率就是金钱;
    • 前端提高开发效率的发展历程:原生JS -> jQuery之类的类库 -> 前端模板引擎 -> Vue / React / Angular
  • 4.框架有很多, 为什么要先学Vue

    • Vue、Angular、React一起,被称之为前端三大主流框架!
      • 但是Angular、React是老外编写的, 所以所有的资料都是英文的
      • 而Vue是国人编写的,所以所有的资料都是中文的,并且Vue中整合了Angular、React中的众多优点
      • 所以为了降低我们的学习难度,我们先学Vue, 学完之后再学习Angular和React
  • 5.使用Vue有哪些优势?

    • 5.1Vue的核心概念之一:
      • 通过数据驱动界面更新,无需操作DOM来更新界面
        • 使用Vue我们只需要关心如何获取数据,如何处理数据,如何编写业务逻辑代码,我们只需要将处理好的数据交给Vue, Vue就会自动将数据渲染到模板中(界面上)
    • 5.2Vue的核心概念之二:

Vue基本模板

  • 1.Vue框架使用方式

    • 1.1传统下载导入使用
    • 1.2vue-cli安装导入使用
  • 2.Vue框架使用步骤

    • 2.1下载Vue框架
    • 2.2导入Vue框架
    • 2.3创建Vue实例对象
    • 2.4指定Vue实例对象控制的区域
    • 2.5指定Vue实例对象控制区域的数据

Vue数据单向传递

  • 1.MVVM设计模式

    • 在MVVM设计模式中由3个部分组成
      • M : Model 数据模型(保存数据, 处理数据业务逻辑)
      • V : View 视图(展示数据, 与用户交互)
      • VM: View Model 数据模型和视图的桥梁(M是中国人, V是美国人, VM就是翻译)
    • MVVM设计模式最大的特点就是支持数据的双向传递
      • 数据可以从 M -> VM -> V
      • 也可以从 V -> VM -> M
  • 2.Vue中MVVM的划分

    • Vue其实是基于MVVM设计模式的
      • 被控制的区域: View
      • Vue实例对象 : View Model
      • 实例对象中的data: Model
  • 3.Vue中数据的单向传递

    • 我们把"数据"交给"Vue实例对象","Vue实例对象"将数据交给"界面"
    • Model -> View Model -> View
<!--这里就是MVVM中的View-->
<div id="app">
    <p>{{ name }}</p>
</div>
<script>
// 这里就是MVVM中的View Model
let vue = new Vue({
    el: '#app',
    // 这里就是MVVM中的Model
    data: {
        name: "微双"
    }
});
</script>

Vue数据双向传递

  • 1.Vue调试工具安装

  • 2.安装步骤:

    • 2.1下载离线安装包
    • 2.2打开谷歌插件界面
    • 2.3直接将插件拖入
    • 2.4报错程序包无效:"CRX_HEADER_INVALID",可以将安装包修改为rar后缀,解压之后再安装
    • 2.5重启浏览器
  • 3.数据双向绑定

    • 默认情况下Vue只支持数据单向传递 M -> VM -> V,但是由于Vue是基于MVVM设计模式的,所以也提供了双向传递的能力
    • 在<input>、<textarea> 及 <select> 元素上可以用v-model指令创建双向数据绑定

注意点:
v-model 会忽略所有表单元素的value、checked、selected 特性的初始值,而总是将 Vue 实例的数据作为数据来源


常用指令-v-once

  • 1.什么是指令?

    • 指令就是Vue内部提供的一些自定义属性,这些属性中封装好了Vue内部实现的一些功能,只要使用这些指令就可以使用Vue中实现的这些功能
  • 2.Vue数据绑定的特点

    • 只要数据发生变化, 界面就会跟着变化
  • 3.v-once指令

    • 让界面不要跟着数据变化, 只渲染一次
  • 4.v-model指令

    • 渲染多次
    • 示例
<div id="app">
    <p v-once>{{ name }}</p>
    <p>{{ name }}</p>
</div>
<script src="js/vue.js"></script>
<script>
    let vue = new Vue({
        el: '#app',
        data: {
            name: "微双"
        }
    });
</script>

常用指令-v-cloak

  • 1.Vue数据绑定过程

    • 1.1会先将未绑定数据的界面展示给用户
    • 1.2然后再根据模型中的数据和控制的区域生成绑定数据之后的HTML代码
    • 1.3最后再将绑定数据之后的HTML渲染到界面上
      • 正是在最终的HTML被生成渲染之前会先显示模板内容,所以如果用户网络比较慢或者网页性能比较差, 那么用户会看到模板内容
  • 2.如何解决这个问题

    • 利用v-cloak配合 [v-cloak]:{display: none}默认先隐藏未渲染的界面,等到生成HTML渲染之后再重新显示
  • 3.v-cloak指令作用:

    • 数据渲染之后自动显示元素
    • 示例:
<style>
    [v-cloak] { display: none }
</style>
<div id="app">
    <p v-cloak>{{ name }}</p>
</div>
<script src="js/vue.js"></script>
<script>
    let vue = new Vue({
        el: '#app',
        data: {
            name: "微双"
        }
    });
</script>

常用指令v-text和v-html

  • 1.什么是v-text指令

    • v-text就相当于过去学习的innerText
    • 会覆盖便签内原有的内容
    • 不会解析html
  • 2.什么是v-html指令

    • v-html就相当于过去学习的innerHTML
    • 会覆盖便签内原有的内容
    • 会解析html
<div id="app">
    <!--插值的方式: 可以将指定的数据插入到指定的位置-->
  <p>++++{{ name }}++++</p>
    <!--插值的方式: 不会解析HTML-->
  <p>++++{{ msg }}++++</p>
    <!--v-text的方式: 会覆盖原有的内容-->
  <p v-text="name">++++++++</p>
    <!--v-text的方式: 也不会解析HTML-->
  <p v-text="msg">++++++++</p>
    <!--v-html的方式: 会覆盖原有的内容-->
    <p v-html="name">++++++++</p>
    <!--v-html的方式:会解析HTML-->
    <p v-html="msg">++++++++</p>
</div>
<script>
    let vue = new Vue({
        el: '#app',
        data: {
            name: "微双",
            msg: "<span>我是span</span>"
        }
    });
</script>

常用指令v-if/v-else

  • 1.什么是v-if指令

    • 条件渲染: 如果v-if取值是true就渲染元素, 如果不是就不渲染元素
  • 2.==v-if特点==:

    • 如果条件不满足根本就不会创建这个元素
  • 3.v-if注意点

    • v-if可以从模型中获取数据
    • v-if也可以直接赋值一个表达式
<div id="app">
    <p v-if="show">我是true</p>
    <p v-if="hidden">我是false</p>
</div>
<script>
    let vue = new Vue({
        el: '#app',
        data: {
            show: true,
            hidden: false
        }
    });
</script>
  • 4.v-else指令
    • v-else指令可以和v-if指令配合使用
      • 当v-if不满足条件时就执行v-else就显示v-else中的内容
<div id="app">
  <p v-if="age >= 18">成年人</p>
  <p v-else>未成年人</p>
</div>
 <script>
    let vue = new Vue({
        el: '#app',
        data: {
            show: true,
            hidden: false,
            age: 17
        }
    });
</script>

5.v-else注意点

  • v-else不能单独出现
  • v-if和v-else中间不能出现其它内容
// 错误写法
<div id="app">
  <p v-if="age >= 18">成年人</p>
  <p>中间的内容</p>
  <p v-else>未成年人</p>
</div>
  • 6.v-else-if指令
    • v-else-if可以和v-if指令配合使用
      • 当v-if不满足条件时就依次执行后续v-else-if, 哪个满足就显示哪个
<div id="app">
  <p v-if="score >= 80">优秀</p>
  <p v-else-if="score >= 60">良好</p>
  <p v-else>差</p>
</div>
 <script>
    let vue = new Vue({
        el: '#app',
        data: {
            show: true,
            hidden: false,
            age: 17,
            score: 50
        }
    });
</script>
  • 7.v-else-if注意点
    • v-else-if不能单独出现
    • v-if和v-else-if中间不能出现其它内容

常用指令v-show

  • 1.什么是v-show指令

    • v-show和v-if的能够一样都是条件渲染, 取值为true就显示, 取值为false就不显示
  • 2.==v-show特点==

    • 如果条件不满足根本就不会创建这个元素
  • 3.v-show注意点

    • v-show可以从模型中获取数据
    • v-show也可以直接赋值一个表达式

v-if和v-show区别

  • 区别1:元素是否存在

    • v-if: 只要取值为false就不会创建元素
    • v-show: 哪怕取值为false也会创建元素, 只是如果取值是false会设置元素的display为none
  • 区别2:应用场景

    • 由于取值为false时v-if不会创建元素,所以如果需要切换元素的显示和隐藏,每次v-if都会创建和删除元素
    • 由于取值为false时v-show会创建元素并设置display为none,所以如果需要切换元素的显示和隐藏,不会反复创建和删除,只是修改display的值
    • 所以: 如果企业开发中需要频繁切换元素显示隐藏, 那么推荐使用v-show, 可以提高性能,否则使用v-if

常用指令v-for

  • 1.什么是v-for指令

    • 相当于JS中的for in循环,可以根据数据多次渲染元素
  • 2.v-for特点

    • 可以遍历 数组, 字符, 数字(输出是从1开始的), 对象
    • 示例:
<div id="app">
    <ul>
        <li v-for="(value, index) in list">{{index}}-&#45;&#45;{{value}}</li>  // 遍历数组
        <li v-for="(value, index) in 'abcdefg'">{{index}}-&#45;&#45;{{value}}</li>  // 遍历字符串
        <li v-for="(value, index) in 6">{{index}}-&#45;&#45;{{value}}</li>  // 遍历数字
        <li v-for="(value, key) in obj">{{key}}---{{value}}</li> // 遍历对象
    </ul>
</div>
<script>
    let vue = new Vue({
        el: '#app',
        data: {
            list: ["张三", "李四", "王五", "赵六"],
            obj: {
                name: "lnj",
                age: 33,
                gender: "man",
                class: "知播渔"
            }
        }
    });
</script>
==注意点==
  • 1.v-for注意点

    • 1.1v-for为了提升性能,在更新已渲染过的元素列表时,会采用“就地复用”策略。也正是因为这个策略,在某些时刻会导致我们的数据混乱
      • 例如: 在列表前面新增了内容
    • 1.2为了解决这个问题,我们可以在渲染列表的时候给每一个元素加上一个独一无二的key
      • v-for在更新已经渲染过的元素列表时,会先判断key是否相同, 如果相同则复用, 如果不同则重新创建
  • 2.key属性注意点

    • 不能使用index的作为key,因为当列表的内容新增或者删除时index都会发生变化
      • 添加到列表的末尾,index到不会发生变化,但是添加到列表头的话,整体的index都会发生变化
  • 示例:

<div id="app">
    <form>
        <input type="text" v-model="name">
        <input type="submit" value="添加" @click.prevent="add">
    </form>
    <ul>
        <li v-for="(person,index) in persons" :key="person.id">
            <input type="checkbox">
            <span>{{index}} --- {{person.name}}</span>
        </li>
    </ul>
</div>
<script>
    let vue = new Vue({
        el: '#app',
        data: {
            persons: [
                {name: "zs", id: 1},
                {name: "ls", id: 2},
                {name: "ww", id: 3}
                ],
            name: ""
        },
        methods: {
            add(){
                let lastPerson = this.persons[this.persons.length - 1];
                let newPerson = {name: this.name, id: lastPerson.id + 1};
                // this.persons.push(newPerson);
                this.persons.unshift(newPerson);
                this.name = "";
            }
        }
    });
</script>

常用指令v-bind

  • 1.什么是v-bind指令

    • 给"元素的==属性=="绑定数据,就必须使用v-bind
      • 不同于给"元素"绑定数据,我们可以使用{{}}, v-text, v-html
  • 2.v-bind格式

    • v-bind:属性名称="绑定的数据"
    • : 属性名称="绑定的数据"
<input type="text" v-bind:value="age">
<input type="text" :value="age">
<script>
    let vue = new Vue({
        el: '#app',
        data: {
            age: 18
        }
    });
</script>
  • 3.v-bind特点
    • 赋值的数据可以是任意一个合法的JS表达式
    • 例如: :属性名称="age + 1"
绑定类名
  • 1.v-bind指令的特殊作用

    • v-bind指令给"任意标签"的"任意属性"绑定数据,对于大部分的属性而言我们只需要直接赋值即可, 例如:value="name"
    • 但是对于class和style属性而言, 它的格式比较特殊
  • 2.通过v-bind绑定类名格式

    • :class="['需要绑定类名', ...]" 普通格式
    • :class="[flag?'active':'']"数组的每一个元素都可以是一个三目运算符按需导入
    • :class="[{'active': true}]"通过对象来决定是否需要绑定
    • :class="对象名"(==这种方法不错==,修改方便)——使用Model中的对象来替换数组
      • 绑定的类名太多可以将类名封装到Model中例如:obj: {'color': true,'size': true,'active': false}

注意点:
1.(:class="需要绑定类名")直接赋值一个类名(没有放到数组中)默认回去Model中查找,但是Model中没有对应的类名, 所以无效
2.(:class="[需要绑定类名]")如果想让v-bind去style中查找类名,那么就必须把类名放到数组中,但是放到数组中之后默认还是回去Model中查找

  • 4.绑定类名企业应用场景
    • 从服务器动态获取样式后通过v-bind动态绑定类名,这样就可以让服务端来控制前端样式
    • 常见场景: 618 双11等
绑定样式
  • 通过v-bind给style属性绑定数据

    • 1.将数据放到对象中
      • :style="{color:'red','font-size':'50px'}"
    • 2.将数据放到Model对象中
      • :style="obj"
      • Model对象中:
        • obj: {color: 'red','font-size':'80px'}
    • 3.如果需要绑定Model中的多个对象,可以放到一个数组中赋值
      • :style="[obj1,obj2]"
      • Model对象中:
        • obj1: {color: 'red','font-size':'80px'}
        • obj2: {'background-color': 'blue'}
  • 示例:

<div id="app">
    <p :style="{color: 'red', 'font-size': '100px'}">我是段落</p>
    <p :style="obj">我是段落</p>
    <p :style="[obj1, obj2]">我是段落</p>
</div>
<script>
    let vue = new Vue({
        el: '#app',
        data: {
            obj:{
                "color": "blue",   // color可以用引号括起来,也可以不括
                "font-size": "100px"
            },
            obj1:{
                "color": "blue",
                "font-size": "100px"
            },
            obj2: {
                "background-color": "red"
            }
        }
    });
</script>
  • ==重点==:
    • 属性和取值都用引号括起来
      • 个别属性不用,但是都括起来没毛病

注意点:
如果属性名称包含-, 那么必须用引号括起来


常用指令-v-on

  • 1.什么是v-on指令?

    • v-on指令专门用于给元素绑定监听事件
  • 2.v-on指令两种格式

    • v-on:事件名称="回调函数名称"
    • @事件名称="回调函数名称"
    • 示例:
<div id="app">
<!--<button v-on:click="myFn">我是按钮</button>-->
<button @click="myFn">我是按钮</button>
</div>
<script>
    let vue = new Vue({
        el: '#app',
        data: {
        },
        methods: {
            myFn(){
                alert('lnj')
            }
        }
    });
</script>

注意点:
v-on绑定的事件被触发之后,会去Vue实例对象的methods中查找对应的回调函数

v-on修饰符
  • 1.v-on修饰符

    • 在事件中有很多东西需要我们处理,例如事件冒泡,事件捕获,阻止默认行为等.那么在Vue中如何处理以上内容呢,我们可以通过v-on修饰符来处理
  • 2.常见修饰符

    • .once
      • 只触发一次回调。
    • .prevent
      • 调用 event.preventDefault()。阻止事件默认行为
    • .stop
      • 调用 event.stopPropagation()。
      • 默认情况下载嵌套的元素中,如果都监听了相同的事件,那么会触发事件冒泡,这个stop就是阻止事件冒泡
    • .self
      • 当前元素触发事件的时候才触发回调。
    • .capture
      • 添加事件侦听器时使用 capture 模式。
      • 默认情况下是事件冒泡,如果想变成事件捕获, 那么就需要使用.capture修饰符
  • 示例:
<style>
    *{
        margin: 0;
        padding: 0;
    }
    .a{
        width: 300px;
        height: 300px;
        background: red;
    }
    .b{
        width: 200px;
        height: 200px;
        background: blue;
    }
    .c{
        width: 100px;
        height: 100px;
        background: green;
    }
</style>
<div id="app">
    <!--<button v-on:click.once ="myFn">我是按钮</button>-->
    <!--<a href="http://www.it666.com" v-on:click.prevent="myFn">我是A标签</a>-->
    <!--<div class="a" @click="myFn1">
        <div class="b" @click.stop="myFn2">
            <div class="c" @click="myFn3"></div>
        </div>
    </div>-->
    <!--<div class="a" @click="myFn1">
        <div class="b" @click.self="myFn2">
            <div class="c" @click="myFn3"></div>
        </div>
    </div>-->
    <div class="a" @click.capture="myFn1">
        <div class="b" @click.capture="myFn2">
            <div class="c" @click.capture="myFn3"></div>
        </div>
    </div>
</div>
<script>
    let vue = new Vue({
        el: '#app',
        data: {
        },
        // 专门用于存储监听事件回调函数
        methods: {
            myFn1(){
                console.log("爷爷");
            },
            myFn2(){
                console.log("爸爸");
            },
            myFn3(){
                console.log("儿子");
            }
        }
    });
</script>
v-on注意点
  • 1.绑定回调函数名称的时候,后面可以写()也可以不写

    • v-on:click="myFn"
    • v-on:click="myFn()"
  • 2.可以给绑定的回调函数传递参数

    • v-on:click="myFn('lnj', 33)"
    • 示例:
<div id="app">
    <button @click="myFn('ws',29)">按钮</button>
</div>
<script>
    let vue = new Vue({
        el: '#app',
        data: {
            
        },
        methods:{
            myFn(name,age){
                console.log(name,age);
            }
        }
    });
</script>
  • 3.如果在绑定的函数中需要用到data中的数据必须加上this
    • 示例:
<div id="app">
    <button @click="myFn('ws',29,$event)">按钮</button>
</div>
<script>
    let vue = new Vue({
        el: '#app',
        data: {
            gender: 'man'
        },
        methods:{
            myFn(name,age,e){
                console.log(name,age,this.gender);
            }
        }
    });
</script>
v-on按键修饰符
  • 1.什么是按键修饰符

    • 我们可以通过按键修饰符监听特定按键触发的事件
    • 例如: 可以监听当前事件是否是回车触发的, 可以监听当前事件是否是ESC触发的等
  • 2.按键修饰符分类

    • 2.1系统预定义修饰符
      • .enter/.tab/.delete (捕获“删除”和“退格”键)/.esc/.space/.up/.down/.left/.right等
    • 2.2自定义修饰符
      • 可以使用 v-on:keyup.自定义按键名称
        • Vue.config.keyCodes.自定义按键名称 = 查询keycode列表里自定义按键对应的值
<div id="app">
    <!--<input type="text" @keyup.enter="myFn">-->
    <input type="text" @keyup.f2="myFn">
</div>
<script>
    Vue.config.keyCodes.f2 = 113;
    let vue = new Vue({
        el: '#app',
        data: {
        },
        methods: {
            myFn(){
                alert("lnj");
            }
        }
    });
</script>

自定义指令

  • 1.自定义全局指令

    • 在Vue中除了可以使用Vue内置的一些指令以外, 我们还可以自定义指令
  • 2.自定义全局指令语法

    • 格式如下:
<script>
Vue.directive('自定义指令名称', 
    {
    生命周期名称: function (el) {
        指令业务逻辑代码
    } 
});
</script>  
  • 3.指令生命周期方法
    • 自定义指令时一定要明确指令的业务逻辑代码更适合在哪个阶段执行
    • 例如: 指令业务逻辑代码中没有用到元素事件, 那么可以在bind阶段执行
    • 例如: 指令业务逻辑代码中用到了元素事件, 那么就需要在inserted阶段执行
    • 示例:
<div id="app">
<!--    <p v-color>我是段落</p>-->
    <input type="text" v-focus>
</div>
<script>
Vue.directive("color", {
    // 这里的el就是被绑定指令的那个元素
    bind: function (el) {  // bind是生命周期名称
        el.style.color = "red";
    }
});
Vue.directive("focus", {
    inserted: function (el) {
        el.focus();   // 聚焦
    }
});
</script>

自定义指令注意点:
使用时需要加上v-, 而在自定义时不需要加上v-

自定义指令参数
  • 1.自定义指令参数

    • 在使用官方指令的时候我们可以给指令传参
    • 例如: v-model="name"在我们自定义的指令中我们也可以传递传递
  • 2.获取自定义指令传递的参数

    • 在执行自定义指令对应的方法的时候,除了会传递el给我们,还会传递一个对象给我们,这个对象中就保存了指令传递过来的参数
    • 示例:
<div id="app">
    <!--<p v-color="'blue'">我是段落</p>-->
    <p v-color="curColor">我是段落</p>
</div>
<script>
    Vue.directive("color", {
        bind: function (el, obj) {
            // el.style.color = "red";
            el.style.color = obj.value;
        }
    });
    let vue = new Vue({
        el: '#app',
        data: {
            curColor: 'green'
        }
    });
</script>

自定义局部指令

  • 1.自定义全局指令的特点

    • 在任何一个Vue实例控制的区域中都可以使用
  • 2.自定义局部指令的特点

    • 只能在自定义的那个Vue实例中使用
  • 3.如何自定义一个局部指令

    • 给创建Vue实例时传递的对象添加
    • 格式如下:
<script>
let vue = new Vue({
    el: '#app',
    data: {
    },
    directives: {
    // key: 指令名称
    // value: 对象
    '自定义生命周期名称': {
        bind: function (el, obj) {
            指令业务逻辑代码
            }
        }
    }
});

</script>
  • 示例:
<div id="app1">
    <p v-color="'blue'">我是段落</p>
</div>
<div id="app2">
    <p v-color="'red'">我是段落</p>
</div>
<script>
let vue1 = new Vue({
    el: '#app1',
    data: {},
    methods: {}
});
let vue2 = new Vue({
    el: '#app2',
    data: {},
    methods: {},
    // 专门用于定义局部指令的
    directives: {
        "color": {
            bind: function (el, obj) {
                el.style.color = obj.value;
            }
        }
    }
});
</script>

计算属性

  • 1.插值语法特点

    • 可以在{{}}中编写合法的JavaScript表达式
  • 2.在插值语法中编写JavaScript表达式缺点

    • 2.1没有代码提示
    • 2.2语句过于复杂不利于我们维护
  • 3.如何解决?

    • 对于任何复杂逻辑,你都应当使用计算属性computed
    • 示例:
<div id="app">
    <!--<p>{{msg.split("").reverse().join("")}}</p>-->
    <p>{{msg2}}</p>
</div>
<script>
    let vue = new Vue({
        el: '#app',
        data: {
            // msg: "abcdef"
        },
        // 专门用于定义计算属性的
        computed: {
            msg2: function () {
                let res = "abcdef".split("").reverse().join("");
                return res;
            }
        }
    });
</script>

注意点:
虽然在定义计算属性的时候是通过一个函数返回的数据,但是在使用计算属性的时候不能在计算属性名称后面加上()
因为它是一个属性不是一个函数(方法)


计算属性和函数的区别

  • 1.计算属性和函数的共同点

    • 通过计算属性或者通过函数我们都能拿到处理后的数据
  • 2.计算属性和函数的区别

    • 2.1函数"不会"将计算的结果缓存起来,每一次访问都会重新求值
    • 2.2计算属性"会"将计算的结果缓存起来, 只要数据没有发生变化, 就不会重新求值
  • 3.计算属性应用场景

    • 计算属性:比较适合用于计算不会频繁发生变化的的数据,这样会比使用函数的性能高
    • 函数:经常发生变化的数据
<div id="app">
    <p>{{msg1()}}</p>
    <p>{{msg1()}}</p>
    <p>{{msg1()}}</p>
    <p>{{msg2}}</p>
    <p>{{msg2}}</p>
    <p>{{msg2}}</p>
</div>
<script>
let vue = new Vue({
    el: '#app',
    data: {
    },
    // 专门用于存储监听事件回调函数
    methods: {
        // 函数的特点: 每次调用都会执行
        msg1(){
            console.log("msg1函数被执行了");
            let res = "abcdef".split("").reverse().join("");
            return res;
        }
    },
    // 专门用于定义计算属性的
    computed: {
        msg2: function () { 
            console.log("msg2计算属性被执行了");
            let res = "abcdef".split("").reverse().join("");
            return res;
        }
    }
});
</script>

自定义全局过滤器

  • 1.什么是过滤器?

    • 过滤器和函数和计算属性一样都是用来处理数据的,但是过滤器一般用于格式化插入的文本数据
  • 2.自定义全局过滤器的特点

    • 在任何一个Vue实例控制的区域中都可以使用
  • 3.如何自定义全局过滤器Vue.filter

    • Vue.filter(参数1,参数2);
      • 第一个参数: 过滤器名称
      • 第二个参数: 处理数据的函数

注意点:
默认情况下处理数据的函数接收一个参数,就是当前要被处理的数据

  • 4.如何使用全局过滤器

    • {{msg | 过滤器名称}}
    • :value="msg | 过滤器名称"
  • 5.过滤器注意点

    • 5.1只能在插值语法和v-bind中使用
    • 5.2过滤器可以连续使用
    • 示例:
<div id="app">
    <!--Vue会把name交给指定的过滤器处理之后, 再把处理之后的结果插入到指定的元素中-->
    <p>{{name | formartStr1 | formartStr2}}</p>
</div>
<script>
    Vue.filter("formartStr1", function (value) {
        value = value.replace(/学院/g, "大学");
        return value;
    });
    Vue.filter("formartStr2", function (value) {
        value = value.replace(/大学/g, "幼儿园");
        return value;
    });
    let vue = new Vue({
        el: '#app',
        data: {
            name: "知播渔学院, 指趣学院, 前端学院, 区块链学院"
        }
    });
</script>
自定义局部过滤器
  • 1.自定义局部过滤器的特点

    • 只能在自定义的那个Vue实例中使用
  • 2.如何自定义一个局部指令

    • 给创建Vue实例时传递的对象添加
    • 格式如下:
filters: {
    // key: 过滤器名称
    // value: 过滤器处理函数
    '过滤器名称': function (value) {
        过滤器处理函数
    }
}
  • 示例:
<div id="app1">
    <p>{{name | formartStr}}</p>
</div>
<div id="app2">
    <p>{{name | formartStr}}</p>
</div>
<script>
let vue1 = new Vue({
    el: '#app1',
    data: {
        name: "知播渔学院, 指趣学院, 前端学院, 区块链学院"
    }
});
let vue2 = new Vue({
    el: '#app2',
    data: {
        name: "知播渔学院, 指趣学院, 前端学院, 区块链学院"
    },
    // 专门用于定义局部过滤器的
    filters: {
        "formartStr": function (value) {
            value = value.replace(/学院/g, "大学");
            return value;
        }
    }
});
</script>
  • ==注意点==
    • 在使用过滤器的时候,可以在过滤器名称后面加上()
    • 如果给过滤器的名称后面加上了(),那么就可以给过滤器的函数传递参数
    • 示例:
<div id="app">
    <p>{{time | filter1('yyyy-MM-dd')}}</p>
</div>
<script>
    Vue.filter('filter1',function (value,frm) {
        let date = new Date(value);
        let year = date.getFullYear();
        let mouth = date.getMonth() + 1 + '';
        let day = date.getDate() + '';
        let hour = date.getHours() + '';
        let minute = date.getMinutes() + '';
        let second = date.getSeconds() + '';
        if(frm && frm === 'yyyy-MM-dd'){
            return `${year}-${mouth.padStart(2,'0')}-${day.padStart(2,'0')}`;
        }
        return `${year}-${mouth.padStart(2,'0')}-${day.padStart(2,'0')} ${hour.padStart(2,'0')}:${minute.padStart(2,'0')}:${second.padStart(2,'0')}`;
    });
    let vue = new Vue({
        el: '#app',
        data: {
            name:'知播渔学院, 指趣学院, 前端学院, 区块链学院',
            time: Date.now()
        }
    });
</script>

过渡动画

1.默认类名(v-xxx)来指定过渡动画
  • 如何给Vue控制的元素添加过渡动画
    • 1.将需要执行动画的元素放到transition组件中
    • 2.transition组件中会自动查找
      • 显示时会自动查找.v-enter/.v-enter-active/.v-enter-to类名
      • 隐藏时会自动查找.v-leave/ .v-leave-active/.v-leave-to类名
    • 3.我们只需要在.v-enter.v-leave-to中指定动画动画开始的状态
    • 4.在.v-enter-active.v-leave-active中指定动画执行的状态
    • 5.即可完成过渡动画
    • 示例:
<style>
    *{
        margin: 0;
        padding: 0;
    }
    .box{
        width: 200px;
        height: 200px;
        background: red;
    }
    .v-enter{
        opacity: 0;
    }
    .v-enter-to{
        opacity: 1;
    }
    .v-enter-active{
        transition: all 3s;
    }
    .v-leave{
        opacity: 1;
    }
    .v-leave-to{
        opacity: 0;
    }
    .v-leave-active{
        transition: all 3s;
    }
</style>
<div id="app">
    <button @click="toggle">我是按钮</button>
    <transition>
        <div class="box" v-show="isShow"></div>
    </transition>
</div>
<script>
let vue = new Vue({
    el: '#app',
    data: {
        isShow: false
    },
    methods: {
        toggle(){
            this.isShow = !this.isShow;
        }
    }
});
</script>
==注意点==
  • 1.初始动画设置

    • 默认情况下第一次进入的时候没有动画的
    • 如果想一进来就有动画,我们可以通过给transition添加appear属性的方式,告诉Vue第一次进入就需要显示动画
  • 2.如何给多个不同的元素指定不同的动画

    • 如果有多个不同的元素需要执行不同的过渡动画,那么我们可以通过给transition指定name的方式,来指定"进入之前/进入之后/进入过程中,离开之前/离开之后/离开过程中"对应的类名,来实现不同的元素执行不同的过渡动画

注意点:
transition中只能放一个元素, 多个元素无效
如果想给多个元素添加过渡动画, 那么就必须创建多个transition组件

<style>
    *{
        margin: 0;
        padding: 0;
    }
    .box{
        width: 200px;
        height: 200px;
        background: red;
    }
    .one-enter{
        opacity: 0;
    }
    .one-enter-to{
        opacity: 1;
        margin-left: 500px;
    }
    .one-enter-active{
        transition: all 3s;
    }
    .two-enter{
        opacity: 0;
    }
    .two-enter-to{
        opacity: 1;
        margin-top: 500px;
    }
    .two-enter-active{
        transition: all 3s;
    }
</style>
<div id="app">
    <button @click="toggle">我是按钮</button>
    <transition appear name="one">
        <div class="box" v-show="isShow"></div>
    </transition>
    <transition appear name="two">
        <div class="box" v-show="isShow"></div>
    </transition>
</div>
<script>
    let vue = new Vue({
        el: '#app',
        data: {
            isShow: true
        },
        methods: {
            toggle(){
                this.isShow = !this.isShow;
            }
        }
    });
</script>
2.JS钩子函数来指定过渡动画
  • 1.当前过渡存在的问题

    • 通过transition+类名的方式确实能够实现过渡效果,但是实现的过渡效果并不能保存动画之后的状态
    • 因为Vue内部的实现是在过程中动态绑定类名, 过程完成之后删除类名
    • 正是因为删除了类名, 所以不能保存最终的效果
  • 2.在Vue中如何保存过渡最终的效果

    • 通过Vue提供的JS钩子来实现过渡动画
      • v-on:before-enter="beforeEnter" 进入动画之前

      • v-on:enter="enter" 进入动画执行过程中

      • v-on:after-enter="afterEnter" 进入动画完成之后

      • v-on:enter-cancelled="enterCancelled" 进入动画被取消

      • v-on:before-leave="beforeLeave" 离开动画之前

      • v-on:leave="leave" 离开动画执行过程中

      • v-on:after-leave="afterLeave" 离开动画完成之后

      • v-on:leave-cancelled="leaveCancelled" 离开动画被取消

  • 3.JS钩子实现过渡注意点

    • 3.1在动画过程中必须写上el.offsetWidth或者el.offsetHeight
    • 3.2在enter和leave方法中必须调用done方法,否则after-enter和after-leave不会执行
    • 3.3若需要添加初始动画,那么需要把done方法包裹到setTimeout方法中调用
    • 示例:
<div id="app">
    <button @click="toggle">我是按钮</button>
    <transition appear
                v-bind:css="false"
                v-on:before-enter="beforeEnter"
                v-on:enter="enter"
                v-on:after-enter="afterEnter">
        <div class="box" v-show="isShow"></div>
    </transition>
</div>
<script>
let vue = new Vue({
    el: '#app',
    data: {
        isShow: true
    },
    methods: {
        toggle(){
            this.isShow = !this.isShow;
        },
        beforeEnter(el){
            // 进入动画开始之前
            console.log("beforeEnter");
            el.style.opacity = "0";
        },
        enter(el, done){
            // 进入动画执行过程中
            console.log("enter");
            // el.offsetWidth;
            el.offsetHeight;
            el.style.transition = "all 3s";
            // done();
            /*
            注意点: 如果想让元素一进来就有动画, 那么最好延迟以下再调用done方法
            */
            setTimeout(function () {
                done();
            }, 0);
        },
        afterEnter(el){
            // 进入动画执行完毕之后
            console.log("afterEnter");
            el.style.opacity = "1";
            el.style.marginLeft = "500px";
        }
    }
});
</script>
配合使用第三方 JavaScript 动画库,实现过渡动画
  • 配合Velocity实现过渡动画
    • 在Vue中我们除了可以自己实现过渡动画以外,还可以结合第三方框架实现过渡动画
      • 1.导入Velocity库
      • 2.在动画执行过程钩子函数中编写Velocity动画
      • 示例:
<style>
    *{
        margin: 0;
        padding: 0;
    }
    .box{
        width: 200px;
        height: 200px;
        background: red;
    }
</style>
<div id="app">
    <button @click="toggle">我是按钮</button>
    <transition appear
                v-bind:css="false"
                v-on:before-enter="beforeEnter"
                v-on:enter="enter"
                v-on:after-enter="afterEnter">
        <div class="box" v-show="isShow"></div>
    </transition>
</div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/velocity/1.2.3/velocity.min.js"></script>
<script>
    let vue = new Vue({
        el: '#app',
        data: {
            isShow: true
        },
        methods: {
            toggle(){
                this.isShow = !this.isShow;
            },
            beforeEnter(el){
            },
            enter(el, done){
                Velocity(el, {opacity: 1, marginLeft: "500px"}, 3000);
                done();
            },
            afterEnter(el){

            }
        }
    });
</script>
使用自定义类名的方式来指定过渡动画
  • 1.自定义类名动画

    • 1.在Vue中除了可以使用默认类名(v-xxx)来指定过渡动画
    • 2.除了可以使用自定义类名前缀(yyy-xx)来指定过渡动画(transition name="yyy")
    • 3.除了可以使用 JS钩子函数来指定过渡动画以外
    • 4.还可以使用自定义类名的方式来指定过渡动画
      • enter-class 进入动画开始之前
      • enter-active-class 进入动画执行过程中
      • enter-to-class 进入动画执行完毕之后
      • leave-class 离开动画开始之前
      • leave-active-class 离开动画执行过程中
      • leave-to-class 离开动画执行完毕之后
  • 示例:

<style>
    *{
        margin: 0;
        padding: 0;
    }
    .box{
        width: 200px;
        height: 200px;
        background: red;
    }
    .a{
        opacity: 0;
    }
    .b{
        opacity: 1;
        margin-left: 500px;
    }
    .c{
        transition: all 3s;
    }
</style>
<div id="app">
    <button @click="toggle">我是按钮</button>
    <transition appear
                enter-class="a"
                enter-active-class="c"
                enter-to-class="b">
        <div class="box" v-show="isShow"></div>
    </transition>
</div>
<script>
    let vue = new Vue({
        el: '#app',
        data: {
            isShow: true
        },
        methods: {
            toggle(){
                this.isShow = !this.isShow;
            }
        }
    });
</script>
配合使用第三方 CSS 动画库Animate.css实现过渡动画
  • 配合Animate.css实现过渡动画步骤
    • 1.导入Animate.css库
    • 2.在执行过程中的属性上绑定需要的类名
    • 示例:
<link href="https://cdn.jsdelivr.net/npm/animate.css@3.5.1" rel="stylesheet" type="text/css">
<div id="app">
    <button @click="toggle">我是按钮</button>
    <transition appear
                enter-active-class="animated bounceInRight">
        <div class="box" v-show="isShow"></div>
    </transition>
</div>
<script>
    let vue = new Vue({
        el: '#app',
        data: {
            isShow: true
        },
        methods: {
            toggle(){
                this.isShow = !this.isShow;
            }
        }
    });
</script>

过渡动画(添加多个)

  • 如何同时给多个元素添加过渡动画
    • 通过transition可以给单个元素添加过渡动画,如果想给多个元素添加过渡动画,那么就必须通过transition-group来添加
    • transition-group和transition的用法一致,只是一个是给单个元素添加动画,一个是给多个元素添加动画而已
    • 示例(不是最终版,里面还有bug,下面有讲注意点):
<style>
    *{
        margin: 0;
        padding: 0;
    }
    .v-enter{
        opacity: 0;
    }
    .v-enter-to{
        opacity: 1;
    }
    .v-enter-active{
        transition: all 3s;
    }
    .v-leave{
        opacity: 1;
    }
    .v-leave-to{
        opacity: 0;
    }
    .v-leave-active{
        transition: all 3s;
    }
</style>
<div id="app">
    <form>
        <input type="text" v-model="name">
        <input type="submit" value="添加" @click.prevent="add">
    </form>
    <ul>
        <transition-group appear>
            <li v-for="(person,index) in persons" :key="person.id" @click="del(index)">
                <input type="checkbox">
                <span>{{index}} --- {{person.name}}</span>
            </li>
        </transition-group>
    </ul>
</div>
<script>
let vue = new Vue({
    el: '#app',
    data: {
        persons: [
            {name: "zs", id: 1},
            {name: "ls", id: 2},
            {name: "ww", id: 3}
            ],
        name: ""
    },
    methods: {
        add(){
            let lastPerson = this.persons[this.persons.length - 1];
            let newPerson = {name: this.name, id: lastPerson.id + 1};
            // this.persons.push(newPerson);
            this.persons.unshift(newPerson);
            this.name = "";
        },
        del(index){
            this.persons.splice(index, 1);
        }
    }
});
</script>
注意点:
  • 1.标签问题

    • 默认情况下transition-group会将动画的元素放到span标签中
      • 解决方法:我们可以通过tag属性来指定将动画元素放到什么标签中(把html里面对应的标签删除,tag属性就会自动添加标签)
  • 2.transition-group动画混乱问题

    • 一般情况下组动画出现动画混乱都是因为v-for就地复用导致的
      • 解决方案:我们只需要保证所有数据key永远是唯一的即可
    • 示例(上面示例就有这个bug),解决如下:
      • 1.data里面新增一个id,赋值为3(list的长度)
      • 2.add方法中
        • 添加this.id++
        • let lastPerson = this.persons[this.persons.length - 1];删除
        • let newPerson = {name: this.name, id: lastPerson.id + 1};改成let newPerson = {name: this.name, id: this.id};
        • 成品View Model如下:
<script>
    let vue = new Vue({
        el: '#app',
        data: {
            persons: [
                {name: "zs", id: 1},
                {name: "ls", id: 2},
                {name: "ww", id: 3}
                ],
            name: "",
            id: 3
        },
        methods: {
            add(){
                this.id++;
                // let lastPerson = this.persons[this.persons.length - 1];
                let newPerson = {name: this.name, id: this.id};
                // this.persons.push(newPerson);
                this.persons.unshift(newPerson);
                this.name = "";
            },
            del(index){
                this.persons.splice(index, 1);
            }
        }
    });
</script>
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 215,794评论 6 498
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,050评论 3 391
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 161,587评论 0 351
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,861评论 1 290
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,901评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,898评论 1 295
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,832评论 3 416
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,617评论 0 271
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,077评论 1 308
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,349评论 2 331
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,483评论 1 345
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,199评论 5 341
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,824评论 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,442评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,632评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,474评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,393评论 2 352