Vue 计算属性、监视属性、绑定样式

155 阅读3分钟

计算属性

  1. 姓名案例_插值语法实现
<body>
        <!-- 准备好一个容器-->
        <div id="root">
                姓:<input type="text" v-model="firstName"> <br/><br/>
                名:<input type="text" v-model="lastName"> <br/><br/>
                全名:<span>{{firstName}}-{{lastName}}</span>
        </div>
</body>
<script type="text/javascript">
        Vue.config.productionTip = false //阻止 vue 在启动时生成生产提示。
        new Vue({
                el:'#root',
                data:{
                        firstName:'张',
                        lastName:'三'
                }
        })
</script>
  1. 姓名案例_methods实现
<body>
        <div id="root">
                姓:<input type="text" v-model="firstName"> <br/><br/>
                名:<input type="text" v-model="lastName"> <br/><br/>
                全名:<span>{{fullName()}}</span>
        </div>
</body>

<script type="text/javascript">
        Vue.config.productionTip = false //阻止 vue 在启动时生成生产提示。
        new Vue({
                el:'#root',
                data:{
                        firstName:'张',
                        lastName:'三'
                },
                methods: {
                        fullName(){
                                console.log('@---fullName')
                                return this.firstName + '-' + this.lastName
                        }
                },
        })
</script>
  1. 计算属性实现
    • 定义:要用的属性不存在,要通过已有属性计算得来。
    • 原理:底层借助了Objcet.defineproperty方法提供的getter和setter。
    • get函数什么时候执行?(1).初次读取时会执行一次。(2).当依赖的数据发生改变时会被再次调用。
    • 优势:与methods实现相比,内部有缓存机制(复用),效率更高,调试方便。
    • 备注:1.计算属性最终会出现在vm上,直接读取使用即可。2.如果计算属性要被修改,那必须写set函数去响应修改,且set中要引起计算时依赖的数据发生改变。直接修改不行。
<body>
        <div id="root">
                姓:<input type="text" v-model="firstName"> <br /><br />
                名:<input type="text" v-model="lastName"> <br /><br />
                测试:<input type="text" v-model="x"> <br /><br />
                全名:<span>{{fullName}}</span> <br /><br />
                <!-- 全名:<span>{{fullName}}</span> <br/><br/>
                        全名:<span>{{fullName}}</span> <br/><br/>
                        全名:<span>{{fullName}}</span> -->
        </div>
</body>

<script type="text/javascript">
        Vue.config.productionTip = false //阻止 vue 在启动时生成生产提示。

        const vm = new Vue({
                el: '#root',
                data: {
                        firstName: '张',
                        lastName: '三',
                        x: '你好'
                },
                methods: {
                        demo() {

                        }
                },
                computed: {
                        fullName: {
                                //get有什么作用?当有人读取fullName时,get就会被调用,且返回值就作为fullName的值
                                //get什么时候调用?1.初次读取fullName时。2.所依赖的数据发生变化时。
                                get() {
                                        console.log('get被调用了')
                                        // console.log(this) //此处的this是vm
                                        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]
                                }
                        }
                }
        })
</script>

监视属性

  1. 天气案例_监视属性
    • 当被监视的属性变化时, 回调函数自动调用, 进行相关操作
    • 监视的属性必须存在,才能进行监视!!
    • 监视的两种写法:(1).new Vue时传入watch配置(2).通过vm.$watch监视
<body>
        <div id="root">
                <h2>今天天气很{{info}}</h2>
                <button @click="changeWeather">切换天气</button>
        </div>
</body>

<script type="text/javascript">
        Vue.config.productionTip = false //阻止 vue 在启动时生成生产提示。

        const vm = new Vue({
                el: '#root',
                data: {
                        isHot: true,
                },
                computed: {
                        info() {
                                return this.isHot ? '炎热' : '凉爽'
                        }
                },
                methods: {
                        changeWeather() {
                                this.isHot = !this.isHot
                        }
                },
                /* watch:{
                        isHot:{
                                immediate:true, //初始化时让handler调用一下
                                //handler什么时候调用?当isHot发生改变时。
                                handler(newValue,oldValue){
                                        console.log('isHot被修改了',newValue,oldValue)
                                }
                        }
                } */
        })

        vm.$watch('isHot', {
                immediate: true, //初始化时让handler调用一下
                //handler什么时候调用?当isHot发生改变时。
                handler(newValue, oldValue) {
                        console.log('isHot被修改了', newValue, oldValue)
                }
        })
</script>
  1. 深度监视
    • 深度监视:(1).Vue中的watch默认不监测对象内部值的改变(一层)。(2).配置deep:true可以监测对象内部值改变(多层)。
    • 备注:(1).Vue自身可以监测对象内部值的改变,但Vue提供的watch默认不可以!(2).使用watch时根据数据的具体结构,决定是否采用深度监视。
<div id="root">
        <h2>今天天气很{{info}}</h2>
        <button @click="changeWeather">切换天气</button>
        <hr/>
        <h3>a的值是:{{numbers.a}}</h3>
        <button @click="numbers.a++">点我让a+1</button>
        <h3>b的值是:{{numbers.b}}</h3>
        <button @click="numbers.b++">点我让b+1</button>
        <button @click="numbers = {a:666,b:888}">彻底替换掉numbers</button>
        {{numbers.c.d.e}}
