Vue学习笔记 2 - 计算属性/过滤器/自定义指令/监测数组更新/高阶函数/ES6 语法补充/Vue 实例的生命周期

计算属性

当需要对数据进行某种转化,并返回转化后的数据时,我们可以使用计算属性。

<h1>{{fullName}}</h1>
//注意:fullName是属性,不是函数,不用加()
	data: {
        firstName:'LeBron',
        lastName:'James'
    },
    computed: {
        fullName: function () {
            return this.firstName + ' ' + this.lastName
        }
    }
  • 计算属性的缓存

看起来 computed 与 methods 都可以实现我们想要的功能,区别在于计算机属性会进行缓存,如果多次使用时,computed 属性只会调用一次

  • 计算属性有缓存,计算属性会把函数执行一次,把结果存起来,依赖的值改变,会重新赋值。

  • 函数是每次模板编译都会执行。只要有响应式属性改变,视图刷新,函数就执行。

  • 计算属性的 setter 和 getter

计算属性的完整写法:

		computed: {
            fullName: {
                set: function () {
                },
                get: function () {
                    return this.firstName + ' ' + this.lastName
                }
            }
        }

所以调用时直接使用{{fullName}}调用属性,它并不是一个方法。

  • 计算属性一般没有 set 方法(只读属性)。在上面的例子中我们只是使用 getter 来读取,在某些情况下,也可以提供一个 setter 方法:
		computed: {
			fullName: {
                set(newValue) {
                    console.log('----调用了 fullName 的 set 方法')
                    const names = newValue.split('')
                    this.firstName = names[0]
                    this.lastName = names[1]
                },
                get() {
                    console.log('----调用了 fullName 的 get 方法')
                    return this.firstName + ' ' + this.lastName
                }
            }
        }
  • 计算属性的复杂操作

		data: {
            comics: [
                {id: 1, name: 'Naruto', price: 101},
                {id: 2, name: 'OnePiece', price: 204},
                {id: 3, name: 'Conan', price: 143},
                {id: 4, name: 'Sherlock', price: 242}
            ]
        },
        computed: {
            totalPrice: function () {
                let result = 0;
                for (let i = 0; i < this.comics.length; i++) {
                    result += this.comics[i].price
                }
                return result
            }
        }

 

根据条件筛选品牌

  • 筛选框绑定到 VM 实例中的 searchName 属性:
<label>
    search:
    <input type="text" class="form-control" v-model="keywords">
</label>
  • 在使用 v-for 指令循环每一行数据的时候,不再直接 item in list,而是 in 一个过滤的methods 方法,同时,把过滤条件searchName传递进去:
<tr v-for="item in search(keywords)" :key="item.id">
    <td>{{item.id}}</td>
    <td>{{item.name}}</td>
    <td>{{item.date}}</td>
    <td><a href="" @click.prevent="del(item.id)">delete</a></td>
</tr>
  • search 过滤方法中,使用 数组的 filter 方法进行过滤:
search(keywords) {
    return this.list.filter(item => {
        if (item.name.includes(keywords)) {
            return item
        }
    })
}

 

过滤器

过滤器可以用在两个地方:mustache 插值和 v-bind 表达式。

  • 全局过滤器

调用格式:

//过滤器的定义语法
{{ name | 过滤器的名称 }}
//过滤器调用时的格式
//过滤器中的function,第一个参数是规定死的,永远是 过滤器 管道符前面 传过来的数据
Vue.filter('过滤器的名称',function (data) {
    return data
})

可以传多个参数,也可多次调用过滤器:

<script>
    Vue.filter('msgFormat', function (msg,arg,arg2) {
        return msg.replace(/4/g, arg + arg2)
    })

    Vue.filter('test', function (msg) {
        return msg+'---'
    })

    var vm = new Vue({
        el: '#app',
        data: {
            msg: '111111224442233333'
        },
        methods: {
        }
    })
</script>
  • 私有过滤器

过滤器的调用采用就近原则,如果私有和全局过滤器名称一致,优先调用私有过滤器。

