前端Vue2-Day48

计算属性:computed属性)要使用的数据不存在,须通过已有属性计算得出。

原理:使用了Object.defineproperty方法提供的getter和setter。

get函数的执行时机:1.在初次获取元素时调用(产生缓存防止重复调用)2.修改数据时调用

优势:相较于methods,内部存在缓存机制,效率更高,调试方便。

备注:计算属性会挂载到vm上,直接调用即可。如果计算属性发生修改,需要去内部编写set方法响应修改,且要修改依赖的数据。

computed: {
                fullName: {
                    // 读取时自动调用
                    // 初次读取和修改时重新调用
                    get() {
                        return `${this.firstName}-${this.lastName}`
                    },
                    // 修改时自动调用
                    set(value) {
                        const arr = value.split('-')
                        this.firstName = arr[0]
                        this.lastName = arr[1]
                    }
                }
            }

计算属性简写:当不发生修改时,即无set方法时。直接将属性写成方法并返回值。

new Vue({
            el: '#root',
            data: {
                firstName: '张',
                lastName: '三'
            },
            computed: {
                // 简写:不发生修改
                fullName() {
                    return `${this.firstName}-${this.lastName}`
                }
            }
        })

 

监视属性:(watch)当监视的属性发生变化时,回调函数handler调用。handler属性默认为newValue和oldValue。

监视属性的写法:

① new Vue中加入配置项watch进行相关配置(immediate:初始化是否立即执行,handler为变化执行的回调函数)

② 使用vm.$watch进行配置。$watch('属性名',{回调函数}) 

深度监视:监视对象内部值变化。

① Vue中的watch属性默认不检测对象内部的改变。

② 配置watch中的deep属性为true即可达到多级监视的目的。

new Vue({
            el: '#root',
            data: {
                isHot: true,
                numbers: {
                    a: 1,
                    b: 2,
                }
            },
            methods: {
                changeWeather() {
                    this.isHot = !this.isHot
                }
            },
            computed: {
                info() {
                    return this.isHot ? '炎热' : '凉爽'
                }
            },
            watch: {
                // 监视多级解构中某个属性的变化
                'numbers.a': {
                    handler(newValue, oldValue) {

                    }
                },
                // 监视多级结构中所有属性的变化
                numbers: {
                    deep:true,
                    handler(newValue, oldValue) {
                        console.log('change');
                    }
                }
            }
        })

监视属性简便写法:不考虑设置immediate和deep时直接将监视属性作为handler函数返回。

// 简便写法1:
 isHot(newValue, oldValue) {
        console.log('change');
 }

// 简便写法2:
vm.$watch('isHot', function (newValue, oldValue) {
            console.log('change');
})

computed和watch的区别:

① computed能完成的功能,watch都能完成。

② watch能完成的功能,computed不一定能完成,如使用watch实现异步操作。

 

注意:所有由Vue管理的函数,最好写成普通函数,这样this执行为vm即Vue实例对象。而不被Vue管理的函数(定时器,Ajax回调函数,Promise回调函数等)最好写成箭头函数,这样this才指向vm。

 

绑定样式:

绑定Class样式:写法:class="xxx" xxx可以为字符串,数组或对象。

  • 字符串适用于类名不确定,需要动态获取。
  • 数组适用于要绑定多个样式,个数和名字均确定,但要动态决定是否选用。
  • 对象适用于要绑定多个样式,个数和名字均不确定。

绑定Style样式:写法:style="{fontSize:xxx}"其中xxx为动态值,:style="[a,b,c]"其中abc为样式对象。

 

条件渲染:v-show和v-if

v-if:v-if="xxx" / v-else-if="xxx" / v-else

适用于低频率变化的场景,不展示的DOM元素直接被移除,v-if和v-else-if和v-else使用时必须相接不能被打断。

v-show:v-show="xxx"

高频率变化使用v-show,不展示的DOM元素未被移除,仅仅是display:none隐藏掉。

template标签:与v-if一起使用,隐藏时会在页面随之隐藏,显示和隐藏均不会存在该节点。

<template v-if="n===1">
            <h1>12</h1>
            <h2>23</h2>
</template>

 

列表渲染:

v-for命令:用于展示列表数据。

语法:v-for="(item,index)" in "xxx" :key="yyy"(这里用in和of均可)

虚拟DOM中key的作用:key是虚拟DOM对象的唯一标识。当数据发生变化时,Vue会根据【新数据】生成【新的虚拟DOM】,随后Vue进行【新虚拟DOM】和【旧虚拟DOM】的差异比较。

新旧虚拟DOM比较规则(Diff算法):

(1)旧虚拟DOM中找到了与新虚拟DOM相同的key值:

  • ① 若新虚拟DOM中内容没变,则直接使用之前生成的真实DOM。
  • ② 若新虚拟DOM中内容变化了,则直接生成新的真实DOM,随后替换掉之前生成的旧真实DOM。

