vue基础--动态class、动态style、过滤器filter、方法methods、计算属性computed、侦听器watch

目录

 一、动态class 

 1.1 基本用法

1.2 示例

二 、动态style

2.1 基本用法

2.2 示例

三、过滤器filter

3.1 定义使用

3.2 额外用法--传参和多过滤器

3.4 综合示例

四、方法methods

4.1 .使用绑定事件的方式

4.2 在插值表达式里({{}})

五、计算属性computed

5.1 语法

5.3 计算属性完整写法

六、侦听器watch

6.1 初识侦听器

6.2 侦听器的基本使用

6.3 深度侦听

6.4 watch 和 watchEffect

七、字符串补全长度功能

7.1 基本用法

7.2 示例


 一、动态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>