<div id="ban">{{dt | dateFormat}}</div>
var vm2 = new Vue({
    el: '#ban',
    data: {
        dt: new Date()
    },
    methods: {},
    filters: {
        dateFormat: function (dateStr, pattern = '') {
            var dt = new Date(dateStr)
            var y = dt.getFullYear()
            var m = dt.getMonth() + 1
            var d = dt.getDate()
            // return `${y}-${m}-${d}`
            if (pattern && pattern.toLowerCase() === 'yy-mm-dd') {
                return `${y}-${m}-${d}`
            } else {
                var hh = dt.getHours()
                var mm = dt.getMinutes()
                var ss = dt.getSeconds()
                return `${y}-${m}-${d} ${hh}:${mm}:${ss}`
            }
        }
    }
})
  • 使用ES6中的字符串新方法 String.prototype.padStart(maxLength, fillString='')String.prototype.padEnd(maxLength, fillString='')来填充字符串;
var mm = dt.getMinutes().toString().padStart(2,'0')

使用前:2019-9-24 15:37:32
使用后:2019-09-24 15:37:58

 

键盘修饰符及自定义

  • 通过Vue.config.keyCodes.名称 = 按键值来自定义案件修饰符的别名:
Vue.config.keyCodes.f2 = 113;
  • 使用自定义的按键修饰符:
<input type="text" v-model="name" @keyup.f2="add">

js中键盘事件对应的键码

 

自定义指令

  • 通过Vue.directive定义指令
    在定义时指令时不加 v- 前缀
//定义全局指令(全局不加 s,私有加 s)
//参数1:指令名称
//参数2:是一个对象,在这个对象身上有指令相关的函数,这些函数在特定阶段执行相关操作
Vue.directive('focus', {
    bind: function (el) {
    //每当指令绑定到元素上的时候,会立刻执行,只执行一次
    //注意在每个函数中,第一个参数永远是el,表示被绑定指令的那个元素。
    //在元素刚绑定指令的时候,还没插入到 DOM 中去,调用 focus 方法没有用。
    //因为一个元素只有在插入 DOM 之后才能获取焦点
    // el.focus()
    },
    inserted: function (el) { //当元素插入到DOM中的时候,会立刻执行,只执行一次
        el.focus()
    },
    updated: function () { //当 VNode 更新的时候执行,可能会触发多次
    }
})

//定义设置字体颜色指令
Vue.directive('color', {
    //样式只要通过指令绑定给了元素,不管这个元素有没有被插入到页面中去,这个元素肯定有了内联样式
    //将来元素肯定会显示到页面中,此时浏览器的渲染引擎必然会解析样式,应用给这个元素
    //和样式相关的操作,一般都可以在 bind 中执行
    bind: function (el,binding) {
        el.style.color = binding.value
    },
    //和 JS 行为有关的操作,最好在 inserted 中执行,放置 JS 行为不生效
    inserted: function () {
    },
    updated: function () {
    }
})
  • 指令调用
    Vue中所有指令在调用时,必须以v-开头
<input type="text" class="form-control" v-model="keywords" v-focus v-color="'green'">
  • 定义私有指令
directives: { //自定义私有指令
    'fontweight': {
        bind: function (el, binding) {
            el.style.fontWeight = binding.value
            }
        }
    }
  • 私有指令调用
<div id="ban">
<p v-color="'pink'" v-fontweight="200">{{dt|dateFormat}}</p>
</div>
  • 函数简写
    当我们想在bind 和 update钩子上做重复动作,而不想关心其他钩子函数,可以这么写:
<div id="ban">
<p v-color="'pink'" v-fontweight="200">{{dt|dateFormat}}</p>
</div>

调用

directives: { //自定义私有指令
    'fontsize': function (el, binding) {
        el.style.fontSize = parseInt(binding.value) + 'px'
    }
}

 

监测数组更新(响应式)

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

		data: {
            list: ['a', 'b', 'c']
        }
  • push()
			this.list.push('d')
			//(a,b,c → a,b,c,d)
  • pop():删除数组中的最后一个元素
			this.list.pop()
			//(a,b,c → a,b)
  • shift():删除数组中的第一个元素
			this.list.shift()
			//(a,b,c → b,c)
  • unshift():在数组最前面添加元素
			this.list.unshift
			//('d','e','f')
  • splice():删除、插入、替换元素

删除元素:第二个参数传入你要删除几个元素(不传就删除后面所有元素)

			this.list.splice(1,1)
			//(a,b,c → a,c)

替换元素:第二个参数表示我们要替换几个元素,后面是用于替换前面的元素

			this.list.splice(1,2,'o','p')
			//(a,b,c → a,o,p)