(2)旧虚拟DOM中未找到和新虚拟DOM相同的key值:则直接生成新的真实DOM,渲染至页面。

 

使用下标index作为key的问题:若对数据进行:逆序添加、逆序删除等破坏顺序的操作,会产生没有必要的真实DOM更新,造成效率低下。如果结构中还包含输入类DOM则会产生错误的真实DOM更新,造成页面渲染出错。

 

筛选列表事例:

1.使用监视属性实现时,改变的是页面遍历的数组。故设立一个新数组于data中。handler进行筛选改变,需要immediate立即执行。

2.使用计算属性实现时,将页面要展现的新数组计算出来。设置新的数组作为计算属性,直接对其进行get方法改变即可。

这里的种种操作是因为筛选数组用到的filter方法不会改变原数组,而是生成一个新数组作为返回值。

 <div id="root">
        <h2>人员列表</h2>
        <input type="text" placeholder="请输入名字" v-model="keyWord">
        <ul>
            <li v-for="(p,index) in filPersons" :key="p.id">
                {{p.name}}-{{p.age}}
            </li>
        </ul>
    </div>

    <script>
        // 利用 watch实现
        new Vue({
            el: '#root',
            data: {
                keyWord: '',
                persons: [
                    {
                        id: 001,
                        name: '马冬梅',
                        age: 18,
                        gender: ''
                    },
                    {
                        id: 002,
                        name: '周冬雨',
                        age: 20,
                        gender: ''
                    },
                    {
                        id: 003,
                        name: '周杰伦',
                        age: 30,
                        gender: ''
                    },
                    {
                        id: 004,
                        name: '温兆伦',
                        age: 35,
                        gender: ''
                    }
                ],
                // 存放新数据
                filPersons: []
            },
            watch: {
                keyWord: {
                    immediate: true,
                    handler(value) {
                        this.filPersons = this.persons.filter(p => {
                            return p.name.indexOf(value) !== -1
                        })
                    }
                }
            }
        })

        // 利用 computed实现
        new Vue({
            el: '#root',
            data: {
                keyWord: '',
                persons: [
                    {
                        id: 001,
                        name: '马冬梅',
                        age: 18,
                        gender: ''
                    },
                    {
                        id: 002,
                        name: '周冬雨',
                        age: 20,
                        gender: ''
                    },
                    {
                        id: 003,
                        name: '周杰伦',
                        age: 30,
                        gender: ''
                    },
                    {
                        id: 004,
                        name: '温兆伦',
                        age: 35,
                        gender: ''
                    }
                ],
            },
            computed: {
                filPersons() {
                    return this.persons.filter(e => {
                        return e.name.indexOf(this.keyWord) !== -1
                    })
                }
            }
        })
    </script>

 

列表排序事例:

给各排序按钮设置事件改变定义的sortType属性,在计算属性内部进行判断是否需要进行重排序,由于计算属性触发时机为依赖属性改变故总会随按钮点击而变化。

<div id="root">
        <h2>人员列表</h2>
        <input type="text" placeholder="请输入名字" v-model="keyWord">
        <button @click="sortType=0">年龄升序</button>
        <button @click="sortType=1">年龄降序</button>
        <button @click="sortType=2">原顺序</button>
        <ul>
            <li v-for="(p,index) in filPersons" :key="p.id">
                {{p.name}}-{{p.age}}
            </li>
        </ul>
    </div>

    <script>
        new Vue({
            el: '#root',
            // 0为原顺序,1为降序,2为升序
            data: {
                keyWord: '',
                sortType: 0,
                persons: [
                    {
                        id: 001,
                        name: '马冬梅',
                        age: 28,
                        gender: ''
                    },
                    {
                        id: 002,
                        name: '周冬雨',
                        age: 20,
                        gender: ''
                    },
                    {
                        id: 003,
                        name: '周杰伦',
                        age: 30,
                        gender: ''
                    },
                    {
                        id: 004,
                        name: '温兆伦',
                        age: 35,
                        gender: ''
                    }
                ],
            },
            // 计算属性的依赖属性改变时也会重新执行!
            computed: {
                filPersons() {
                    const arr = this.persons.filter(e => {
                        return e.name.indexOf(this.keyWord) !== -1
                    })
                    // 判断是否需要排序
                    if (this.sortType) {
                        this.sortType === 1 ? arr.sort((x, y) => {
                            return x.age - y.age
                        }) : arr.sort((x, y) => {
                            return y.age - x.age
                        })
                    }
                    return arr
                }
            }
        })
    </script>

 

posted @ 2022-10-12 10:21  HM-7  阅读(36)  评论(0)    收藏  举报