Vue学习笔记(第三天)

30 阅读4分钟

本文已参与「新人创作礼」活动, 一起开启掘金创作之路。

Vue学习笔记(第三天)

计算属性

1.姓名案例-插值语法实现

根据之前所学,使用基本的插值语法,通过v-model实现数据与页面展示的双向绑定,即可实现功能

image.png image.png

    <div id="root">
        姓:<input type="text" v-model="firstName"><br><br>
        名:<input type="text" v-model="lastName"><br><br>
        全名:<span>{{firstName}}-{{lastName}}</span>
    </div>
    
   <script type="text/javascript">
    new Vue({
        el: '#root',
        data: {
            firstName: '张',
            lastName: '三'
        },
    })
</script>

2.姓名案例-methods实现

    <div id="root">
        姓:<input type="text" v-model="firstName"><br><br>
        名:<input type="text" v-model="lastName"><br><br>
        全名:<span>{{fullName()}}</span>
    </div>
    
    <script type="text/javascript">
    new Vue({
        el: '#root',
        data: {
            firstName: '张',
            lastName: '三'
        },
        methods: {
            fullName() {
                return this.firstName + '-' + this.lastName
            }
        },
    })
</script>

3.姓名案例-计算属性实现

计算属性:

  1. 定义:要用的属性不存在,要通过已有属性计算得来
  2. 原理:底层借助了Object.defineproperty方法提供的getter和setter
  3. get函数什么时候执行?
    • 初次读取时会执行一次
    • 当依赖的数据发生改变时会被再次调用
  4. 优势:与methods实现相比,内部有缓存机制(复用),效率更高,调用方便
  5. 备注
  • 计算属性最终会出现在vm上,直接读取使用即可
  • 如果计算属性要被修改,那必须写set函数去响应修改,且set中要引起计算时依赖的数据发生改变
<div id="root">
        姓:<input type="text" v-model="firstName"><br><br>
        名:<input type="text" v-model="lastName"><br><br>
        全名:<span>{{fullName}}</span><br><br>
    </div>
computed: {//计算属性
            fullName: {
                // get有什么作用?当有人读取fullName时,get就会被调用,且返回值就作为fullName的值
                // get什么时候调用?1.初次读取fullName时。2.所依赖的数据发生变化时。
                get() {
                    console.log('get被调用了')
                    // console.log(this);
                    return this.firstName + '-' + this.lastName
                },
                //set什么时候调用?当fullName被修改时
                set(value) {
                    console.log('set', value)
                    const arr = value.split('-')
                    this.firstName = arr[0];
                    this.lastName = arr[1];
            }
        }
    }

当然计算属性有简写了

        // 简写 只有在只考虑读取,不考虑修改的情况下才能简写
        fullName() {
            console.log('get被调用了')
            return this.firstName + '-' + this.lastName
        }

监视属性

1.天气案例

没学监视属性时,我们是这样实现的

    <div id="root">
        <h2>今天天气很{{info}}</h2>
        <!-- <button @click="this.isHot = !this.isHot">切换天气</button> -->
        <button @click="changeWeather">切换天气</button>
    </div>
    
    new Vue({
        el: '#root',
        data: {
            isHot: true
        },
        methods: {
            changeWeather() {
                this.isHot = !this.isHot
            }
        },
        computed: {
            info() {
                return this.isHot ? '炎热' : '凉爽'
            }
        }
    })

2.天气案例-监视属性

监视属性watch:

  1. 当被监视的属性变化时,回调函数自动调用,进行相关操作
  2. 监视的属性必须存在,才能进行监视
  3. 监视的两种写法 (1)new Vue时传入watch配置 (2)通过vm.$watch监视

在上面的基础上,我们进行增加

(1)new Vue时传入watch配置