插入元素:第二个参数传入 0,后面跟上要插入的元素

			this.list.splice(0,0,'e','f')
			//(a,b,c → e,f,a,o,p)
  • sort():整理数组
			this.list.sort()
  • reverse():反转数组
			this.list.reverse()

注意:通过索引值修改数组中的元素不是响应式的

			this.list[0] = 'v'
			//(a,b,c)
            console.log(this.list)
            //log: ["v","b","c"]
			this.list.splice(0, 1, 'v')
			//(v,b,c)
            //set(要修改的对象,索引值,修改后的值)
            vue.set(this.list, 0, 'v')
            //(v,b,c)

 

高阶函数 filter/map/reduce

	const nums = [10, 20, 30, 40]
  • filter函数的使用

filter 中的回调函数有一个要求:必须返回一个 bool 值

  • 当返回 true 时,函数内部会自动将这次回调的 n 加入到新的数组中
  • 当返回 false 时,函数内部会过滤掉这次的 n
    let newNums = nums.filter(function (n) {
        return n < 130
    })
    
    console.log(newNums) // [10, 20]
  • map函数的使用
	let newNums = nums.map(function (n) {
        return n * 2
    })
    console.log(newNums) //[20, 40, 60, 80]
  • reduce函数的使用

作用:对数组中所有内容进行汇总

	let total = nums.reduce(function (preValue, n) {
        return preValue + n
    }, 0)
    console.log(total) //100
    // 遍历过程
    // (preValue,n)→(10,0)
    // (preValue,n)→(20,10)
    // (preValue,n)→(30,30)
    // (preValue,n)→(40,60)

直接结构化访问对象

	let total = nums.reduce(function (preValue, movies) {
        return preValue + movies.price * movies.count
    }, 0)
  • 链式语法
	let total = nums.filter(function (n) {
        return n < 100
    }).map(function (n) {
        return n * 2
    }).reduce(function (preValue, n) {
        return preValue + n
    }, 0)
  • 箭头函数
	let total = nums.filter(n => n < 100).map(n => n * 2).reduce((pre, n) => pre + n)

 

ES6 语法补充

  • let/var

区别:let有块级作用域,而var没有

在 ES5 之前,因为 if 和 for 都没有块级作用域的概念,所以很多时候我们必须借助 function 的作用域来解决应用外面变量的问题。

定义 5 个按钮:

<div id="app">
    <button>按钮1</button>
    <button>按钮2</button>
    <button>按钮3</button>
    <button>按钮4</button>
    <button>按钮5</button>
</div>
  • var(ES5)
	const btns = document.getElementsByTagName('button')
    for (var i = 0; i < btns.length; i++) {
        btns[i].addEventListener('click', function () {
            console.log('第' + i + '个按钮被点击')
        })
    }

//点击按钮1
第5个按钮被点击

函数是一个作用域,所以闭包可以解决作用域引起的问题

  • 闭包(ES5)
	const btns = document.getElementsByTagName('button')
    for (var i = 0; i < btns.length; i++) {
        (function (i) {
            btns[i].addEventListener('click', function () {
                console.log('第' + i + '个按钮被点击')
            })
        })(i)
    }

//点击按钮1
第0个按钮被点击

  • let(ES6)
	const btns = document.getElementsByTagName('button')
    for (let i = 0; i < btns.length; i++) {
        btns[i].addEventListener('click', function () {
            console.log('第' + i + '个按钮被点击')
        })
    }

//点击按钮1
第0个按钮被点击

  • const

当我们修饰的标识符不会被再次赋值时,就可以使用 const 来保证数据的安全性。

建议:在 ES6 的开发中,优先使用 const ,只有需要改变某一个标识符的时候才使用 let 。

  • const修饰的标识符,被赋值后不能修改
const a = 20;
a = 30 //错误,const不能被改变
  • 使用const定义标识符,必须赋值
const a; //错误,const修饰的标识符必须赋值
  • 常量的含义是,指向的对象不能修改,但是可以改变对象内部的属性(const 指向的内存地址不变)
const obj = {
        name: 'puppy',
        age: 18,
        height: 0.5
    }
    obj.name = 'cat'
    obj.age = 7
    console.log(obj)

{name: “cat”, age: 7, height: 0.5}

  • 对象字面量增强写法

