綁定事件v-on和按鍵修飾符
-
v-on:click 表示在button元素上監聽click事件 簡寫:@click
-
enter space tab 按鍵修飾符
-
keyup是用戶松開按鍵才觸發
-
keydown是在用戶按下按鍵時立即觸發
代碼展示:
<!DOCTYPE html><html lang="en" xmlns:v-on="http://www.w3.org/1999/xhtml"><head><meta charset="UTF-8"><title>Title</title></head><body><div id="app">{{msg}}<h2>{{web.title}}</h2><h2>{{web.age}}</h2><a :href="web.url">{{web.url}}</a><!-- v-on:click 表示在button元素上監聽click事件--><button v-on:click="edit">修改url</button><!-- 簡寫:@click--><button @click="edit">修改url-簡寫模式</button>?<hr><!-- 當用戶按下回車鍵并松開的時候觸發-->回車<input type="text" @keyup.enter="add(1,2)"><br>空格<input type="text" @keyup.space="add(1,2)"><br><!-- 不能使用keyup,當按下tab鍵時,光標會移到下一個文本框,失去焦點,所以要使用keydown-->Tab<input type="text" @keydown.tab="add(1,2)"><br>W <input type="text" @keyup.w="add(1,2)"><br><!-- 組合快捷鍵-->CTRL+shift+enter <input type="text" @keyup.ctrl.shift.enter="add(1,2)"></div><script type="module">import {createApp,reactive} from "./vue.esm-browser.js";createApp({setup(){const web=reactive({title:'vue3',author:'vue',year:'2023',age:18,url:'https://www.baidu.com'})const edit= ()=>{web.url='https://www.meituan.com'}const add =(a,b)=>{return web.age += a+b}return{msg:'hello world',//普通變量web,//響應式數據edit,add}}}).mount('#app')</script></body></html>
顯示和隱藏 v-show
v-show:通過設置布爾值確定是否顯示
原理:通過添加移除插件中style的display:none來實現顯示與隱藏
代碼展示:
?<!DOCTYPE html><html lang="en"><head><meta charset="UTF-8"><title>Title</title></head><body><div id="app"><h2>{{web.show}}</h2><p v-show="web.show"> 你好,Vue</p><button @click="toggle">切換</button></div><script type="module">import {createApp,reactive} from './vue.esm-browser.js'createApp({setup(){const web=reactive({show:true})const toggle=()=>{web.show=!web.show}return{web,toggle//方法}}}).mount('#app')</script></body></html>
條件渲染v-if(判斷)
-
v-if 用于對元素進行條件渲染,當條件為true時,渲染該元素,當為false時,則不渲染
-
v-if 適用于較少改變的場景,因為頻繁從DOM中添加與刪除元素,會導致性能下降
-
v-else-if v-else
-
v-show 通過添加移除插件中style的display:none來實現顯示與隱藏
-
v-show 適用于頻繁切換元素的顯示狀態,因為只改變display屬性,不需要重新渲染整個組件
?
<!DOCTYPE html><html lang="en"><head><meta charset="UTF-8"><title>Title</title></head><body><div id="app"><h2>{{web.show}}</h2><p v-show="web.show"> 你好,Vue</p><p v-if="web.show">你好,if</p><button @click="toggle">切換</button><p v-if="web.user < 1000">新網站</p><p v-else-if="web.user >= 1000 && web.user < 10000">老網站</p><p v-else>老老網站</p></div><script type="module">import {createApp,reactive} from './vue.esm-browser.js'createApp({setup(){const web=reactive({show:true,user:11100})const toggle=()=>{web.show=!web.show}return{web,toggle//方法}}}).mount('#app')</script></body></html>
Vue:雙向數據綁定 v-model
什么是雙向數據綁定
Vue. js 是一個MVVM 框架,即數據雙向綁定,即當數據發生變化的時候,視圖也就發生變化,當視圖發生變化的時候,數據也會跟著同步變化。這也算是 Vue.js 的精髓之處了。
值得注意的是,我們所說的數據雙向綁定,一定是對于U1控件醉說的,非UI 控件不會涉及到數據雙向綁定。單向數據綁定是使用狀態管理工具的前提。如果我們使用 vuex,那么數據流也是單項的,這時就會和雙向數據綁定有沖突。
為什么要實現數據的雙向綁定
在 Vue.js 中,如果使用 vuex,實際上數據還是單向的,之所以說是數據雙向綁定,這是用的UI 控件來說,對于我們處理表單,Vue. js 的雙向數據綁定用起來就特別舒服了。即兩者并不互斥,在全局性數據流使用單項,方便跟蹤;局部性數據流使用雙向,簡單易操作。
在表單中使用雙向數據綁定
你可以用 v-model指令在表單<input>、(textarea)及<select> 元素上創建雙向數據綁定。它會根據控件類型自動選取正確的方法來更新元素。盡管有些神奇,但v-model 本質上不過是語法糖。它負責監聽用戶的輸入事件以更新數據,并對一些極端場景進行一些特殊處理。 注意:v-model 會忽略所有表單元素的value、checked、selected 特性的初始值而總是將Vue 實例的數據作為數據來源。你應該通過 JavaScript 在組件的 data 選項中聲明初始值!
代碼示例
?
<!DOCTYPE html><html lang="en"><head><meta charset="UTF-8"><title>Title</title></head><body><div id="app">輸入的文本: <input type="text" v-model="number">{{number}}文本域: <textarea name="" id="" cols="30" rows="10" v-model="obj.name"></textarea> {{obj.name}}<br>單選框: <input type="radio" v-model="obj.name" value="zhangsan">zhangsan<input type="radio" v-model="obj.name" value="lisi">lisi<p>選中了誰:{{obj.name}}</p>下拉框:<select v-model="obj.name"><option value="" disabled>===請選擇===</option><option value="zhangsan" selected>zhangsan</option><option value="lisi">lisi</option></select></div><script type="module">import {createApp,ref,reactive} from './vue.esm-browser.js'createApp({setup(){const number = ref(0)//響應式數據 ref用于存儲單個基本類型的數據,如數字,字符串等number.value = 20 // 使用ref創建的響應式對象,可以直接修改其value值const obj = reactive({//響應式數據 reactive用于存儲對象,數組等復雜數據類型name:'zhangsan',age:18})obj.name = 'lisi'//使用reactive創建的響應式對象,可以直接通過屬性名修改其屬性值return{msg:'hello world',number,obj}}}).mount('#app')</script>?</body></html>
注意:如果v-model表達式的初始值未能匹配任何選項,<select>元素會被渲染為“未選中狀態”,推薦提供一個值為空的禁用選擇項
v-model常用修飾符
-
v-model.lazy:在失去焦點或按下回車鍵之后渲染
-
v-model.number:輸入框的值被轉換成數字類型,非數字類型不識別
-
v-model.trim:去除首尾空格
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>Title</title>
</head>
<body>
<div id="app"><h3>url:{{web.url}}</h3><h3>user:{{web.user}}</h3>實時渲染<input type="text" v-model="web.url"><br>
<!-- 輸入100人,web.user的值仍為100-->在失去焦點或按下回車鍵之后渲染<input type="text" v-model.lazy="web.url"><br>輸入框的值被轉換成數字類型<input type="text" v-model.number="web.user"><br>去除首尾空格<input type="text" v-model.trim="web.url"><br>
</div>
<script type="module">import {createApp,reactive} from './vue.esm-browser.js'createApp({setup(){const web = reactive({url:'https://www.baidu.com',user:10})return{web}}}).mount('#app')</script>
</body>
</html>
v-for(循環)
?<!DOCTYPE html><html lang="en"><head><meta charset="UTF-8"><title>Title</title></head><body><div class="app"><li v-for="(item,index) in vm.items">{{item.name}}===={{index}}</li></div><script type="module">import {createApp,reactive,ref} from "./vue.esm-browser.js";createApp({setup(){const vm = reactive({msg:"hello world",items:[{name:"xwq",age:18},{name:"xwq1",age:19},{name:"xwq2",age:20}]})const message = ref("hello world1")return{vm,message}}}).mount(".app")</script></body></html>
Attribute綁定 :v-bind:
雙大括號不能在 HTML attributes 中使用。想要響應式地綁定一個 attribute,應該使用 v-bind指令
?<b :class="{textColor:web.fontStatus}"> 你好</b>
v-bind
指令指示 Vue 將元素的 class
attribute 與組件的 選擇器
屬性保持一致。如果綁定的值是 null
或者 undefined
,那么該 attribute 將會從渲染的元素上移除。
可以直接簡寫為 v-bind: ==》:
開頭為 :
的 attribute 可能和一般的 HTML attribute 看起來不太一樣,但它的確是合法的 attribute 名稱字符,并且所有支持 Vue 的瀏覽器都能正確解析它。
<!DOCTYPE html>
<html lang="en" xmlns:v-bind="http://www.w3.org/1999/xhtml">
<head><meta charset="UTF-8"><title>Title</title>
</head>
<body>
<style>.textColor{color: red;}
</style>
<div id="app">
<!-- :value--><h3>value="xwqnoicwen"</h3><input type="text" value="xwqnoicwen"><h3>value="xwqnoicwen"</h3><input type="text" v-bind:value="web.url"><p></p><input type="text" :value="web.url">
<!--:src--><h3>src="101.png"</h3><img src="101.png" style="width: 10%" height="10%"><p></p><img :src="web.img" style="width: 10%" height="10%">
<!-- :class--><h3>class="textColor"</h3><b class="textColor"> 你好</b><p></p>
<!-- 可以通過布爾值確認是否渲染樣式--><b :class="{textColor:web.fontStatus}"> 你好</b>
</div>
<script type="module">import {createApp,reactive} from './vue.esm-browser.js'createApp({setup(){const web = reactive({url:'https://www.baidu.com',fontStatus:false,img:"101.png"})return{web}}}).mount("#app")
</script>
</body>
</html>
渲染數據 v-text和v-html
-
v-text將數據解析純文本格式 與{{}}作用相同
-
v-html將數據解析成HTML格式
?<!DOCTYPE html><html lang="en"><head><meta charset="UTF-8"><title>Title</title><script src="vue.global.js"></script></head><body><div id="app"><!-- ? 差值表達式,將vue實例中定義的數據在視圖中渲染-->{{msg}}<h2>{{web.title}}</h2><p>Using text interpolation: {{ rawHtml }}</p><p>Using v-html directive: <span v-text="rawHtml"></span></p><p>Using v-html directive: <span v-html="rawHtml"></span></p><a :href="web.url">{{web.title}}</a></div><script>//這里使用的是一種解構賦值語法,將vue對象中的createApp方法,reactive方法,mount方法等掛載到Vue上const {createApp,reactive,ref} = VuecreateApp({//設置響應數據和方法等setup(){const web=reactive({title:'vue3',author:'vue',year:'2023',url:'https://www.baidu.com'})const rawHtml = '<span style="color:red">this should be red</span>'return{msg:'hello world',web,rawHtml}}}).mount('#app')</script></body></html>
計算屬性 computed
計算屬性緩存 vs 方法
你可能注意到我們在表達式中像這樣調用一個函數也會獲得和計算屬性相同的結果:
?
<!DOCTYPE html><html lang="en"><head><meta charset="UTF-8"><title>Title</title></head><body><div id="app"><h2>{{add()}}</h2><h2>{{add()}}</h2><h2>{{sum}}</h2><h2>{{sum}}</h2>?</div><script type="module">import {createApp,reactive,computed} from './vue.esm-browser.js'createApp({setup(){const data= reactive({x:10,y:20})//方法 無緩存let add = () =>{console.log('add')//打印兩次,說明方法是沒有緩存的,return data.x+data.y}//計算屬性 有緩存 【計算屬性根據其以來的響應式數據變化而重新計算】const sum = computed(()=>{console.log('sum')//打印一次return data.x+data.y})return{add,sum}}}).mount('#app')</script></body></html>
若我們將同樣的函數定義為一個方法而不是計算屬性,兩種方式在結果上確實是完全相同的,
不同之處在于計算屬性值會基于其響應式依賴被緩存。一個計算屬性僅會在其響應式依賴更新時才重新計算。
這意味著只要 author.books
不改變,無論多少次訪問 publishedBooksMessage
都會立即返回先前的計算結果,而不用重復執行 getter 函數。
這也解釋了為什么下面的計算屬性永遠不會更新,因為 Date.now()
并不是一個響應式依賴:
js
?const now = computed(() => Date.now())
相比之下,方法調用總是會在重渲染發生時再次執行函數。沒有緩存
為什么需要緩存呢?想象一下我們有一個非常耗性能的計算屬性 list
,需要循環一個巨大的數組并做許多計算邏輯,并且可能也有其他計算屬性依賴于 list
。沒有緩存的話,我們會重復執行非常多次 list
的 getter,然而這實際上沒有必要!如果你確定不需要緩存,那么也可以使用方法調用。
手動監聽偵聽器 watch()
偵聽一個或多個響應式數據源,并在數據源變化時調用所給的回調函數。
詳細:
watch()
默認是懶偵聽的,即僅在偵聽源發生變化時才執行回調函數。
第一個參數是偵聽器的源。這個來源可以是以下幾種:
-
一個函數,返回一個值
-
一個 ref
-
一個響應式對象
-
...或是由以上類型的值組成的數組
第二個參數是在發生變化時要調用的回調函數。這個回調函數接受三個參數:新值、舊值,以及一個用于注冊副作用清理的回調函數。該回調函數會在副作用下一次重新執行前調用,可以用來清除無效的副作用,例如等待中的異步請求。
當偵聽多個來源時,回調函數接受兩個數組,分別對應來源數組中的新值和舊值。
第三個可選的參數是一個對象,支持以下這些選項:
-
immediate
:在偵聽器創建時立即觸發回調。第一次調用時舊值是undefined
。 -
deep
:如果源是對象,強制深度遍歷,以便在深層級變更時觸發回調。在 3.5+ 中,此參數還可以是指示最大遍歷深度的數字。參考深層偵聽器。 -
flush
:調整回調函數的刷新時機。參考回調的刷新時機及 watchEffect()。 -
onTrack / onTrigger
:調試偵聽器的依賴。參考調試偵聽器。 -
once
:(3.4+) 回調函數只會運行一次。偵聽器將在回調函數首次運行后自動停止。
與 watchEffect() 相比,watch()
使我們可以:
-
懶執行副作用;
-
更加明確是應該由哪個狀態觸發偵聽器重新執行;
-
可以訪問所偵聽狀態的前一個值和當前值。
?<!DOCTYPE html><html lang="en"><head><meta charset="UTF-8"><title>偵聽器</title></head><body><div id="app">愛好<select v-model="hobby"><option value="" disabled>請選擇</option><option value="1">足球</option><option value="2">籃球</option><option value="3">排球</option></select><hr>年<select v-model="date.year"><option value="" disabled>請選擇</option><option value="2020">2020</option><option value="2021">2021</option><option value="2023">2022</option></select>月<select v-model="date.month"><option value="" disabled>請選擇</option><option value="1">1</option><option value="2">2</option><option value="3">3</option></select></div><script type="module">import {createApp,ref,reactive,watch} from './vue.esm-browser.js'createApp({setup(){const hobby = ref('')//愛好const date = reactive({year:'2023',month:'1'})// 監聽hobby的變化 通過監聽的值,可以獲取到變化前后的值,這樣當你切換到某個選項時,我們可以進行對應的操作watch(hobby,(newValue,oldValue)=>{console.log("newValue\t"+newValue,"oldValue\t"+oldValue)if(newValue==='1'){alert('足球')}else if(newValue==='2'){alert('籃球')}else if(newValue==='3'){alert('排球')}})// 監聽date的變化watch(date,(newValue,oldValue)=>{/**JS中對象和數組是通過引用傳遞的,而不是通過值傳遞的* 當修改對象或數組的時候,實際上修改的是對象或數組的引用,而不是創建一個新的對象或數組* 所以,當監聽到date的變化時,newValue和oldValue都是同一個對象,* 所以,如果修改了對象或數組的值,那么打印的結果是修改后的值*/console.log("newValue\t",newValue,"oldValue",oldValue)if(newValue.year==='2020'&&newValue.month==='1'){alert('2020年1月')}else if(newValue.year==='2021'&&newValue.month==='2'){alert('2021年2月')}else if(newValue.year==='2023'&&newValue.month==='3'){alert('2023年3月')}})//監聽date.year的變化watch(()=>date.year,(newValue,oldValue)=>{console.log("newValue\t",newValue,"oldValue\t",oldValue)if(newValue==='2020'){alert('2020年')}else if(newValue==='2021'){alert('2021年')}else if(newValue==='2023'){alert('2023年')}})return{hobby,date}}}).mount('#app')</script></body></html>
自動偵聽器 watchEffect()
立即運行一個函數,同時響應式地追蹤其依賴,并在依賴更改時重新執行。
第一個參數就是要運行的副作用函數。這個副作用函數的參數也是一個函數,用來注冊清理回調。清理回調會在該副作用下一次執行前被調用,可以用來清理無效的副作用,例如等待中的異步請求 (參見下面的示例)。
第二個參數是一個可選的選項,可以用來調整副作用的刷新時機或調試副作用的依賴。
默認情況下,偵聽器將在組件渲染之前執行。設置 flush: 'post'
將會使偵聽器延遲到組件渲染之后再執行。詳見回調的觸發時機。在某些特殊情況下 (例如要使緩存失效),可能有必要在響應式依賴發生改變時立即觸發偵聽器。這可以通過設置 flush: 'sync'
來實現。然而,該設置應謹慎使用,因為如果有多個屬性同時更新,這將導致一些性能和數據一致性的問題。
簡單代碼展示:
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>偵聽器</title>
</head>
<body>
<div id="app">愛好<select v-model="hobby"><option value="" disabled>請選擇</option><option value="1">足球</option><option value="2">籃球</option><option value="3">排球</option></select><hr>年<select v-model="date.year"><option value="" disabled>請選擇</option><option value="2020">2020</option><option value="2021">2021</option><option value="2022">2022</option></select>月<select v-model="date.month"><option value="" disabled>請選擇</option><option value="1">1</option><option value="2">2</option><option value="3">3</option></select>
</div>
<script type="module">import {createApp,ref,reactive,watchEffect} from './vue.esm-browser.js'createApp({setup(){const hobby = ref('')//愛好const date = reactive({year:'2023',month:'1'})//自動監聽watchEffect(()=> {console.log("監聽開始")if (hobby.value === '1') {alert('足球')}if (date.year === '2022') {alert('2022')}if (date.month === '3') {alert('3')}})return{hobby,date}}}).mount('#app')
</script>
</body>
</html>
返回值是一個用來停止該副作用的函數。
?const count = ref(0)?watchEffect(() => console.log(count.value))// -> 輸出 0?count.value++// -> 輸出 1
停止偵聽器:
js
?const stop = watchEffect(() => {})?// 當不再需要此偵聽器時:stop()
暫停/恢復偵聽器:
js
?const { stop, pause, resume } = watchEffect(() => {})?// 暫停偵聽器pause()?// 稍后恢復resume()?// 停止stop()
副作用清理:
js
?watchEffect(async (onCleanup) => {const { response, cancel } = doAsyncWork(newId)// 如果 `id` 變化,則調用 `cancel`,// 如果之前的請求未完成,則取消該請求onCleanup(cancel)data.value = await response})
3.5+ 中的副作用清理:
js
?import { onWatcherCleanup } from 'vue'?watchEffect(async () => {const { response, cancel } = doAsyncWork(newId)// 如果 `id` 變化,則調用 `cancel`,// 如果之前的請求未完成,則取消該請求onWatcherCleanup(cancel)data.value = await response})
選項:
js
?watchEffect(() => {}, {flush: 'post',onTrack(e) {debugger},onTrigger(e) {debugger}})
以上就是Vue.js常用的指令,希望對大家有所幫助