侦听器

69 阅读4分钟

1. 侦听器

  1. 衍生值:通过多个值得到一个东西

  2. 后续的开发应该更改思想为数据驱动视图,一切操作应该基于数据发生改变去做什么事

  3. watch侦听首次默认不执行但是可以通过配置项控制首次打开执行,内部的名字就是你要侦听的响应式数据就的名字(计算属性或者data中都可以)当响应式数据发生变化就会执行内部代码

  4. 侦听器特性:一个值会影响多个值的变化

  5. 侦听器与ajax请求联合起来

 <!DOCTYPE html>
 <html lang='en'>

 <head>
 <meta charset='UTF-8'>
 <meta http-equiv='X-UA-Compatible' content='IE=edge'>
 <meta name='viewport' content='width=device-width, initial-scale=1.0'>
 <title>Document</title>
 <script src='./vue.global.js'></script>
 <script src="./axios.min.js"></script>
 <style>
     * {
         padding: 0;
         margin: 0;
         list-style: none;
     }

     .box {
         width: 500px;
         height: 600px;
         margin: 50px auto;
         border: 1px skyblue solid;
     }

     .box img {
         width: 100px;
         height: 100px;
     }
 </style>
 </head>

 <body>
 <div id='app'>
     <div class="box">
         <ul>
             <li v-for="item in goodsList">
                 <img :src="item.img_big_logo" alt="">
                 <span>
                     {{item.title}}
                 </span>
             </li>
         </ul>
         <button @click="prev">上一页</button>
         <span> {{current}}/{{goodsTotal}} </span>
         <button @click="next">下一页</button>
     </div>
 </div>
 <script>
     /**
      *  当前案例的逻辑:
     *      首次打开页面有一个生命周期 created 会执行, 调用了 this.getList 这个函数
     *          所以首次打开页面是有数据
     * 
     *      后续在操作的时候点击了某个按钮, 有可能会改变当前页码,
     *      如果改变了当前页码, 那么会触发侦听器内的 current
     *      这个侦听器执行的时候, 会调用一次 this.getList 这个函数, 所以页面的数据发生了变化
     */
     const app = Vue.createApp({
         data() {
             return {
                 current: 1,
                 goodsList: [],
                 goodsTotal: 0,
             }
         },

         methods: {
             prev() {
                 if (this.current === 1) return

                 this.current--
             },
             next() {
                 if (this.current === this.goodsTotal) return

                 this.current++
             },
             
             getList() {
                 
                 axios({
                     // url: `http://localhost:8888/goods/list?current=${this.current}&pagesize=5`,
                     url: `http://localhost:8888/goods/list`,
                     params: {
                         current: this.current,
                         pagesize: 4
                     },
                     methods: 'GET'
                 }).then(res => {
                     this.goodsList = res.data.list
                     this.goodsTotal = res.data.total
                 })
             },
             
         },
         
         // created() {
         //     this.getList()
         // },

         watch: {
             // 如果想给侦听器添加配置项, 需要更改另一种写法
             // current() {
             //     this.getList()`  ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ````````````````````````````````````````````````````````````````````````````````                                      
             // }
             current: {
                 handler() {
                     // 当前函数为固定的, 不要修改函数名, 把你要执行的代码 放在这个函数内
                     this.getList()
                 },
                 // 当前配置项表明的让 handler 这个函数立即执行一次
                 immediate: true,
                 /**
                   *  当前配置项表明会深度监听这个对象内部的所有属性
                   * 
                   *  注意: 这个配置项一般不要使用, 因为他会遍历你这个对象内部的所有属性, 然后全都添加一个侦听器
                   * 
                   *  所以如果在对象属性很多的时候, 这种操作会对内存性能有很大影响
                 */
                 // deep: true,

                 // 当前配置项会让当前回调的执行时机延迟到 真实DOM更新后
                 // flush: 'post'
             }
         }
     })
     app.mount('#app')
 </script>
 </body>

 </html>
  1. 侦听器中的首次打开执行: js // immediate: true, // 当前配置项表明的让 handler 这个函数立即执行一次

  2. 侦听器的深度侦听 ```js /**

    • 当前配置项表明会深度监听这个对象内部的所有属性
    • 注意: 这个配置项一般不要使用, 因为他会遍历你这个对象内部的所有属性, 然后全都添加一个侦听器
    • 所以如果在对象属性很多的时候, 这种操作会对内存性能有很大影响 */ // deep: true, ```
  3. 侦听器的延迟侦听: js // 当前配置项会让当前回调的执行时机延迟到 真实DOM更新后 // flush: 'post'

  4. 侦听器与计算属性区别 * 侦听器首次打开不会执行除非添加配置项或者侦听的值发生改变,但是计算属性首次打开会执行 * 侦听器内不需要写return,计算属性内需要写return * 侦听器内可以书写异步代码,计算属性内不能书写异步代码 * 侦听器里面没有缓存,计算属性里面有缓存 * 侦听器内一个值变化可以引起多个值修改,计算属性内多个值变化可以引起一个值修改

2. class与style的绑定

  1. class可以绑定对象,变量,数组 js :class ='{active:true,active1:false}' // true的时候会绑定上去,false不会 :class = 'classObj' classObj:{ active:true, active1:false // 此时只有第一个会绑定上 } :class = 'classList' classList:[active,active1,active2] // 此时这三个都会绑定上

  2. style样式的绑定 js <div :style="{color: styleColor, fontSize: styleSize}">文本不重要, 重要的是样式</div> <div :style="{color: styleColor, 'font-size': styleSize}">文本不重要, 重要的是样式</div> styleColor: 'red', styleSize: '50px', <div :style="styleObj">文本不重要, 重要的是样式</div> // 这时两个属性都能绑定上 styleObj: { color: 'pink', fontSize: '100px' },

  3. template的作用 * template 是一个空标签, 哪怕渲染成功也只会有它内部的标签, 它本身不会渲染出来 js <template v-if="count"> <h1>标题</h1> <h3>内容</h3> <footer>底部分类</footer> </template>

3. v-model中key的关键点

  1. 这个写法有问题是数据跟标签并没有绑定到一起,我们在处理时将标签添加到原本的标签之前,但是虚拟dom在处理时会将标签实际向后添加,所以会导致标签跟数据位置有问题

  2. 想要解决上述问题就应该将数据跟标签绑定到一起,做法就是在使用v-for的时候同时给当前标签绑定一个key,绑定的时候不要使用下标,一定要找一个当前数据唯一值不会重复的值,一般是当前数据的id

  3. 在使用v-for时要用key给该数据绑定一个唯一值

  4. 绑定key之后还可以帮助vue的DIFF算法更好的找到两个虚拟新旧DOM节点

4. 双向数据绑定

  1. 数据会改变视图,视图也会改变数据

  2. v-model的实现原理:内容绑定一个变量(value),改变内容用事件函数(on),利用了双向数据绑定,就是代替v-on还有v-bind

  3. 事件绑定的修饰符 * .stop: 阻止事件传播进行 * .prevent:阻止默认事件 * .self:事件源是自身时才能触发 * .capture:将当前默认的 冒泡修改捕获的方式触发 * .once:事件只能触发一次 * .passive:修饰符一般用于触摸事件的监听器,可以用来改善移动端设备的滚屏性能。