</div>

data:{
        isHot:true,
        numbers:{
                a:1,
                b:1,
                c:{
                        d:{
                                e:100
                        }
                }
        }
},
watch:{
        isHot:{
                // immediate:true, //初始化时让handler调用一下
                //handler什么时候调用?当isHot发生改变时。
                handler(newValue,oldValue){
                        console.log('isHot被修改了',newValue,oldValue)
                }
        },
        //监视多级结构中某个属性的变化
        /* 'numbers.a':{
                handler(){
                        console.log('a被改变了')
                }
        } */
        //监视多级结构中所有属性的变化
        numbers:{
                deep:true,
                handler(){
                        console.log('numbers改变了')
                }
        }
}
  1. 简写
watch: {
        //正常写法
        /* isHot:{
                // immediate:true, //初始化时让handler调用一下
                // deep:true,//深度监视
                handler(newValue,oldValue){
                        console.log('isHot被修改了',newValue,oldValue)
                }
        }, */
        //简写
        isHot(newValue, oldValue) {
                console.log('isHot被修改了', newValue, oldValue, this)
        }
}

//正常写法
/* vm.$watch('isHot',{
        immediate:true, //初始化时让handler调用一下
        deep:true,//深度监视
        handler(newValue,oldValue){
                console.log('isHot被修改了',newValue,oldValue)
        }
}) */
//简写
vm.$watch('isHot',(newValue,oldValue)=>{
        console.log('isHot被修改了',newValue,oldValue,this)
})

computed和watch之间的区别

  1. computed能完成的功能,watch都可以完成。
  2. watch能完成的功能,computed不一定能完成,例如:watch可以进行异步操作。
  3. 两个重要的小原则:
    • 所被Vue管理的函数,最好写成普通函数,这样this的指向才是vm 或 组件实例对象。
    • 所有不被Vue所管理的函数(定时器的回调函数、ajax的回调函数等、Promise的回调函数),最好写成箭头函数,这样this的指向才是vm 或 组件实例对象。
<body>
	<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>
</body>

<script type="text/javascript">
	Vue.config.productionTip = false //阻止 vue 在启动时生成生产提示。

	const vm = new Vue({
		el: '#root',
		data: {
			firstName: '张',
			lastName: '三',
			fullName: '张-三'
		},
		watch: {
			firstName(val) {
				setTimeout(() => {
					console.log(this)
					this.fullName = val + '-' + this.lastName
				}, 1000);
			},
			lastName(val) {
				this.fullName = this.firstName + '-' + val
			}
		}
	})
</script>

绑定样式

  1. class样式
    • 写法:class="xxx" xxx可以是字符串、对象、数组。
    • 字符串写法适用于:类名不确定,要动态获取。
    • 对象写法适用于:要绑定多个样式,个数不确定,名字也不确定。
    • 数组写法适用于:要绑定多个样式,个数确定,名字也确定,但不确定用不用。
  2. style样式
    • :style="{fontSize: xxx}"其中xxx是动态值。
    • :style="[a,b]"其中a、b是样式对象。
<head>
	<meta charset="UTF-8" />
	<title>绑定样式</title>
	<style>
		.basic {
			width: 400px;
			height: 100px;
			border: 1px solid black;
		}

		.happy {
			border: 4px solid red;
			;
			background-color: rgba(255, 255, 0, 0.644);
			background: linear-gradient(30deg, yellow, pink, orange, yellow);
		}

		.sad {
			border: 4px dashed rgb(2, 197, 2);
			background-color: gray;
		}

		.normal {
			background-color: skyblue;
		}

		.one {
			background-color: yellowgreen;
		}

		.two {
			font-size: 30px;
			text-shadow: 2px 2px 10px red;
		}

		.three {
			border-radius: 20px;
		}
	</style>
	<script type="text/javascript" src="../js/vue.js"></script>
</head>

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

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

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

		<!-- 绑定style样式--对象写法 -->
		<div class="basic" :style="styleObj">{{name}}</div> <br /><br />
		<!-- 绑定style样式--数组写法 -->
		<div class="basic" :style="styleArr">{{name}}</div>
	</div>
</body>

<script type="text/javascript">
	Vue.config.productionTip = false

	const vm = new Vue({
		el: '#root',
		data: {
			name: 'aaa',
			mood: 'normal',
			classArr: ['one', 'two', 'three'],
			classObj: {
				one: false,
				two: false,
			},
			styleObj: {
				fontSize: '40px',
				color: 'red',
			},
			styleObj2: {
				backgroundColor: 'orange'
			},
			styleArr: [
				{
					fontSize: '40px',
					color: 'blue',
				},
				{
					backgroundColor: 'gray'
				}
			]
		},
		methods: {
			changeMood() {
				const arr = ['happy', 'sad', 'normal']
				const index = Math.floor(Math.random() * 3)
				this.mood = arr[index]
			}
		},
	})
</script>