vue基础--动态class、动态style、过滤器filter、方法methods、计算属性computed、侦听器watch
目录
一、动态class
1.1 基本用法
目标: 用v-bind给标签class设置动态的值
语法 :class="{类名: 布尔值}"
1.2 示例
<template>
<div id="app">
<p :class="{red: bool}">动态class</p>
</div>
</template>
<script>
export default {
name: 'App',
components: {
},
data () {
return {
bool: true
}
},
methods: {
}
}
</script>
<style scoped lang="less">
.red {
color: red;
}
</style>
二 、动态style
2.1 基本用法
目标: 给标签动态设置style的值
语法 :style="{css属性名: 值}"
2.2 示例
<template>
<div id="app">
<p :style="{color: colorStr}">动态class</p>
</div>
</template>
<script>
export default {
name: 'App',
components: {
},
data () {
return {
colorStr: 'blue'
}
},
methods: {
}
}
</script>
公共部分:
<div id="root"></div>
<script src="https://unpkg.com/vue@next"></script>
三、过滤器filter
目标: 转换格式, 过滤器就是一个函数, 传入值返回处理后的值
VUE3.0已经移除了过滤器
3.1 定义使用
vue 中过滤器只能用在, 插值表达式和v-bind动态属性里
Vue中的过滤器场景:
- 传入一个值,得到处理后的值,例如:
- 字符串翻转, "输入hello, world", 输出"dlrow ,olleh”
- 字母转大写, 输入"hello", 输出"HELLO”
- ......
语法:
Vue.filter("过滤器名", (值) => {return "返回处理后的值"})--全局过滤器
filters: {过滤器名字: (值) => {return "返回处理后的值"}
a.全局过滤器:
main.js,
Vue.config.productionTip = false
// 方式1 定义全局过滤器--可以在任意的 .vue 文件里直接使用
Vue.filter("reverse", val => {
val.split('').reverse().join('')
})
x.vue,
<template>
<div id="app">
<p>{{msg | reverse}}</p>
</div>
</template>
<script>
export default {
data() {
return {
msg: 'hellw word',
};
},
methods: {
},
};
</script>
b.局部过滤器:
<template>
<div id="app">
<!--全局过滤器-->
<p>{{msg | reverse}}</p>
<!-- 局部过滤器 -->
<p :title="msg | toUp">鼠标长时间停留:</p>
</div>
</template>
<script>
export default {
data() {
return {
msg: 'hellw word',
};
},
// 方式2--局部过滤器
filters: {
toUp (val) {
return val.toUpperCase()
}
},
methods: {
},
};
</script>
3.2 额外用法--传参和多过滤器
可同时使用多个过滤器, 或者给过滤器传参
语法:
- 过滤器传参: vue变量 | 过滤器(实参)
- 多个过滤器: vue变量 | 过滤器1 | 过滤器2
i.传参--全局过滤器:
main.js,
// 方式1 定义全局过滤器--可以在任意的 .vue 文件里直接使用
Vue.filter("reverse", (val ,s) => {
return val.split('').reverse().join(s)
})
x.vue,
<p>{{msg | reverse('|')}}</p>
ii. 传参--局部过滤器:
<template>
<div id="app">
<!--全局过滤器-->
<p>{{msg | reverse('|')}}</p>
<!-- 局部过滤器 -->
<p :title="msg | toUp('|')">鼠标长时间停留:</p>
</div>
</template>
<script>
export default {
data() {
return {
msg: 'hellw word',
};
},
// 方式2--局部过滤器
filters: {
toUp (val, s) {
return val.toUpperCase(s)
}
},
methods: {
},
};
</script>
iii.多个过滤器--
main.js,
// 方式1 定义全局过滤器--可以在任意的 .vue 文件里直接使用
Vue.filter("reverse", (val ,s) => {
return val.split('').reverse().join(s)
})
x.vue,
<template>
<div id="app">
<!--全局过滤器-->
<p>{{msg | reverse('|')}}</p>
<!-- 局部过滤器 -->
<p :title="msg | toUp() | reverse('|')">鼠标长时间停留:</p>
</div>
</template>
<script>
export default {
data() {
return {
msg: 'hellw word',
};
},
// 方式2--局部过滤器
filters: {
toUp (val, s) {
return val.toUpperCase(s)
}
},
methods: {
},
};
</script>
3.4 综合示例
用于一些常见的文本格式化
过滤器可以用在两个地方:双花括号插值和 v-bind
表达式 (后者从 2.1.0+ 开始支持)
过滤器应该被添加在 JavaScript 表达式的尾部,由“管道”符号指示
<!-- 在双花括号中 -->
{{ message | capitalize }}
<!-- 在 `v-bind` 中 -->
<div v-bind:id="rawId | formatId"></div>
App.vue
<template>
<div id="app">
<ul>
<li v-for="(item,index) in order" :key="index">
<span>{{ item.name }}</span><span>{{ item.price | meony }}</span>
</li>
</ul>
<div>
<p>{{ bookName | author }}</p>
<p>{{ '浪流地球' | author }}</p>
<p>{{ bookName | author | meony }}</p>
</div>
</div>
</template>
<script>
export default {
name: 'App',
data(){
return{
bookName:"三体",
order:[
{
id:1001,
name:"纸巾",
price:59
},
{
id:1002,
name:"衣服",
price:399
}
]
}
},
// 局部过滤器
filters:{
author:function(val){
if(val){
return val + " 作者:大刘"
}
}
},
components: {
},
}
</script>
<style>
#app {
font-family: Avenir, Helvetica, Arial, sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
text-align: center;
color: #2c3e50;
margin-top: 60px;
}
</style>
main.js
import Vue from 'vue'
import App from './App.vue'
import './registerServiceWorker'
import "./filters"
Vue.config.productionTip = false
new Vue({
render: h => h(App),
}).$mount('#app')
filters/index.js
import Vue from "vue"
//全局过滤器
Vue.filter("meony", function(val) {
if (val) {
return "¥" + val
};
})
注意:
- 当全局过滤器和局部过滤器重名时,会采用局部过滤器
- 过滤器可以串联
-
{{ message | filterA | filterB }}
- 全局过滤器可以在任何一个Vue实例控制的区域中使用
- 局部过滤器只能在自定义的那个Vue实例中使用
四、方法methods
专门用于存储监听事件回调函数
4.1 .使用绑定事件的方式
在 methods 定义的函数,不要使用箭头函数,因为如果使用了箭头函数,这该函数的this则指向了windows,而不是vue实例:
<script>
//生命周期函数:在某一时刻会自动执行的函数
const app = Vue.createApp({
data() {
return {
message: 'hello world'
}
},
methods: {
handleClick() {
console.log('click', this);
}
//handleClick: () => {
// console.log('click', this);
// }
},
template: `
<div @click="handleClick">{{message}}</div>
`
});
//将组件挂到root节点里,即只作用在id等于root的div元素里
//vm 代表的就是 vue 应用的根组件
const vm = app.mount('#root');
//vm.$data 获得数据
// vm.$data.message = 'root';
</script>
未使用箭头函数,
使用箭头函数,
4.2 在插值表达式里({{}})
<script>
//生命周期函数:在某一时刻会自动执行的函数
const app = Vue.createApp({
data() {
return {
message: 'hello world'
}
},
methods: {
formatString(string) {
return string.toUpperCase();
}
},
template: `
<div>{{formatString(message)}}</div>
`
});
//将组件挂到root节点里,即只作用在id等于root的div元素里
//vm 代表的就是 vue 应用的根组件
const vm = app.mount('#root');
//vm.$data 获得数据
// vm.$data.message = 'root';
</script>
五、计算属性computed
专门用于定义计算属性的
目标: 一个变量的值, 依赖另外一些数据计算而来的结果
5.1 语法
语法:
应用场景:当一个变量的值,需要用另外变量计算而得来
计算属性好处是?
- 带缓存
- 依赖项不变, 直接从缓存取
- 依赖项改变, 函数自动执行并重新缓存
5.2 注意事项
虽然在定义计算属性时是通过一个函数返回的数据,但是在使用计算属性时不能在计算属性名称后加上(),因为它是一个属性不是一个函数(方法)
计算属性和data属性度数变量,因此不能重名
<template>
<div class="app">
<p>{{total}}</p>
<p>{{getTotal()}}</p>
</div>
</template>
<script>
export default {
data () {
return {
message: 'hello world',
count: 2,
price: 5
}
},
computed: {
//当计算属性依赖的内容发生变更时,才会重新执行计算
total () {
// return Date.now();
return this.count * this.price;
}
},
methods: {
// 只要页面重新渲染,就会重新执行计算
getTotal () {
return Date.now();
}
},
}
</script>
在上面代码中 total() 和 getTotal(),实现的功能都是一样的,但是区别在于 computed 里面的方法只有在当它依赖的属性发生变化时,也就是 count、price发生变化时,才会重新计算;而 methods 里面的方法,只要页面重新渲染,就会重新执行计算
computed 和 methods 都能实现的一个功能时,建议使用 computed, 因为有缓存
由于计算属性会将返回的结果缓存起来,如果返回的数据不经常发生变化,则使用计算属性(computed )的性能高于函数(methods )的性能 ,反之使用函数(methods )
5.3 计算属性完整写法
计算属性也是变量--计算属性实现双向绑定
应用场景:给计算属性变量赋值时
语法:
<template>
<div class="app">
<div>
<span>姓名:</span>
<input type="text"
v-model="full">
</div>
</div>
</template>
<script>
export default {
data () {
return {
}
},
computed: {
full: {
// 给 full 赋值触发 set()
set(val) {
console.log(val);
},
// 使用 full 的值触发 get()
get(val) {
return 'zs'
}
}
},
}
</script>
六、侦听器watch
6.1 初识侦听器
主动侦听data/computed变量“值”的改变
语法:
watch: {
"被侦听的属性名": (newVal1, oldVal){
}
},
6.2 侦听器的基本使用
使用场景:
当需要在数据变化时执行异步或开销较大的操作时,使用侦听器是最有用的
<template>
<div id="app">
<input type="text" v-model="name">
</div>
</template>
<script>
export default {
data () {
return {
name: ''
}
},
watch: {
// 侦听到 name 值的改变
name(newVal, oldVal){
console.log('新值为:' + newVal, '旧值为:' + oldVal);
}
},
}
</script>
6.3 深度侦听
侦听复杂类型, 或者立即执行侦听函数
语法:
watch: {
// 深度侦听
"要侦听的属性名": {
immediate: true, // 立即执行
deep: true, // 深度侦听复杂类型的变化
handler (newVal, oldVal) {}
}
},
示例,
<template>
<div id="app">
<!-- 基本用法 -->
<!-- <input type="text" v-model="name"> -->
<input type="text" v-model="user.name">
<input type="text" v-model="user.age">
</div>
</template>
<script>
export default {
data () {
return {
name: '',
user: {
name: 'zs',
age: 20
}
}
},
watch: {
// 侦听到 name 值的改变
// 基本用法
// name(newVal, oldVal){
// console.log('新值为:' + newVal, '旧值为:' + oldVal);
// }
// 深度侦听
user: {
deep: true, // 深度侦听
immediate: true, // 立即执行
handler(newVal, oldVal){
// console.log('新值为:' + newVal, '旧值为:' + oldVal); // 打印的是 user 里的对象
}
}
},
}
</script>
注意:
computed 和 watch 都能实现的一个功能,建议使用 computed,因为更加简洁
6.4 watch 和 watchEffect
公共部分:
<script src="https://unpkg.com/vue@next"></script>
<div id="root"></div>
i.watch
- 具备一定的惰性
- 有两个参数,可以拿到原始值(prevValue)和当前值(currentValue)
- Watch属性是专门用于监听数据变化的, 只要数据发生了变化, 就会自动调用对应数据的回调方法
- Watch属性不仅仅能够监听数据的变化, 还能够监听路由地址的变化
- 在企业开发中我们可以通过Watch来判断当前界面是从哪个界面跳转过来的
示例1:监听一个数据的变化
<script>
const app = Vue.createApp({
setup() {
const {
reactive,
watch,
toRefs
} = Vue;
const nameObj = reactive({
name: 'dell'
});
//当写的是 reactive 对应的响应式引用时,需要在前面写一个箭头函数:() => {nameObj.name}
watch(() => {
nameObj.name
}, (currentValue, prevValue) => {
// console.log(currentValue, prevValue);
});
const {
name
} = toRefs(nameObj);
return {
name
}
},
template: `
<div>
Name:<input v-model="name" />
</div>
<div>
Name is {{name}}
</div>
`
});
const vm = app.mount('#root');
</script>
示例2:监听多个数据的变化
<script>
const app = Vue.createApp({
setup() {
const {
reactive,
watch,
toRefs
} = Vue;
const nameObj = reactive({
name: 'dell',
englishName: 'jack'
});
//当写的是 reactive 对应的响应式引用时,需要在前面写一个箭头函数:() => {nameObj.name}
watch([() => nameObj.name, () => nameObj.englishName], ([curName, curEng], [preName, preEng]) => {
console.log(curName, preName, '-----', curEng, preEng);
})
const {
name,
englishName
} = toRefs(nameObj);
return {
name,
englishName
}
},
template: `
<div>
Name:<input v-model="name" />
</div>
<div>
Name is {{name}}
</div>
<div>
EnglishName:<input v-model="englishName" />
</div>
<div>
EnglishName is {{englishName}}
</div>
`
});
const vm = app.mount('#root');
</script>
将 watch 变为非惰性:
//当写的是 reactive 对应的响应式引用时,需要在前面写一个箭头函数:() => {nameObj.name}
watch([() => nameObj.name, () => nameObj.englishName], ([curName, curEng], [preName, preEng]) => {
console.log(curName, preName, '-----', curEng, preEng);
}, { //将 watch 变为非惰性
immediate: true
})
ii.watchEffect
- 立即执行,没有惰性
- 不需要传递你要监听的内容,自动会感知代码依赖
- 不需要传递太多参数,只需传递一个回调函数
- 只能获取之前数据当前的值,无法获取数据之前的值
<script>
const app = Vue.createApp({
setup() {
const {
reactive,
watch,
toRefs,
watchEffect
} = Vue;
const nameObj = reactive({
name: 'dell',
englishName: 'jack'
});
//当写的是 reactive 对应的响应式引用时,需要在前面写一个箭头函数:() => {nameObj.name}
const stop1 = watch([() => nameObj.name, () => nameObj.englishName], ([curName, curEng], [preName, preEng]) => {
console.log(curName, preName, '-----', curEng, preEng);
setTimeout(() => {
stop1();
}, 3000)
})
const stop = watchEffect(() => {
console.log(nameObj.name);
console.log(nameObj.englishName);
setTimeout(() => {
stop();
}, 2000)
})
const {
name,
englishName
} = toRefs(nameObj);
return {
name,
englishName
}
},
template: `
<div>
Name:<input v-model="name" />
</div>
<div>
Name is {{name}}
</div>
<div>
EnglishName:<input v-model="englishName" />
</div>
<div>
EnglishName is {{englishName}}
</div>
`
});
const vm = app.mount('#root');
</script>
七、字符串补全长度功能
7.1 基本用法
- padStart()用于头部补全,padEnd()用于尾部补全
- 一共接受两个参数,第一个参数用来指定字符串的最小长度,第二个参数是用来补全的字符串
- 如果原字符串的长度,等于或大于指定的最小长度,则返回原字符串
'xxx'.padStart(2, 'ab') // 'xxx'
'xxx'.padEnd(2, 'ab') // 'xxx'
- 如果用来补全的字符串与原字符串,两者的长度之和超过了指定的最小长度,则会截去超出位数的补全字符串
'abc'.padStart(10, '0123456789')
// '0123456abc'
- 如果省略第二个参数,默认使用空格补全长度
'x'.padStart(4) // ' x'
'x'.padEnd(4) // 'x '
7.2 示例
需求: 利用过滤器对时间进行格式化
<template>
<div id="app">
<p>{{time | dateFormate("yyyy-MM-dd")}}</p>
</div>
</template>
<script>
export default {
data () {
return {
time: Date.now()
}
},
filters: {
dateFormate (value, fmStr) {
// console.log(fmStr);
let date = new Date(value);
let year = date.getFullYear();
let month = date.getMonth() + 1 + "";
let day = date.getDate() + "";
let hour = date.getHours() + "";
let minute = date.getMinutes() + "";
let second = date.getSeconds() + "";
if (fmStr && fmStr === "yyyy-MM-dd") {
return `${year}-${month.padStart(2, "0")}-${day.padStart(2, "0")}`;
}
return `${year}-${month.padStart(2, "0")}-${day.padStart(2, "0")} ${hour.padStart(2, "0")}:${minute.padStart(2, "0")}:${second.padStart(2, "0")}`;
}
},
}
</script>