vue2 中 watch 监听属性

文章目录

  • vue2 中 watch 监听属性
    • 1. 简介
    • 2. 基本语法
      • 1. 函数式写法
      • 2. 对象式写法
    • 3. 示例
      • 1. 基础用法
      • 2. 深度监听对象属性
      • 3. 立即执行 watcher
    • 4. 性能优化
    • 5. 实际应用场景
      • 1. 数据变化时执行异步操作
      • 2. 复杂计算和数据同步
      • 3. 监听对象或数组的变化
      • 4. 执行副作用操作
      • 5. 表单验证
      • 6. 数据缓存和更新
      • 7. 与第三方库集成
      • 8. 路由变化监听
    • 6. 总结

vue2 中 watch 监听属性

1. 简介

watch 是 Vue 2 中的一个重要选项,用于定义观察者(watcher),监视指定的数据属性的变化。当被监视的属性发生变化时,相应的处理函数会被调用,从而允许你对变化做出反应。这在需要根据数据变化执行异步操作或开销较大的计算时非常有用。

2. 基本语法

watch 的基本语法如下:
如果监听的需求比较简单,可以直接使用函数式写法:

1. 函数式写法

export default {
	data() {
		return {
			message: 'Hello, Vue!'
		}
	},
	watch: {
		// 定义一个 watcher 来监视 message 属性
		message (newValue, oldValue) {
			console.log(`message changed from ${oldVal} to ${newValue}`)
		}
	}
}

在这个例子中,每当 message 的值发生变化时,watch 选项中的处理函数就会被触发,并接收新旧两个值作为参数。这种方式写起来简便,适用于简单的监听需求

2. 对象式写法

如果监听需求比较复杂,建议使用对象式写法:、

export default {
  data() {
    return {
      dataProperty: ''
    };
  },
  watch: {
    dataProperty: {
      handler(newVal, oldVal) {
        console.log(`数据从 ${oldVal} 变更为 ${newVal}`);
      },
      deep: true,
      immediate: true
    }
  }
};

这种方式更清晰,更方便拓展和维护,适用于复杂的监听需求

3. 示例

1. 基础用法

假设我们有一个简单的输入框,希望在用户输入内容后立即更新某个状态:

<template>
  <div id="app">
    <input v-model="searchText" placeholder="Search...">
    <p>Searching for: {{ searchText }}</p>
  </div>
</template>

<script>
export default {
  data() {
    return {
      searchText: ''
    };
  },
  watch: {
    searchText(newValue) {
      console.log('Search text changed:', newValue);
      this.performSearch(newValue);
    }
  },
  methods: {
    performSearch(query) {
      // 执行搜索逻辑...
      console.log('Performing search with query:', query);
    }
  }
};
</script>

这段代码会在每次 searchText 变化时打印新的值,并调用 performSearch 方法来执行搜索操作。

2. 深度监听对象属性

如果你需要监听的对象是嵌套的,或者是一个复杂的数据结构,默认情况下 watch 只会监听顶层属性的变化。为了监听对象内部属性的变化,可以使用 deep 选项:

export default {
  data() {
    return {
      user: {
        name: 'John Doe',
        age: 30
      }
    };
  },
  watch: {
    user: {
      handler(newVal, oldVal) {
        console.log('User object changed:', newVal);
      },
      deep: true // 开启深度监听
    }
  }
};

在这个例子中,无论 user 对象中的 name 还是 age 发生变化,都会触发 watch 处理函数
注意事项: 开启深度监听后,需要写 handler()方法。如果没有设置 deep,当对象内部的属性变化时,处理函数不会被触发。

3. 立即执行 watcher

有时候你可能希望在组件初始化时就执行一次 watch 的处理函数。为此,可以设置 immediate 选项为 true

export default {
  data() {
    return {
      message: 'Initial message'
    };
  },
  watch: {
    message: {
      handler(newVal) {
        console.log('Message changed:', newVal);
      },
      immediate: true // 初始化时立即执行一次
    }
  }
};

这段代码会在组件实例创建之初就打印出 message 的初始值

4. 性能优化

  • 避免过度使用深度监听: 深度监听可能会导致性能下降,尤其是当监听的对象非常大或嵌套层次很深时。
  • 减少不必要的 watch 调用: 只在必要时使用 watch,并尽量避免在监听器中执行复杂的逻辑。

5. 实际应用场景

1. 数据变化时执行异步操作

当某个数据发生变化时,可能需要执行一些异步操作,比如发送网络请求。

<template>
  <div>
    <input v-model="keyword" placeholder="请输入关键词">
    <ul>
      <li v-for="item in searchResults" :key="item.id">{{ item.name }}</li>
    </ul>
  </div>
</template>

<script>
export default {
  data() {
    return {
      keyword: '',
      searchResults: []
    };
  },
  watch: {
    keyword(newVal) {
      // 模拟异步搜索请求
      this.fetchSearchResults(newVal);
    }
  },
  methods: {
    async fetchSearchResults(keyword) {
      try {
      // 这里的请求地址只是示例,无法使用
        const response = await fetch(`https://api.example.com/search?keyword=${keyword}`);
        const data = await response.json();
        this.searchResults = data;
      } catch (error) {
        console.error('搜索出错:', error);
      }
    }
  }
};
</script>

在上述代码中,watch 监听 keyword 的变化,当 keyword 改变时,会调用 fetchSearchResults 方法发送异步请求并更新搜索结果。
注意事项: 如果进行网络请求,建议进行防抖操作,避免过度多次请求给服务器造成更大的压力。

2. 复杂计算和数据同步

当一个数据的变化依赖于另一个数据,并且需要进行复杂计算时,可以使用 watch 来实现数据同步。