const obj = new Object() //对象
const obj = {} //对象字面量

	//ES5
    const obj = {
        run: function () {
        },
        eat: function () {
        }
    }
	//ES6
    const obj = {
        run() {
        },
        eat() {
        }
    }

 

Vue 实例的生命周期

  • 什么是生命周期:从Vue实例创建、运行、到销毁期间,总是伴随着各种各样的事件,这些事件,统称为生命周期!

  • 生命周期钩子 = 生命周期函数 = 生命周期事件

  • 主要的生命周期函数分类:

  • 创建期间的生命周期函数:
    • beforeCreate:实例刚在内存中被创建出来,此时,还没有初始化好 data 和 methods 属性
    • created:实例已经在内存中创建OK,此时 data 和 methods 已经创建OK,此时还没有开始 编译模板
    • beforeMount:此时已经完成了模板的编译,但是还没有挂载到页面中
    • mounted:此时,已经将编译好的模板,挂载到了页面指定的容器中显示
  • 运行期间的生命周期函数:
    • beforeUpdate:状态更新之前执行此函数, 此时 data 中的状态值是最新的,但是界面上显示的 数据还是旧的,因为此时还没有开始重新渲染DOM节点
    • updated:实例更新完毕之后调用此函数,此时 data 中的状态值 和 界面上显示的数据,都已经完成了更新,界面已经被重新渲染好了!
  • 销毁期间的生命周期函数:
    • beforeDestroy:实例销毁之前调用。在这一步,实例仍然完全可用。
    • destroyed:Vue 实例销毁后调用。调用后,Vue 实例指示的所有东西都会解绑定,所有的事件监听器会被移除,所有的子实例也会被销毁。

Vue学习笔记 2 - 计算属性/过滤器/自定义指令/监测数组更新/高阶函数/ES6 语法补充/Vue 实例的生命周期_第1张图片
生命周期完整示例:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>HelloVue</title>
    <script src="js/vue.js"></script>
</head>
<body>
<div id="app">
    <h3 id="msg">{{ msg }}</h3>
    <input type="button" value="修改 msg" @click="msg='No'">
</div>
</body>
<script>
    var vm = new Vue({
        el: '#app',
        data: {
            msg: 'datamsg'
        },
        methods: {
            show() {
                console.log('执行了 show 方法')
            }
        },
        //注意,在 beforeCreate 生命周期函数执行的时候,data 和 methods 中的数据都还没有初始化
        beforeCreate() {
            // console.log(this.msg) //报错,说明 data 内数据未被初始化
            // this.show() //不执行
        },
        //在 created中,data 和 methods 都已经被初始化好了,
        created() { //这是遇到的第二个生命周期函数
            // console.log('this.msg')
            // this.show()
        },
        //这是遇到的第三个生命周期函数,表示模板已经在内存中编译完成了,但是尚未把模板渲染到页面中
        beforeMount() {
            // console.log(document.getElementById('msg').innerText) //输出{{msg}}
            //在 beforeMount 执行的时候,页面中的元素还没被真正替换过来,只是之前写的一些模板字符串
        },
        //这是遇到的第四个生命周期函数,表示内存中的模板已经真实地
        mounted() {
            // console.log(document.getElementById('msg').innerText) //输出 datamsg
            //注意,mounted 是实例创建的最后一个生命周期函数,当执行完就表示实例已经被完全创建好了,
            // 此时如果没有其他操作的话,这个实例就静静的躺在内存中不动了
        },
        //接下来的是运行中的两个事件,点击按钮更新 data 触发
        beforeUpdate(){ //此时数据已更新,页面未更新
            // console.log('界面上元素内容:'+ document.getElementById('msg').innerText) //console:界面上元素内容:datamsg
            // console.log('data 中的msg数据:' + this.msg)//console:data 中的msg数据:No
        },
        updated(){ //此时数据与页面都已更新
            console.log('界面上元素内容:'+ document.getElementById('msg').innerText) //console:界面上元素内容:No
            console.log('data 中的msg数据:' + this.msg)//console:data 中的msg数据:No
        }
    })
</script>
</html>

 

参考视频:Vue黑马视频教程
参考视频:小码哥 Vue 视频教程

你可能感兴趣的:(Vue学习笔记 2 - 计算属性/过滤器/自定义指令/监测数组更新/高阶函数/ES6 语法补充/Vue 实例的生命周期)