watch: {
         isHot: {
            immediate: true,//初始化时让handler调用一下
            //handler什么时候调用?当isHot发生修改
            handler(newValue, oldValue) {
                console.log('isHot被修改了', newValue, oldValue);
        }
    }, 

(2)通过vm.$watch监视

vm.$watch('isHot', {
        immediate: true,
        handler(newValue, oldValue) {
            console.log('info被修改了', newValue, oldValue);
        }
    })

3.天气案例-深度监视

深度监视:

  1. Vue中的watch默认不监测对象内部值的改变(一层)
  2. 配置deep:true可以监测对象内部值的改变(多层)

备注:

  • Vue自身可以监测对象内部值的改变,但Vue提供的watch默认不可以
  • 使用watch时根据数据的具体结构,决定是否采用深度监视
    <div id="root">
        <h2>今天天气很{{info}}</h2>
        <!-- <button @click="this.isHot = !this.isHot">切换天气</button> -->
        <button @click="changeWeather">切换天气</button>
        <hr>
        <h3>a的值是:{{numbers.a}}</h3>
        <button @click="numbers.a++">点我让a+1</button>
        <hr>
        <h3>b的值是:{{numbers.b}}</h3>
        <button @click="numbers.b++">点我让b+1</button>
        <button @click="numbers={a:666,b:888}">彻底替换掉numbers</button>
    </div>

image.png

image.png

深度监视的两种简写形式如下

image.png

image.png


4.姓名案例-watch实现

computed 和 watch之间的区别:

  • computed能完成的功能,watch都可以完成
  • watch能完成的功能,computed不一定能完成,例如watch可以进行异步操作

两个重要的小原则:

  1. 所被Vue管理的函数,最好写成普通函数,这样this的指向才是vm或组件实例对象
  2. 所有不被Vue所管理的函数(定时器的回调函数、ajax的回调函数等),最好写成箭头函数。这样this的指向才是vm或组件实例对象
    <div id="root">
        姓:<input type="text" v-model="firstName"><br><br>
        名:<input type="text" v-model="lastName"><br><br>
        全名:<span>{{fullName}}</span><br><br>
    </div>
        watch: {
            firstName(val) {
                //箭头函数特点:本身不存在this,但是可以通过调用上下域中的this供自己使用
                setTimeout(() => {
                    this.fullName = val + '-' + this.lastName
                }, 1000)
            },
            lastName(val) {
                this.fullName = this.firstName + '-' + val
            }
        }

绑定样式

在已有多个样式的基础上,进行样式的绑定

        <!-- 绑定class样式--字符串写法 适用于:样式的类名不确定,需要动态绑定-->
        <div class="basic" :class="mood" @click="changeMood">{{name}}</div>

        <!-- 绑定class样式--数组写法 适用于:要绑定的样式个数不确定、名字也不确定-->
        <div class="basic" :class="classArr">{{name}}</div>

        <!-- 绑定class样式--对象写法,适用于:要绑定的样式个数确定、名字也确定,但要动态决定用不用 -->
        <div class="basic" :class="classObj">{{name}}</div>

        <!-- 绑定style样式--对象写法-->
        <div class="basic" :style="styleObj">{{name}}</div>
        <!-- 绑定style样式--数组写法-->
        <div class="basic" :style="[styleObj,styleObj2]">{{name}}</div>
data: {
            name: 'hhh',
            mood: 'normal',
            classArr: ['hh1', 'hh2', 'hh3'],
            classObj: {
                hh1: false,
                hh2: false
            },
            styleObj: {
                fontSize: '40px',
                color: 'red',
            },
            styleObj2: {
                backgroundColor: 'orange'
            },
        },

条件渲染

1.v-if
    写法:
    (1)v-if="表达式"
    (2)v-else-if="表达式"
    (3)v-else="表达式"
    适用于:切换频率较低的场景
    特点:不展示的DOM元素直接被移除
    注意:v-if可以和v-else-if、v-else一起使用,但要求结构不能被“打断”
2.v-show
    写法:v-show="表达式"
    适用于:切换频率较高的场景
    特点:不展示的DOM元素未被移除,仅仅是使用样式隐藏掉
3.备注:使用v-if的时,元素可能无法获取到,而使用v-show一定可以获取到
<div id="root">
    <h2>当前的n值是:{{n}}</h2>
    <button @click="n++">点我+1</button>

    <!-- 使用v-show做条件渲染 -->
    <!-- <h2 v-show="a">欢迎来到{{name}}</h2>
    <h2 v-show="true">欢迎来到{{name}}</h2>
    <h2 v-show="1===1">欢迎来到{{name}}</h2> -->

    <!-- 使用v-if做条件渲染 -->
    <!-- <h2 v-if="1===1">欢迎来到{{name}}</h2>
    <h2 v-if="true">欢迎来到{{name}}</h2> -->

    <!-- <div v-show="n===1">Angular</div>
    <div v-show="n===1">React</div>
    <div v-show="n===3">Vue</div> -->

    <!-- <div v-if="n===1">Angular</div>
    <div v-if="n===1">React</div>
    <div v-if="n===3">Vue</div> -->

    <!-- <div v-if="n===1">Angular</div>
    <div v-else-if="n===2">React</div>
    <div v-else-if="n===3">Vue</div>
    <div v-else>哈哈</div> -->

    <!-- v-if与templated的配合使用 -->
    <template v-if="n===1">
        <h2>你好</h2>
        <h2>!!</h2>
        <h2>北京</h2>
    </template>
</div>

new Vue({
        el: '#root',
        data: {
            name: '学校',
            a: true,
            n: 0
        },
    })