继上一篇关于的动态属性和v-model内容的补充,计算属性和侦听器
目录
2.v-model (v-model实现原理,v-model自动收集表单数据和ref来获取表单数据)
1.动态绑定style
关于style的动态绑定有 5 种方法:
第一种:对象形式
第二种:数组形式
第三种:三目运算符形式
第四种:绑定计算属性 computed
第五种:通过条件绑定样式
注意:
1、凡是有 - 的style属性名都要变成驼峰式,比如font-size要变成fontSize。
2、除了绑定值,其他的属性名的值要用引号括起来,比如fontSize:'14px'而不是 fontSize:14px。
<template>
<div>
<!-- 第一种:对象形式 -->
<div :style="{ color: 'green', fontSize: '20px' }">第一种:对象形式</div>
<div :style="styleObject">第一种</div>
<!-- 第二种:数组形式 -->
<div :style="[baseStyles, overridingStyles]">第二种</div>
<!-- 第三种:三目运算符形式 -->
<div class="three" :style="{ background: index === 0 ? 'skyblue' : 'pink' }">第三种</div>
<div class="three" :style="[{ color: index === 0 ? 'orange' : 'green' }, { fontSize: '30px' }]">第三种</div>
<!-- 第四种:绑定计算属性 computed -->
<div class="four" :style="setIconStyle">第四种</div>
<!-- 第五种:通过条件绑定样式 -->
<div class="five" :style="setStyle(0)">第五种(蓝)</div>
<div class="five" :style="setStyle(1)">第五种(粉)</div>
</div>
</template>
<script>
export default {
data() {
return {
styleObject: {
color: 'red',
fontSize: '30px'
},
baseStyles: {
width: '100px',
height: '100px'
},
overridingStyles: {
backgroundColor: 'skyblue',
height: '200px'
}
}
},
computed: {
// 动态设置样式
setIconStyle() {
return 'color: skyblue; fontSize: 30px'
},
setStyle() {
return function (index) {
return index === 0 ? 'background: skyblue' : 'background: pink'
}
}
}
}
</script>
<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped lang="less">
.three {
width: 100px;
height: 100px;
border: 1px solid black;
}
.four {
width: 100px;
height: 100px;
background-color: gold;
}
.five {
width: 100px;
height: 100px;
}
</style>
绑定计算属性和v-for运用:
注意的是计算属性返回函数的形式
<template>
<div class="container">
<div v-for="(item, index) in items"
:key="index"
class="item.name"
:style="itemObject(item)"
>
{{ item.name }}
</div>
</div>
</template>
<script>
export default {
data() {
return {
items: [
{
'name': 'FAN_1',
'background': 'skyblue',
},
{
'name': 'FAN_2',
'background': 'pink',
},
{
'name': 'FAN_3',
'background': 'orange',
}
]
}
},
computed: {
itemObject(item) {
// 需要以函数的形式返回样式,直接返回对象需要加括号,不加括号就认为是箭头函数的大括号了。
return (item) => ({
backgroundColor: item.background,
})
}
}
}
</script>
这里要注意:如果使用计算属性,返回的是函数的形式,直接返回对象需要加括号,不加括号就认为是箭头函数的大括号了。(如上面例子)
2.v-model (v-model实现原理,v-model自动收集表单数据和ref来获取表单数据)
v-model实现原理:
1、通过v-bind 来绑定变量(响应式数据 data里的)
2、监听input事件($event
,该事件的事件对象), 把变化后的值,赋值给绑定的变量
<template>
<div>
<p>
<!-- 动态绑定 -->
<input type="text" :value="msg" @input="getVal" placeholder="输入内容">
<!-- 简写 -->
<input type="text" :value="msg" @input="msg = $event.target.value"
placeholder="输入内容">
</p>
<p>{{ msg }}</p>
</div>
</template>
<script>
export default {
data() {
return {
msg: ''
}
},
methods: {
getVal(e) {
// target属性就用于返回最初触发事件的DOM元素
this.msg = e.target.value;
}
}
}
</script>
v-model自动收集表单数据:
v-model指令在表单控件元素上创建双向数据绑定
说到双向数据绑定就要讲到MVVM模型
MVVM模型:
M: model 数据层
V: View 视图层
VM: 视图模型 作为桥梁
通过下面列子,来更好的理解双向数据绑定:
<template>
<div>
<p>
用户名: <input type="text" v-model="userInfo.username">
</p>
<p>
性别:男<input type="radio" name="sex" value="男" v-model="userInfo.sex">
女<input type="radio" name="sex" value="女" v-model="userInfo.sex">
</p>
<p>
爱好:足球:<input type="checkbox" name="hobbies" value="足球" v-model="userInfo.hobbies">
篮球:<input type="checkbox" name="hobbies" value="篮球" v-model="userInfo.hobbies">
乒乓球:<input type="checkbox" name="hobbies" value="乒乓球" v-model="userInfo.hobbies">
</p>
<p>
<select v-model="userInfo.city">
<option value="北京">北京</option>
<option value="合肥">合肥</option>
<option value="成都">成都</option>
</select>
</p>
<p>
<button @click="getValue">提交</button>
</p>
</div>
</template>
<script>
export default {
data() {
return {
userInfo: {
// 初识默认值
username: 'my name is vue',
sex: '男',
hobbies: ['足球', '篮球'],
city: '成都'
}
}
},
methods: {
getValue() {
console.log(this.userInfo);
}
}
}
</script>
注意:写入input的value值,所有表单元素绑定的都是value属性(v-model与value对应)
得到的内容:
不仅v-model能获取表单中的数据, ref也可以
ref来获取表单数据:
ref: 给组件(input框)起名字,相当于id标记,通过 this.$refs.名字 获取dom元素或组件
<template>
<div>
<!-- 作用1: 获取dom元素 -->
<!-- 作用2: 获取组件 -->
<input type="text" ref="myRef">
<button @click="getVal">获取表单数据</button>
<h3 ref="h3Ref">我是一个h3标签</h3>
</div>
</template>
<script>
export default {
methods: {
getVal() {
// 获取输入框
console.log(this.$refs.myRef);
// 获取框内值
console.log(this.$refs.myRef.value);
console.log(this.$refs.h3Ref.innerHTML);
}
}
}
</script>
内容展示:
3.计算属性
计算属性(computed):由计算得来的属性(现有的属性)叫做计算属性
computed是属性,直接写名字不用加小括号,小括号是函数调用
看下面列子,用不同的方式来实现姓+名的展示
<template>
<div>
<p>
<!-- 绑定默认值 -->
<input type="text" v-model="firstname">
<input type="text" v-model="lastname">
</p>
<p>输出方式:姓 + 名</p>
<!-- 第一种:js拼接 -->
<p>js拼接: {{ firstname + '+' + lastname }}</p>
<!-- 第二种:函数方式 -->
<p>函数方式: {{ getFullName() }}</p>
<!-- 第三种:计算属性 -->
<p>计算属性写法: {{ fullName }}</p>
</div>
</template>
<script>
export default {
data() {
return {
firstname: '',
lastname: ''
}
},
methods: {
getFullName() {
return this.firstname + '+' + this.lastname;
}
},
computed: {
fullName() {
return this.firstname + '+' + this.lastname;
}
}
}
</script>
内容展示:
这里需要特别注意计算属性和函数的区别:
函数方法:不存在缓存,调用几次,执行几次,每次调用都会重新执行
计算属性:只调用一次,当现有属性变化后,才会重新调用,基于他的依赖进行缓存,依赖不变,计算属性不变
具体展示看下面例子:
<template>
<div>
<p>函数方式: {{ getFullName() }}</p>
<p>函数方式: {{ getFullName() }}</p>
<p>函数方式: {{ getFullName() }}</p>
<p>计算属性写法: {{ fullName }}</p>
<p>计算属性写法: {{ fullName }}</p>
<p>计算属性写法: {{ fullName }}</p>
</div>
</template>
<script>
export default {
methods: {
getFullName() {
console.log('函数写法调用了');
}
},
computed: {
fullName() {
console.log('计算属性调用了');
}
}
}
</script>
这里我们看到了函数方法和计算属性都调了三次,控制台打印的结果却是:函数打印3次,计算属性打印了1次
4.侦听器
侦听器(watch):监听已有属性的变化,当侦听到变化后,执行相应的函数
计算属性和侦听器的区别:
计算属性:由计算得来的属性,它不需要在data中提前声明,因为它是由现有属性计算而来
侦听器: 侦听的属性和侦听属性变化后要修改的属性,都必须要做data中提前声明
内容有:侦听器的简写方法,完整写法和延迟执行
侦听器的简写方法:第一次不侦听,只有变化后才侦听
<template>
<div>
<p>姓:<input type="text" v-model="firstname"></p>
<p>名:<input type="text" v-model="lastname"></p>
<p>fullname: {{ fullname }}</p>
</div>
</template>
<script>
export default {
data() {
return {
firstname: '123',
lastname: '456',
fullname: ''
}
},
watch: {
// 简写方法:第一次不侦听,只有变化后才侦听
firstname(newVal) {
console.log('firstname变化了...',newVal);
this.fullname = newVal + this.lastname;
}
}
}
</script>
内容展示:对input中的内容没有修改的时候,控制台没有打印信息,证明简写方法第一次是不会侦听的
让我们来看看完整写法: 完整写法是一上来就侦听
<template>
<div>
<p>姓:<input type="text" v-model="firstname"></p>
<p>名:<input type="text" v-model="lastname"></p>
<p>fullname: {{ fullname }}</p>
</div>
</template>
<script>
export default {
data() {
return {
firstname: '123',
lastname: '456',
fullname: ''
}
},
watch: {
// 完整写法:一上来就侦听
firstname: {
handler(newVal,oldVal) {
console.log('firstname变化了...',newVal);
this.fullname = newVal + this.lastname;
},
immediate: true // 无论有没有侦听到变化,都执行一次上面的回调
}
}
}
</script>
immediate: true ,意思是无论有没有侦听到变化,都执行一次上面的回调
我们再来看控制台内容,刚进来没有对input内容进行更改,控制台仍然打印了信息
侦听器的延迟执行:可以使用异步
<template>
<div>
<p>姓:<input type="text" v-model="firstname"></p>
<p>名:<input type="text" v-model="lastname"></p>
<p>fullname: {{ fullname }}</p>
</div>
</template>
<script>
export default {
data() {
return {
firstname: '123',
lastname: '456',
fullname: ''
}
},
watch: {
// 延迟执行
firstname: {
handler(newVal, oldVal) {
// 侦听器里可以用异步
setTimeout(() => {
this.fullname = newVal + this.lastname;
}, 2000)
},
immediate: true
}
}
}
</script>
上面延迟执行的效果就是input修改的内容延后2s
我也是个小白😂,如果内容有什么不对或者不严谨的地方欢迎大家指出,感谢阅读!!!