家好,本篇文章我們繼續學習和 Vue 相關的內容,今天我們歸納總結下如何使用 watch 監聽組件中的數據變化,以及 computed 和 watch 的區別。
watch 是 Vue.js 中用于監聽數據變化的一種機制。它允許我們在數據發生變化時執行特定的操作。
在 Vue 中使用 watch 的方法如下:
1.在 Vue 組件中,定義一個 watch 對象,其中包含要監聽的數據屬性以及對應的回調函數。
watch: {
dataName: function(newValue, oldValue) {
// code
}
}
其中,dataName 是要監聽的數據名稱,newValue 是新的值,oldValue 是舊的值。
2.在 Vue 實例中,使用 $watch() 方法進行監聽
vm.$watch('someData', function(newVal, oldVal) {
// do something with newVal
});
注意:watch 回調函數會在偵聽的數據發生變化時立即執行,而 computed 屬性只有在其依賴的數據發生變化時才會計算。
watch 通常用于監聽一個數據的變化并執行復雜的業務邏輯,例如在某個數據變化后需要進行 HTTP 請求或者調用其他函數。
下面是一個簡單的 watch 的例子:
<template>
<div>
<input v-model="message" type="text" placeholder="請輸入內容">
<p>{{ message }}</p>
</div>
</template>
<script>
export default {
data() {
return {
message: '',
}
},
watch: {
message: function (newVal, oldVal) {
console.log('message changed from ' + oldVal + ' to ' + newVal)
}
},
}
</script>
在這個例子中,我們使用了 watch 來監聽 message 的變化,并在數據變化時打印出更改前后的值。
當然,watch 還可以接收一個對象,其中可以定義多個監聽器。這里有一個例子,它監聽了多個數據:
watch: {
firstName: function (newVal, oldVal) {
console.log('firstName changed from ' + oldVal + ' to ' + newVal)
},
lastName: function (newVal, oldVal) {
console.log('lastName changed from ' + oldVal + ' to ' + newVal)
}
}
1、深度觀察 (deep: true):如果你希望對對象內部屬性的變化進行監聽,可以使用 deep: true 選項。
data() {
user: {
name: 'John',
age: 25
}
},
watch: {
'user.name': function (val) {
console.log('user name changed:', val)
}
}
在這個例子中,我們監聽了 user 對象中的 name 屬性,當該屬性變化時,會執行回調函數。
2、設置初始值 (immediate: true):如果你希望 watch 在組件創建時立即執行一次,可以使用 immediate: true 選項。
data() {
count: 0
},
watch: {
count: {
handler: function (val, oldVal) {
console.log('count changed');
},
immediate: true
}
}
3、異步處理 (handler):watch 的回調函數是異步執行的,這意味著如果有多個值在短時間內發生變化,回調函數只會在這些變化結束后執行一次。
watch: {
searchText: function (val) {
this.searching=true
setTimeout(()=> {
this.searchData(val)
this.searching=false
}, 500)
}
}
在這個例子中,我們監聽了 searchText 屬性,并在數據變化后延遲 500 毫秒執行搜索操作。
4、使用 watch 觀察器實現自動保存
data() {
content: ''
},
watch: {
content: function (val) {
localStorage.setItem('content', val)
}
}
在這個例子中,我們監聽了 content 屬性,并在數據變化時自動保存到本地存儲中。
watch 監聽器還有許多其他的應用場景,例如:
1.在表單輸入時進行驗證,并顯示錯誤消息
<template>
<form>
<label>
Email:
<input v-model="email" @keyup="validateEmail"/>
</label>
<p v-if="error">{{ error }}</p>
</form>
</template>
<script>
export default {
data() {
return {
email: '',
error: ''
}
},
watch: {
email: {
immediate: true,
handler(val) {
if (!val.includes('@')) {
this.error='Invalid email address'
} else {
this.error=''
}
}
}
}
}
</script>
2.在地圖上實時顯示用戶位置
<template>
<div>
<div id="map"></div>
</div>
</template>
<script>
export default {
data() {
return {
userLocation: {
lat: 0,
lng: 0
},
map: null
}
},
mounted() {
this.map=new google.maps.Map(document.getElementById("map"), {
center: { lat: 0, lng: 0 },
zoom: 8
});
navigator.geolocation.getCurrentPosition(position=> {
this.userLocation={
lat: position.coords.latitude,
lng: position.coords.longitude
}
});
},
watch: {
userLocation: {
deep: true,
handler(val) {
this.map.setCenter(val);
new google.maps.Marker({
position: val,
map: this.map
});
}
}
}
}
</script>
在這個示例中,我們使用了 watch 來監聽 userLocation 的變化,在用戶位置發生變化時,使用 setCenter 方法將地圖中心設置為用戶當前位置,并使用 google maps API 在地圖上添加一個標記,顯示用戶當前位置。
注意:這個例子需要引入 google maps 的 js 文件。
3、監聽路由變化并執行相應操作
<template>
<!-- 省略 -->
</template>
<script>
export default {
watch: {
$route(to, from) {
// 根據路由變化執行相應操作
if (to.path==='/home') {
this.getHomeData()
} else if (to.path==='/about') {
this.getAboutData()
}
}
},
methods: {
getHomeData() {
// 獲取首頁數據
},
getAboutData() {
// 獲取關于頁數據
}
}
}
</script>
4、監聽窗口大小變化并調整布局
<template>
<!-- 省略 -->
</template>
<script>
export default {
data() {
return {
windowWidth: 0
}
},
created() {
this.windowWidth=window.innerWidth
},
watch: {
windowWidth(newWidth, oldWidth) {
// 監聽窗口大小變化并調整布局
if (newWidth < 768) {
// 小屏幕布局
} else {
// 大屏幕布局
}
}
},
mounted() {
window.addEventListener('resize', ()=> {
this.windowWidth=window.innerWidth
})
}
}
</script>
<template>
<div class="container" ref="container" @scroll="handleScroll">
<img v-for="(item, index) in images" :key="index" :src="item.src" v-show="item.isLoaded" />
</div>
</template>
<script>
export default {
data() {
return {
images: [
{ src: 'image1.jpg', isLoaded: false },
{ src: 'image2.jpg', isLoaded: false },
{ src: 'image3.jpg', isLoaded: false },
// ...
]
}
},
mounted() {
// 初始化加載第一屏圖片
this.lazyLoad();
},
methods: {
handleScroll() {
this.lazyLoad();
},
lazyLoad() {
const container=this.$refs.container;
const imageList=Array.from(container.querySelectorAll('img'));
// 遍歷圖片列表,如果圖片進入了可視區域,就加載
imageList.forEach(img=> {
if (this.isInViewport(img)) {
img.src=img.dataset.src;
img.isLoaded=true;
}
});
},
isInViewport(img) {
// 獲取圖片相對于視口的位置
const rect=img.getBoundingClientRect();
// 判斷圖片是否進入了可視區域
return rect.top < window.innerHeight && rect.bottom > 0;
}
},
watch: {
images: {
handler: function(newVal, oldVal) {
// 每當圖片加載完成時,就移除已加載圖片的 isLoaded 屬性
newVal.forEach((item, index)=> {
if (item.isLoaded) {
this.$set(this.images[index], 'isLoaded', false);
}
});
},
deep: true
}
}
}
</script>
注意:需要注意的是,在這個案例中,因為images數組中的對象被改變了,所以需要設置deep: true來監聽對象
總之,watch 是一個非常強大和靈活的功能,它可以在數據變化時執行任何操作,并且可以與 computed 計算屬性配合使用,來實現更復雜的邏輯。
watch和computed都可以監聽Vue實例中的數據變化,但是它們有著明顯的不同。
watch | computed |
用于監聽某個特定的數據變化。 | 用于計算屬性,可以計算出一個新的值。 |
每次數據變化都會觸發回調函數。 | 僅在相關依賴發生改變時才會觸發重新計算。 |
適用于異步操作或復雜邏輯。 | 適用于簡單計算。 |
不可以在HTML模板中使用 | 可以在HTML模板中使用 |
沒有返回值 | 有返回值/getter |
可以修改data中的數據 | 也可以使用setters 修改 data 中的數據 |
總之,如果你需要在數據變化時執行異步操作或復雜邏輯,使用watch是更好的選擇;如果你需要在數據變化時計算出一個新值,使用computed是更好的選擇。
watch的性能取決于你的代碼實現方式和監聽的數據量。
所以,在使用watch時,應該注意監聽的數據量,并且在watch回調函數中盡量少執行復雜的邏輯.總之,watch監聽數據更新并執行回調函數,性能會受到監聽數據量和回調函數實現方式的影響,如果有性能問題,應該優化監聽的數據量和回調函數的實現方式.
今天的文章就介紹到這里,關于 watch 的用法你學會了,希望今天的文章能幫助到你,感謝你的閱讀。如果你喜歡我的分享,別忘了點贊轉發,讓更多的人看到,最后別忘記點個關注,你的支持將是我分享最大的動力,后續我會持續輸出更多內容,敬請期待。
Vue3 學習筆記,Vue 簡介及如何引入 Vue3 框架(一)
在前端這個無奇不有的世界里,有些網站不是正常垂直滾動的,而是橫向滾動的:
那么在沒法把鼠標滾輪橫過來的前提下(蘋果除外),能否實現網頁橫向滾動呢?我們來寫代碼試試。先看一下最終效果,這里我用鼠標的滾輪垂直滾動,頁面是橫向滾動的。
要實現這個功能,只需要一點點的 JS 代碼。
編寫 HTML 結構
先看一下 HTML 結構,很簡單,就是三個模擬全屏頁面的 div,class 都是 page,然后放在一個 class 名為 container 的 div 容器中:
<main>
<div class="container">
<div class="page">Page1</div>
<div class="page">Page2</div>
<div class="page">Page3</div>
</div>
</main>
編寫 CSS 樣式
對于樣式,container 容器設置為 flex 布局,并且顯示橫向滾動條:
.container {
display: flex;
overflow-x: scroll;
}
里面每一個頁面元素的寬高都設置為占滿瀏覽器可視區域的 100%,并且在 flex 布局中,不自動收縮,再分別給他們設置不同的背景色,用于區分:
.page {
width: 100vw;
height: 100vh;
flex-shrink: 0;
}
.page:nth-child(1) {
background: hsl(140deg, 50%, 50%);
}
.page:nth-child(2) {
background: hsl(210deg, 50%, 50%);
}
.page:nth-child(3) {
background: hsl(270deg, 50%, 50%);
}
實現橫向滾動
接下來我們使用 JS 實現橫向滾動,首先獲取 container 容器:
let container=document.querySelector(".container");
給它添加一個 “wheel” 事件,這個是監聽鼠標滾輪的滾動,在滾動時,先阻止默認的滾動事件,然后讓容器水平橫向移動,這里利用到了 scrollLeft 屬性,讓容器的內容向左移動,這里只需要加上滾輪垂直滾動的距離差值就可以了,也就是 event 對象中的 deltaY 屬性:
container.addEventListener("wheel", (event)=> {
event.preventDefault();
container.scrollLeft +=event.deltaY;
});
wheel 事件的兼容性可以參考 caniuse 提供的數據:
這樣就實現橫向滾動了,重點是利用了 “wheel” 事件監聽鼠標滾輪滾動,然后獲取滾動距離差值,把它加到可以滾動的容器的 scrollLeft 屬性中,你學會了嗎?
源碼地址:https://github.com/zxuqian/html-css-examples/tree/master/38-horizontal-scrolling
原文地址:https://zxuqian.cn/docs/videos/effects/js-horizontal-scroll-effect/
021年你需要知道的HTML標簽和屬性
Web開發人員都在廣泛的使用HTML。無論你使用什么框架或者選擇哪個后端語言,框架在變,但是HTML始終如一。盡管被廣泛使用,但還是有一些標簽或者屬性是大部分開發者不熟知的。雖然現在有很多的模版引擎供我們使用,但是樂字節教育的老師和我們說還是需要盡可能的熟練掌握HTML內容,就像CSS一樣。
在我看來,最好盡可能使用HTML特性來實現我們的功能,而不是使用JavaScript實現相同的功能,盡管我承認編寫HTML可能會是重復的和無聊的。
盡管許多開發人員每天都在使用HTML,但他們并沒有嘗試改進自己的項目,也沒有真正利用HTML的一些鮮為人知的特性。
下面這5個通過HTML標簽/屬性實現的功能我覺得需要了解一下:
圖片懶加載
圖片懶加載可以幫助提升網站的性能和響應能力。圖片懶加載可以避免立即加載那些不在屏幕中立即顯示的圖片素材,當用戶滾動臨近圖片時再去開始加載。
換言之,當用戶滾動到圖片出現時再進行加載,否則不加載。這就降低了屏幕內容展示過程中的圖片素材的請求數量,提升了站點性能。
往往我們都是通過javascript來實現的,通過監聽頁面滾動事件來確定加載對應的資源。但是,在不完全考慮兼容性的場景下,我們其實可以直接通過HTML來直接實現。
注:本篇的提到的標簽和屬性的兼容性需要大家根據實際場景來選取是否使用
可以通過為圖片文件添加loading="lazy"的屬性來實現:
輸入提示
當用戶在進行輸入搜索功能時,如果能夠給出有效的提示,這會大大提升用戶體驗。輸入建議和自動完成功能現在到處可見,我們可以使用Javascript添加輸入建議,方法是在輸入框上設置事件偵聽器,然后將搜索到的關鍵詞與預定義的建議相匹配。
其實,HTML也是能夠讓我們來實現預定義輸入建議功能的,通過<datalist>標簽來實現。需要注意的是,使用時這個標簽的id屬性需要和input元素的list屬性一致。
Picture標簽
你是否遇到過在不同場景或者不同尺寸的設備上面的時候,圖片展示適配問題呢?我想大家都遇到過。
針對只有一個尺寸的圖片素材的時候,我們往往可以通過CSS的object-fit屬性來進行裁切適配。但是有些時候需要針對不同的分辨率來顯示不同尺寸的圖片的場景的時候,我們是否可以直接通過HTML來實現呢?
HTML提供了<picture>標簽,允許我們來添加多張圖片資源,并且根據不同的分辨率需求來展示不同的圖片。
我們可以定義不同區間的最小分辨率來確定圖片素材,這個標簽的使用有些類似<audio>和<video>標簽。
Base URL
當我們的頁面有大量的錨點跳轉或者靜態資源加載時,并且這些跳轉或者資源都在統一的域名的場景時,我們可以通過<base>標簽來簡化這個處理。
例如,我們有一個列表需要跳轉到微博的不同大V的主頁,我們就可以通過設置來簡化跳轉路徑
<base>標記必須具有href和target屬性。
頁面重定向(刷新)
當我們希望實現一段時間后或者是立即重定向到另一個頁面的功能時,我們可以直接通過HTML來實現。
我們經常會遇到有些站點會有這樣一個功能,“5s后頁面將跳轉”。這個交互可以嵌入到HTML中,直接通過<meta>標簽,設置http-equiv="refresh"來實現
這里content屬性指定了重定向發生的秒數。值得一提的是,盡管谷歌聲稱這種形式的重定向和其他的重定向方式一樣可用,但是使用這種類型的重定向其實并不是那么的優雅,往往會顯得很突兀。
因此,最好在某些特殊的情況下使用它,比如在長時間用戶不活動之后再重定向到目標頁面。
后記
HTML和CSS是非常強大的,哪怕我們僅僅使用這兩種技術也能創建出一些奇妙的網站。雖然它們的使用量很大很普遍,還是有很多的開發者并沒有真正的深入了解他們,還有很多的內容需要我們深入的去學習和理解,實踐,有很多的技巧等待著我們去發現。
文章轉載至樂字節
最后給大家推薦幾個b站超詳細的Java自學課:
Servlet入門教程BV1D5411373E
Vue、Vuejs教程,BV19V41177od
SpringBoot+Vue項目實戰BV1o64y117qQ
*請認真填寫需求信息,我們會在24小時內與您取得聯系。