<template>
  <div>
    <input v-model="price" type="number" placeholder="请输入价格">
    <input v-model="quantity" type="number" placeholder="请输入数量">
    <p>总价: {{ totalPrice }}</p>
  </div>
</template>

<script>
export default {
  data() {
    return {
      price: 0,
      quantity: 0,
      totalPrice: 0
    };
  },
  watch: {
    price(newPrice) {
      this.totalPrice = newPrice * this.quantity;
    },
    quantity(newQuantity) {
      this.totalPrice = this.price * newQuantity;
    }
  }
};
</script>

这里 watch 监听 price 和 quantity 的变化,当它们其中一个发生变化时,会重新计算 totalPrice。

3. 监听对象或数组的变化

当需要监听对象或数组的变化时,可以使用 watch 的深度监听功能。

<template>
  <div>
    <button @click="addItem">添加商品</button>
    <ul>
      <li v-for="item in shoppingCart" :key="item.id">{{ item.name }}</li>
    </ul>
  </div>
</template>

<script>
export default {
  data() {
    return {
      shoppingCart: []
    };
  },
  watch: {
    shoppingCart: {
      handler(newCart) {
        console.log('购物车发生变化:', newCart);
      },
      deep: true
    }
  },
  methods: {
    addItem() {
      this.shoppingCart.push({ id: Date.now(), name: '商品' + Date.now() });
    }
  }
};
</script>

在这个例子中,使用 deep: true 开启深度监听,当 shoppingCart 数组的内容发生变化时,会触发 handler 函数。

4. 执行副作用操作

除了更新数据,watch 还可以用于执行一些副作用操作,比如修改 DOM 元素的样式。

<template>
  <div>
    <input v-model="isActive" type="checkbox">
    <div :class="{ active: isActive }">这是一个可激活的区域</div>
  </div>
</template>

<script>
export default {
  data() {
    return {
      isActive: false
    };
  },
  watch: {
    isActive(newVal) {
      if (newVal) {
        // 执行一些额外的副作用操作
        console.log('激活状态已开启');
      } else {
        console.log('激活状态已关闭');
      }
    }
  }
};
</script>

当 isActive 的值发生变化时,会在控制台输出相应的信息,同时修改 DOM 元素的样式。

5. 表单验证

在表单输入过程中,当用户输入内容发生变化时,可能需要实时进行表单验证。使用 watch 可以方便地监听表单字段的变化并执行相应的验证逻辑。

<template>
  <div>
    <input v-model="email" placeholder="请输入邮箱">
    <p v-if="emailError">{{ emailError }}</p>
  </div>
</template>

<script>
export default {
  data() {
    return {
      email: '',
      emailError: ''
    };
  },
  watch: {
    email(newEmail) {
      const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
      if (!emailRegex.test(newEmail)) {
        this.emailError = '请输入有效的邮箱地址';
      } else {
        this.emailError = '';
      }
    }
  }
};
</script>

在上述代码中,watch 监听 email 的变化,每当用户输入新内容时,会使用正则表达式验证邮箱格式是否正确,并显示相应的错误信息。

6. 数据缓存和更新

当应用中有缓存数据,并且某个相关的数据发生变化时,需要更新缓存数据。这时可以使用 watch 来监听关键数据的变化,从而触发缓存更新操作。

<template>
  <div>
    <button @click="updateData">更新数据</button>
    <p>当前数据: {{ mainData }}</p>
  </div>
</template>

<script>
export default {
  data() {
    return {
      mainData: '初始数据',
      cachedData: '初始缓存数据'
    };
  },
  watch: {
    mainData(newData) {
      // 更新缓存数据
      this.cachedData = `缓存的 ${newData}`;
      console.log('缓存数据已更新:', this.cachedData);
    }
  },
  methods: {
    updateData() {
      this.mainData = `新数据 ${Date.now()}`;
    }
  }
};
</script>

这里 watch 监听 mainData 的变化,当 mainData 更新时,会相应地更新 cachedData 并在控制台输出更新信息。

7. 与第三方库集成

当使用第三方库,且某个数据的变化需要同步到第三方库时,watch 可以发挥作用。例如,在使用地图库时,监听地图的中心点或缩放级别变化,更新地图显示。

<template>
  <div id="map"></div>
  <input v-model="zoomLevel" type="number" placeholder="请输入缩放级别">
</template>

<script>
import Map from 'some-map-library';

export default {
  data() {
    return {
      zoomLevel: 10,
      map: null
    };
  },
  mounted() {
    // 初始化地图
    this.map = new Map('map', { zoom: this.zoomLevel });
  },
  watch: {
    zoomLevel(newZoom) {
      // 更新地图缩放级别
      this.map.setZoom(newZoom);
    }
  }
};
</script>

在这个例子中,watch 监听 zoomLevel 的变化,当用户修改缩放级别输入框的值时,会调用地图库的 setZoom 方法更新地图的缩放级别。

8. 路由变化监听

在单页面应用(SPA)中,当路由发生变化时,可能需要执行一些特定的操作,比如滚动到页面顶部、重置页面状态等。可以使用 watch 监听路由的变化。

<template>
	<div>
	<!-- 这里是页面内容 -->
	</div>
</template>

<script>
export default {
  watch: {
 	// 当路由变化时,滚动到页面顶部
 	`$store` () {
 	  window.scrollTo(0, 0)
 	}	
  }
}
</script>

在 Vue.js 中,$route 是一个响应式对象,使用 watch 监听它的变化,当路由切换时,会将页面滚动到顶部。

6. 总结

watch 是 Vue 2 中一个非常强大的工具,适用于需要根据数据变化执行异步操作或开销较大的计算场景。通过合理使用 watch,可以实现高效的数据响应和复杂的业务逻辑。

你可能感兴趣的:(Vue2,vue.js,javascript,前端,vue2,前端框架)