vue.js快速上手開發知識梳理(基礎篇)

前言

文章涉及的內容可能不全面,但量不少,須要慢慢看。我花了很長的時間整理,用心分享心得,但願對你們有所幫助。可是不免會有打字的錯誤或理解的錯誤點,但願發現的能夠郵箱告訴我1163675970@qq.com,我會及時的進行修改,只但願對你有所幫助,謝謝。javascript

類庫 vs 插件 vs 組件 vs 框架

再此以前先掃盲一下 區分框架和類庫等css

  1. 類庫

jQuery、Zepto、underscore... 類庫提供的是真實項目中經常使用到的方法,它是一個工具包,基於這個工具包能夠快速開發任何的項目html

  1. 插件

TAB選項卡插件、BANNER輪播圖插件、DIALOG模態框插件、DRAG拖拽插件... iscroll局部滾動插件、jquery中有不少的插件 插件是把項目中某一個具體的功能進行封裝vue

  1. UI組件

bootstrap、swiper、mui、妹子UI... UI組件庫通常是多個插件的集合體,不只提供了JS對應的功能,並且把結構、樣式等也都實現了,咱們只須要作一名CV工程師就能夠快速構建一個產品java

  1. 框架

vue、react、uni-app、react native、flutter、angular(ng)、backbone... 通常來講,框架是類庫和組件的綜合體,裏面提供了大量供咱們操做的方法,也有配套的UI組件庫供咱們快速開發;框架是具有獨立編程思想的,例如:vue是MVVM思想,讓咱們告別傳統的DOM操做,按照視圖和數據的相互渲染來完成項目開發,可是無論怎麼變,都必定會比咱們以前基於原生操做更簡單,性能更好...node

市面上經常使用的框架:vue(MVVM) / react(MVC)react

APP框架:uni-app / react native / flutterjquery


初識VUE

Vue.js(讀音 /vjuː/, 相似於 view) 是一套構建用戶界面的漸進式框架。ios

Vue 只關注視圖層, 採用自底向上增量開發的設計。ajax

Vue 的目標是經過儘量簡單的 API 實現響應的數據綁定和組合的視圖組件。

vue 咱們如今學習和使用的是第二代版本

參考資料:

官方文檔:vuejs.org/v2/guide/sy…

中文文檔: cn.vuejs.org/v2/guide/sy… ---> 強烈推薦

基於 $npm i vue 安裝

漸進式框架

漸進式:類庫或者框架都是重量級的,裏面包含不少方法,可是實際項目開發中,咱們用不到這麼多東西,因此在開啊他們的時候,會把功能按照模塊進行單獨開發,使用者可根據自身狀況選擇一個模塊一個模塊的導入使用

  • vue:基礎模塊(基礎語法、核心實現、組件開發、相關指令等都在這裏)

  • vue-router:構建SPA單頁面應用的路由

  • vuex:公共狀態管理

  • vue-cli:vue腳手架

  • components:vue element、iview、vux...

  • ... 這些東西就是VUE全家桶

聲明式和命令式

  • 命令式編程:命令「機器」如何去作事情(how),這樣無論你想要的是什麼(what),它都會按照你的命令實現,例如for循環
  • 聲明式編程:告訴「機器」你想要的是什麼(what),讓機器想出如何去作(how),例如數組內置方法forEach等

MVC & MVVM

  • 傳統操做DOM模式
  • MVC:model view controller
  • MVVM:model view viewModel

VUE 是 MVVM框架

MVVM是雙向數據綁定的:VUE自己實現了數據和視圖的相互監聽影響

MVC是單向數據綁定,數據更改能夠渲染視圖,可是視圖更改沒有更改數據,須要咱們本身在控制層基於change事件實現數據的更改(REACT)

  • m:mode數據層
  • v:view視圖層
  • vm:viewModel 數據和視圖的監聽層(當數據或者視圖發生改變,VM層會監聽到,同時把對應的另一層特跟着改變或者從新渲染)
    • 數據層改變:vm會幫咱們從新渲染視圖
    • 視圖層改變:vm也會幫咱們把數據從新更改

VUE的雙向數據綁定的原理

當初始化Vue的實例時,會遍歷data中的全部的屬性,給每個屬性新增get和set方法,

當獲取這個屬性對應的屬性值,會默認執行get方法,設置屬性的屬性值時,會執行set方法;

vue的指令編譯器,對v的指令進行解析,並初始化視圖,並訂閱觀察者來更新視圖;

並將watcher添加到Dep訂閱器中,當數據發生改變,observer的set方法會被調用,

會遍歷Dep訂閱器中全部的訂閱者,而後再更新視圖;

vue的使用

<!-- IMPORT JS -->
	<!--<script src="./node_modules/vue/dist/vue.min.js"></script>--> <!-- 開發的時候儘量引用未壓縮版本,這樣有錯誤會拋出異常 --> <script src="./node_modules/vue/dist/vue.js"></script> <script> //=>每當建立一個實例,就至關於建立一個viewModel監聽器:能夠監聽對應視圖和對應數據的相互改變 let vm1 = new Vue({ //=>el:element 當前監聽器監聽的視圖(基於querySelector獲取) el: '#app', //=>data: 當前監聽器監聽的數據(這些監聽的數據會掛載到vm1實例上,也就是vm1.msg=xxx來操做了) data: { msg: 'hello world~~' } }); }); </script> 複製代碼

vue 基礎

mustache([ˈmʌstæʃ]) {{xxx}} 小鬍子語法

<!-- IMPORT CSS -->
<body> <div id='app'> {{msg}} //=> 數據綁定最多見的形式就是使用 {{...}}(雙大括號 小鬍子語法)的文本插值 </div> <div id="box"> <span>{{n}}</span> <br> //=> 事件監聽可使用 v-on 指令: //=>v-on 能夠接收一個定義的方法來調用 <button v-on:click="handle">點我啊~~</button> </div> <!-- IMPORT JS --> <script src="./node_modules/vue/dist/vue.js"></script> <script> let vm1 = new Vue({ el: '#app', data: { msg: 'hello world~~' } }); //需求:把MSG數據綁定在頁面#APP中,一秒後,讓數據更改,同時指望視圖也跟着更改 setTimeout(() => { vm1.msg = '你好世界~~'; }, 1000); </script> <script> let vm2 = new Vue({ el: '#box', data: { n: 0 }, //=>放視圖中須要使用的方法  methods: { handle() { //this:vm2 this.n++; } } }); </script> </body> 複製代碼
<body>
	<div id="app"> 人民幣:¥ <input type="text" v-model="priceRMB"> <br> 美圓:$ <span>{{priceRMB/7.1477}}</span> </div> <!-- IMPORT JS --> <script src="./node_modules/vue/dist/vue.js"></script> <script> //=>v-model 實現雙向數據綁定: //=>v-model先實現把數據綁定到視圖層(給INPUT設置VALUE值),而後監聽文本框內容的改變,一旦改變,會把數據也跟着改變;數據一變,視圖會從新的渲染; let vm = new Vue({ el: '#app', data: { priceRMB: 0 } }); </script> </body> 複製代碼

VUE基礎語法

<body>
	<div id="app"> {{obj}} <br> {{arr}} <br> {{'name' in obj?'OK':'no'}} </div> <!-- IMPORT JS --> <script src="./node_modules/vue/dist/vue.js"></script> <script> let obj = { // name: '' }; let arr = [10]; let vm = new Vue({ //=>基於querySelector獲取視圖容器:指定的容器不能是HTML和BODY el: '#app', data: { /* * 在鬍子語法中綁定的數據值是對象類型,會基於JSON.stringify把其編譯爲字符串再呈現出來(而不是直接toString處理的) * * 並非全部的數據更改最後都會通知視圖從新渲染 * 1.初始數據是一個對象,對象中沒有xxx鍵值對,後期新增的鍵值對是不會讓視圖從新渲染的,解決辦法: * + 最好在初始化數據的時候,就把視圖須要的數據提早聲明好(能夠是空值,可是要有這個屬性) =>原理:只有DATA中初始化過的屬性纔有GET/SET * + 不要修改某個屬性名,而是把對象的值總體替換(指向新的堆內存) * + 能夠基於vm.$set內置方法修改數據:vm.$set(obj,key,value) * * 2.若是數據是一個數組,咱們修改數據基於ARR[N]=xxx或者ARR.length--等操做方式,是沒法讓視圖從新渲染的;須要基於: * + push/pop等內置的方法 * + 從新把ARR的值重寫(指向新的堆內存) * + vm.$set */ obj, arr } }); setTimeout(() => { // vm.arr[1] = 20; // vm.arr.length--; // vm.arr.push(20); vm.$set(vm.arr, 1, 20); // vm.obj.name = "珠峯培訓"; // vm.obj = { // ...obj, // name: '珠峯培訓' // }; // vm.$set(vm.obj, 'name', '珠峯培訓'); }, 1000); </script> </body> 複製代碼

VUE 指令

<body>
	<!-- 
		VUE指令:directive
			1.都是按照v-xxx處理的,它是vue中規定給元素設置的自定義屬性
			2.當vue加載成功並進行處理的時候,會按照相關的規則解析和宣傳視圖,遇到對應的指令實現對應的功能
		v-model通常給表單元素設置的,實現表單元素和數據之間的相互綁定
			1)先把數據綁定給表單元素 ,通常把數據賦值給表單元素的value、
			2)監聽表單元素的內容改變
			3)內容改變後,會把對應的數據也改變
			4)對應的數據改變,視圖中全部用到數據的地方都會從新渲染
			視圖 <=> 數據
			在vue框架中給表單元素設置value等屬性是沒有意義的

		v-html/v-text:給非表單元素設置內容,v-html支持對於標籤的自動識別,v-text會把全部內容分都當作文本
			傳統的鬍子語法,在vue沒有加載完成以前,會把{{xxx}}展現在頁面中,當vue加載完纔會出現真正的內容,這樣體驗很差

		v-bind:給元素的內置屬性動態綁定數據,例如:給img綁定動態的圖片路徑地址
			能夠簡寫成爲 :,也就是 v-bind:src 等價於 :src
		
		v-once:綁定的數據是一次性的,後面不論數據怎麼改變,視圖也都不會從新渲染

		v-if:若是對應的值是TRUE,當前元素會在結構中顯示,若是是FALSE,當前元素會在結構中移除(它控制的是組件的加載和卸載的操做 =>DOM的增長和刪除);還有對應的 v-else-if / v-else 等指令;
		v-show:和v-if相似,只不過它是控制元素樣式的顯示隱藏(display的操做)
			1)v-if是控制組件存不存在,對於結果是FALSE,不存在的組件來講,視圖渲染的時候無需渲染這部份內容;而v-show則不行,由於不論是顯示仍是隱藏,結構都在,因此視圖渲染的時候這部分也要渲染;
			2)在過於頻繁的切換操做中,v-if明顯要比v-show要低一些
	 -->
	<div id="app">
		<button v-html='msg' @click='handle'></button>
		<br>
		<img :src="pic" alt="" v-if='show'>
		<!-- <span v-html='msg'></span>
		<span v-once v-html='msg'></span> -->
		<!-- <input type="text" v-model="msg">
		<span v-html='msg'></span>
		<img :src="pic" alt="">
		<img v-bind:src="pic" alt="">
		<span>{{msg}}</span> -->
	</div>
	<!-- IMPORT JS -->
	<script src="./node_modules/vue/dist/vue.js"></script>
	<script>
		let vm = new Vue({
			el: '#app',
			data: {
				//=>這裏的數據最後都會做爲實例的屬性掛載到實例上vm.show...
				msg: '隱藏圖片',
				show: true,
				pic: '1.png'
			},
			methods: {
				//=>這裏的方法最後也會掛載到實例的私有屬性上
				handle() {
					//=>this:vm
					this.show = !this.show;
					this.msg = this.show ? '隱藏圖片' : '顯示圖片';
				}
			}
		});
		/* setTimeout(() => {
			vm.msg = '哈哈哈哈';
		}, 1000); */
	</script>
</body>
複製代碼

v-for:循環動態綁定數據

<body>
	<!-- v-for:循環動態綁定數據 想循環誰就給誰設置v-for 循環相似for/for in的語法:v-for='(item,index) in arr' --> <div id="app"> <table> <thead> <tr> <th>編號</th> <th>姓名</th> <th>年齡</th> </tr> </thead> <tbody> <tr v-for='(item,index) in arr'> <td v-html='item.id'></td> <td v-html='item.name'></td> <td v-html='item.age'></td> </tr> </tbody> </table> </div> <!-- IMPORT JS --> <script src="./node_modules/vue/dist/vue.js"></script> <script> let vm = new Vue({ el: '#app', data: { arr: [{ id: 1, name: '張三', age: 25 }, { id: 2, name: '李四', age: 24 }, { id: 3, name: '王五', age: 26 }] } }); </script> <script> //JS中循環的幾種方式:for循環、while循環、do while循環 | for in循環 | for of循環 let arr = [10, 20, 30, 40], obj = { name: '珠峯培訓', year: 10, 1: 100 }; Object.prototype.AA = 12; //=>ES6新增for of循環 //1.獲取的不是屬性名是屬性值 //2.不會遍歷原型上公有的屬性方法(哪怕是自定義的) //3.只能遍歷可被迭代的數據類型值(Symbol.iteratoer):Array、String、Arguments、NodeList、Set、Map等,可是普通對象是不可被迭代的數據,因此不能用for of循環 /* for (let item of obj) { console.log(item); } */ /* for (let key in arr) { if (!arr.hasOwnProperty(key)) break; console.log(key, arr[key]); } */ /* for (let key in obj) { //=>KEY遍歷的屬性名 //=>OBJ[KEY]屬性值 //=>優先遍歷屬性名爲數字的 //=>會把所屬類原型上自定義的屬性方法也遍歷到 if (!obj.hasOwnProperty(key)) break; console.log(key); } */ </script> </body>

複製代碼

v-on : 用來實現事件綁定的指令 及 事件修飾符

<body>
	<!-- v-on(簡寫 @):用來實現事件綁定的指令 v-on:click='xxx' @click='xxx' 1.事件觸發的時候,須要傳遞參數信息,把方法加小括號,$event是事件對象 v-on:click='sum($event,10,20)' 2.事件修飾符 常規修飾符:@click.prevent/stop = 'xxx' 按鍵修飾符:@keydown.enter/space/delete/up/right/down/left...='xxx' 鍵盤碼:@keydown.13 = 'xxx' 組合按鍵:@keydown.alt.67 = 'xxx' //=>ALT+C --> <div id="app"> <!-- <a href="http://www.zhufengpeixun.cn/" @click.prevent.stop='func'> 珠峯培訓 </a> --> <!-- <button v-on:click='func'></button> --> <!-- <button v-on:click='sum($event,10,20)'></button> --> <input type="text" placeholder="請輸入搜索內容" v-model='text' @keydown.alt.67='func'> </div> <!-- IMPORT JS --> <script src="./node_modules/vue/dist/vue.js"></script> <script> let vm = new Vue({ el: '#app', data: { text: '' }, methods: { func(ev) { alert('珠峯培訓'); /* if (ev.keyCode === 13) { alert('珠峯培訓'); } */ }, sum(ev, n, m) { console.log(arguments); } } }); </script> </body> 複製代碼

VUE 表單元素的處理 -- 單選或者複選按鈕

<body>
	<!-- 
		單選或者複選按鈕
			1.按照 v-model 進行分組,單選框裝備的數據是一個值,複選框準備的數據是一個數組
			2.每個框都有本身的value,誰被選中,數據值就是被選中元素的value值;相反,值是多少,對應value的元素也會被默認選中;
	 -->
	<div id="app">
		<!-- 性別:<br>
		<input type="radio" value='0' v-model.number='sex'>男
		<input type="radio" value='1' v-model.number='sex'>女
		<br>
		<button @click='submit'>提交</button> -->

		<!-- <input type="checkbox" value="OK" v-model='all' @click='handle'>全選/全不選
		<br>
		<div @change='delegate'>
			<input type="checkbox" value="song" v-model='hobby'>唱歌
			<input type="checkbox" value="dance" v-model='hobby'>跳舞
			<input type="checkbox" value="read" v-model='hobby'>讀書
			<input type="checkbox" value="javascript" v-model='hobby'>編程
		</div>
		<br>
		<button @click='submit'>提交</button> -->
	</div>
	<!-- IMPORT JS -->
	<script src="./node_modules/vue/dist/vue.js"></script>
	<script>
		let vm = new Vue({
			el: '#app',
			data: {
				sex: 0,
				hobby: ['javascript'],
				all: []
			},
			methods: {
				submit() {
					console.log(this.sex);
				},
				handle() {
					//=>CLICK事件處理比視圖更新後數據的更改要先去作
					if (!this.all.includes('OK')) {
						this.hobby = ['song', 'dance', 'read', 'javascript'];
					} else {
						this.hobby = [];
					}
				},
				delegate() {
					//=>CHANGE事件處理,要晚於數據更新
					this.all = this.hobby.length >= 4 ? ['OK'] : [];
				}
			}
		});
	</script>
</body>
複製代碼

VUE - filters-過濾器

過濾器的語法:

按照豎線分隔,把豎線左側的值傳遞給右側的過濾器方法,通過方法的處理,把處理後的結果展現在視圖中

過濾器方法只能在鬍子語法{{}}和v-bind中使用(過濾器中的方法沒有掛載到實例上)

<body>
	<div id="app">
		<input type="text" v-model='text'>
		<br>
		<!-- <span v-text='text.replace(/\b[a-zA-Z]+\b/g,item=>{
			return item.charAt(0).toUpperCase()+item.substring(1);
		})'></span> -->
		<!-- <span v-text='toUP(text)'></span> -->
		<!-- 
			過濾器的語法:按照豎線分隔,把豎線左側的值傳遞給右側的過濾器方法,通過方法的處理,把處理後的結果展現在視圖中
			過濾器方法只能在鬍子語法{{}}和v-bind中使用(過濾器中的方法沒有掛載到實例上)
		 -->
		<!-- <span>{{text|toUP|filterB}}</span> -->
		<!-- <img :src="pic|picHandle" alt=""> -->
	</div>
	<!-- IMPORT JS -->
	<script src="./node_modules/vue/dist/vue.js"></script>
	<script>
		let vm = new Vue({
			el: '#app',
			data: {
				//=>響應式數據:DATA中準備的要在視圖中渲染的數據(MODEL)
				text: ''
			},
			methods: {
				//=>都會掛載到實例上(不能和DATA中的屬性名衝突):這裏的制定的方法是普通方法,能夠在視圖中調取使用,也能夠在其它方法中調取使用
				toUP(value) {
					return value.replace(/\b[a-zA-Z]+\b/g, item => {
						return item.charAt(0).toUpperCase() + item.substring(1);
					});
				}
			},
			filters: {
				//=>設置過濾器:把須要在視圖中渲染的數據進行二次或者屢次的處理
				toUP(value) {
					//=>value:須要過濾的數據 return返回的是過濾後的結果
					return value.replace(/\b[a-zA-Z]+\b/g, item => {
						return item.charAt(0).toUpperCase() + item.substring(1);
					});
				},
				filterB(value) {
					return value.split('').reverse().join('');
				},
				picHandle(value){
					return value.length===0?'http://www.zhufengpeixun.cn/static/1.png':value;
				}
			}
		});
	</script>
</body>
複製代碼

VUE-computed-計算屬性

計算屬性:

它不是方法是一個屬性,因此在視圖中調取的時候不能加括號執行,toUP和DATA中的TEXT同樣,

都會掛載到實例上,它存儲的值是對應方法返回的結果(getter函數處理的結果)

計算屬性有本身的緩存處理:

第一次獲取toUP屬性值,會關聯某個響應式數據(text),當第一次結果獲取後,會把這個結果緩存下來;

後期視圖從新渲染,首先看text值是否發生更改,若是發生更改,會從新計算toUP屬性值,若是沒有更改,則還會拿上次緩存的結果進行渲染;

<body>
	<div id="app"> <input type="text" v-model='text'> <br> <span v-text='toUP'></span> </div> <!-- IMPORT JS --> <script src="./node_modules/vue/dist/vue.js"></script> <script> let vm = new Vue({ el: '#app', data: { text: '' }, computed: { //=>計算屬性:它不是方法是一個屬性,因此在視圖中調取的時候不能加括號執行,toUP和DATA中的TEXT同樣,都會掛載到實例上,它存儲的值是對應方法返回的結果(getter函數處理的結果) //=>計算屬性有本身的緩存處理:第一次獲取toUP屬性值,會關聯某個響應式數據(text),當第一次結果獲取後,會把這個結果緩存下來;後期視圖從新渲染,首先看text值是否發生更改,若是發生更改,會從新計算toUP屬性值,若是沒有更改,則還會拿上次緩存的結果進行渲染; toUP() { return this.text.replace(/\b[a-zA-Z]+\b/g, item => { return item.charAt(0).toUpperCase() + item.substring(1); }); } }, methods: { /* toUP(value) { return value.replace(/\b[a-zA-Z]+\b/g, item => { return item.charAt(0).toUpperCase() + item.substring(1); }); } */ } }); </script> </body> 複製代碼

真實項目中:

咱們通常用一個計算屬性和某些響應式數據進行關聯,響應式數據發生改變,計算屬性的GETTER函數會從新執行,不然使用的是上一次計算出來的緩存結果

計算屬性中必需要關聯一個響應式數據,不然GETTER函數只執行一次

<body>
	<div id="app">
		<p>正常結果:{{text}}</p>
		<p>反轉結果:{{reverseMethod()}}</p>
		<p>反轉結果:{{reverseComputed}}</p>
		<p>{{now2()}}</p>
	</div>
	<!-- IMPORT JS -->
	<script src="./node_modules/vue/dist/vue.js"></script>
	<script>
		//=>真實項目中:咱們通常用一個計算屬性和某些響應式數據進行關聯,響應式數據發生改變,計算屬性的GETTER函數會從新執行,不然使用的是上一次計算出來的緩存結果
		let vm = new Vue({
			el: '#app',
			data: {
				text: 'MY NAME IS ZHUFENG PEIXUN'
			},
			computed: {
				//=>GETTER函數
				reverseComputed() {
					// console.log('computed');
					return this.text.split('').reverse().join('');
				},
				now1() {
					//=>計算屬性中必需要關聯一個響應式數據,不然GETTER函數只執行一次
					return new Date();
				}
			},
			methods: {
				reverseMethod() {
					// console.log('methods');
					return this.text.split('').reverse().join('');
				},
				now2() {
					return new Date();
				}
			}
		});

		let n = 0;
		let timer = setInterval(() => {
			n++;
			if (n > 5) {
				clearInterval(timer);
				return;
			}
			if (n === 3) {
				vm.text = 'WELCOME TO ZHUFENG';
				return;
			}
			//=>強制更新視圖的從新渲染
			vm.$forceUpdate();
		}, 1000);
	</script>
</body>
複製代碼

GETTER:只要獲取這個屬性值就會觸發GET函數執行

SETTER:給屬性設置值的時候會觸發SET函數,VALUE是給這個屬性設置的值

<body>
	<div id="app"> <p>正常結果:{{text}}</p> <p>反轉結果:{{reverseComputed}}</p> <input type="text" v-model='reverseComputed'> </div> <!-- IMPORT JS --> <script src="./node_modules/vue/dist/vue.js"></script> <script> let vm = new Vue({ el: '#app', data: { text: 'MY NAME IS ZHUFENG PEIXUN' }, computed: { //=>GETTER函數 /* reverseComputed() { return this.text.split('').reverse().join(''); } */ reverseComputed: { get() { //=>GETTER:只要獲取這個屬性值就會觸發GET函數執行 return this.text.split('').reverse().join(''); }, set(value) { //=>SETTER:給屬性設置值的時候會觸發SET函數,VALUE是給這個屬性設置的值 console.log('OK', value); } } } }); let n = 0; let timer = setInterval(() => { n++; if (n > 5) { clearInterval(timer); return; } if (n === 3) { vm.text = 'WELCOME TO ZHUFENG'; return; } //=>強制更新視圖的從新渲染 vm.$forceUpdate(); }, 1000); </script> </body>

複製代碼

基於計算屬性監聽 全選/非全選

<body>
	<div id="app">
		<input type="checkbox" v-model='slected'>全選/非全選
		<br>
		<span v-for='item in hobbyList'>
			<input type="checkbox" :id="item.id|handleID" :value="item.value" v-model='checkList'>
			<label :for="item.id|handleID" v-text='item.name'></label>
		</span>
	</div>
	<!-- IMPORT JS -->
	<script src="./node_modules/vue/dist/vue.js"></script>
	<script>
		let vm = new Vue({
			el: '#app',
			data: {
				hobbyList: [{
					id: 1,
					name: '唱歌',
					value: 'song'
				}, {
					id: 2,
					name: '跳舞',
					value: 'dance'
				}, {
					id: 3,
					name: '閱讀',
					value: 'read'
				}, {
					id: 4,
					name: '睡覺',
					value: 'sleep'
				}],
				//存儲選中的興趣愛好
				checkList: [],
			},
			computed: {
				//存儲全選按鈕的選中狀態
				slected: {
					get() {
						return this.checkList.length === this.hobbyList.length;
					},
					set(value) {
						//=>點擊全選框會修改slected的值
						//=>VALUE存儲的是選中的狀態
						if (value) {
							this.hobbyList.forEach(item => {
								this.checkList.push(item.value);
							});
							return;
						}
						this.checkList = [];
					}
				}
			},
			filters: {
				handleID(value) {
					return 'hobby' + value;
				}
			}
		});
	</script>
</body>
複製代碼

VUE -WACTH

watch監聽響應式數據的改變

(watch中監聽的響應式數據必須在data中初始化) 和 computed中的setter相似,

只不過computed是本身單獨設置的計算屬性(不能和DATA中的衝突),

而watch只能監聽DATA中有的屬性

監聽器支持異步操做 computed的getter不支持異步獲取數據

<body>
	<div id="app">
		<input type="checkbox" v-model='slected' @change='handle'>全選/非全選
		<br>
		<span v-for='item in hobbyList'>
			<input type="checkbox" :id="item.id|handleID" :value="item.value" v-model='checkList'>
			<label :for="item.id|handleID" v-text='item.name'></label>
		</span>
	</div>
	<!-- IMPORT JS -->
	<script src="./node_modules/vue/dist/vue.js"></script>
	<script>
		let vm = new Vue({
			el: '#app',
			data: {
				hobbyList: [{
					id: 1,
					name: '唱歌',
					value: 'song'
				}, {
					id: 2,
					name: '跳舞',
					value: 'dance'
				}, {
					id: 3,
					name: '閱讀',
					value: 'read'
				}, {
					id: 4,
					name: '睡覺',
					value: 'sleep'
				}],
				//存儲選中的興趣愛好
				checkList: [],
				//存儲全選狀態
				slected: false
			},
			//=>watch監聽響應式數據的改變(watch中監聽的響應式數據必須在data中初始化) 和 computed中的setter相似,只不過computed是本身單獨設置的計算屬性(不能和DATA中的衝突),而watch只能監聽DATA中有的屬性
			//=>監聽器支持異步操做  computed的getter不支持異步獲取數據
			watch: {
				checkList() {
					this.slected = this.checkList.length === this.hobbyList.length ? true : false;
				}
			},
			methods: {
				handle() {
					if (this.slected) {
						this.hobbyList.forEach(item => {
							this.checkList.push(item.value);
						});
						return;
					}
					this.checkList = [];
				}
			},
			filters: {
				handleID(value) {
					return 'hobby' + value;
				}
			}
		});
	</script>
</body>
複製代碼

VUE-CLASS

<body>
	<div id="app">
		<!-- 
			對象方式處理動態的樣式
				:class="{樣式類名:響應式數據,...}"
				響應式數據爲TRUE則有這個樣式類,反之則沒有
		 -->
		<!-- <p :class="{active:a,big:true}">歡迎來到珠峯培訓,我是大家的老師~~</p>
		<button @click='handle'>切換樣式</button> -->
		<!-- <button @click='a=!a'>切換樣式</button> -->

		<!-- 
			數組控制樣式類
				:class="[響應式數據1,....]"
				控制響應式數據的值是對應的樣式類或者沒有值,來控制是否有這個樣式
		 -->
		<p :class="[active,big]">歡迎來到珠峯培訓,我是大家的老師~~</p>
		<button @click='handle'>切換樣式</button>
	</div>
	<!-- IMPORT JS -->
	<script src="./node_modules/vue/dist/vue.js"></script>
	<script>
		let vm = new Vue({
			el: '#app',
			data: {
				// a: false
				active: '',
				big: 'big'
			},
			methods: {
				handle() {
					this.active = this.active === '' ? 'active' : '';
					// this.a = !this.a;
				}
			}
		});
	</script>
</body>
複製代碼

VUE - 生命週期函數

  • beforeCreate 在實例初始化以後,數據觀測 (data observer) 和 watch 配置以前被調用。
  • created 在實例建立完成後被當即調用。在這一步,實例已完成數據觀測、屬性和方法的運算、watch/event 事件回調;可是在現階段尚未開始掛載,即還沒掛載到根 DOM 元素上,因此 this.$el 屬性不可見
  • beforeMount 在掛載開始以前被調用,建立虛擬 DOM(Virtual-DOM);虛擬 DOM 不是真實的 DOM 元素,而是 js 對象,其中包含了渲染成 DOM 元素信息;
  • mounted 把 Vue 的虛擬 DOM 掛載到真實的 DOM 上;若是要在 Vue 中獲取 DOM 元素對象,通常在這個鉤子中獲取;項目中的 ajax 請求通常會在這裏或者 created 裏發送;
  • beforeUpdate 只有當數據發生變化時,纔會觸發這個函數;
  • updated 因爲數據更改致使的虛擬 DOM 從新渲染和打補丁,在這以後會調用 updated。
  • beforeDestroy 在 Vue 的實例被銷燬以前調用,若是頁面中有定時器,咱們會在這個鉤子中清除定時器;
  • destroyed Vue 實例銷燬後調用,實例中的屬性也再也不是響應式的,watch 被移除
<!DOCTYPE html>
<html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <div id="app"> <div @click="fn">{{msg}}</div> </div> <script src="vue.js"></script> <script> // 生命週期: // Vue 的實例具備生命週期,Vue 的實例在生成的時候,會經歷一系列的初始化的過程;數據的監聽,編譯模板,實例掛載DOM元素,或者數據更新致使 DOM 更新,在執行的過程當中,會運行一些叫作生命週期的鉤子函數,在 Vue 實例生命週期中特定的時間點執行的函數稱爲生命週期的鉤子函數; // 若是咱們須要在某個生命週期處理一些事情,咱們能夠把這些事情寫在鉤子函數中;等到 Vue 的實例生命週期到這個階段就會執行這個鉤子,而咱們要作的事情也就得以處理了 // 生命週期的鉤子函數不能人爲的控制其執行的順序; let vm = new Vue({ data: { msg: 'hello' }, methods: { fn() {console.log(11111)} }, beforeCreate() { // 在實例初始化以後,數據觀測 (data observer) 和 watch 配置以前被調用。 console.log(1); console.log(this.msg); console.log(this.$el); // this.$el 是根 DOM 元素 }, created() { // 在實例建立完成後被當即調用。在這一步,實例已完成數據觀測、屬性和方法的運算、watch/event 事件回調 // 可是在現階段尚未開始掛載,即還沒掛載到根 DOM 元素上,因此 this.$el 屬性不可見 console.log(2); console.log(this.msg); console.log(this.$el); }, beforeMount() { // 在掛載開始以前被調用,建立虛擬DOM(Virtual-DOM);虛擬 DOM 不是真實的 DOM 元素,而是 js 對象,其中包含了渲染成 DOM 元素信息; console.log(3); console.log(this.msg); console.log(this.$el); }, mounted() { // 把 Vue 的虛擬DOM掛載到真實的 DOM 上; // 若是要在 Vue 中獲取 DOM 元素對象,通常在這個鉤子中獲取 // 項目中的 ajax 請求通常會在這裏或者 created 裏發送; console.log(4); console.log(this.msg); console.log(this.$el); }, // 只有當數據發生變化時,纔會觸發這個函數; beforeUpdate() { console.log(5) }, updated() { // 因爲數據更改致使的虛擬 DOM 從新渲染和打補丁,在這以後會調用該鉤子。 console.log(6); }, beforeDestroy() { // 在 Vue 的實例被銷燬以前調用,若是頁面中有定時器,咱們會在這個鉤子中清除定時器; console.log(7); }, destroyed() { // Vue 實例銷燬後調用,實例中的屬性也再也不是響應式的,watch 被移除 console.log(8); } }); vm.$set(vm, 'msg', 'hello world'); // 由於 Vue 的數據都是響應式的,只有修改數據纔會觸發 beforeUpdate 和 updated 鉤子 vm.$mount('#app'); // 當建立實例時不傳遞 el 屬性,能夠手動掛載到 DOM 節點; vm.$destroy(); // 手動銷燬實例; </script> </body> </html> 複製代碼
<body>
	<div id="app">
		<span v-html='msg' class="AAA" @click='msg=10'></span>
	</div>
	<!-- IMPORT JS -->
	<script src="./node_modules/vue/dist/vue.js"></script>
	<script>
		/*
		 * 生命週期函數(鉤子函數)
		 * 	 beforeCreate  建立vue實例以前
		 *   created 建立實例成功(通常在這裏實現數據的異步請求)
		 *   beforeMount 渲染DOM以前(加載組件第一次渲染)
		 *   mounted 渲染DOM完成(加載組件第一次渲染)
		 *   beforeUpdate 從新渲染以前(數據更新等操做控制DOM從新渲染)
		 *   updated 重現渲染完成
		 *   beforeDestroy 銷燬以前
		 *   destroyed 銷燬完成
		 */
		let vm = new Vue({
			el: '#app',
			/* beforeMount() {
				console.log(document.getElementById('app'));
			},
			mounted() {
				console.log(document.getElementById('app'));
			}, */
			data: {
				msg: '你好世界'
			}
		});
		// vm.$mount('#app');  //=>el:'#app' 
		//=>指定當前vm所關聯的視圖

		// vm.$destroy();
		//=>銷燬以後,再去修改響應式數據值,視圖也不會在從新的渲染了

		console.dir(vm);
	</script>
</body>
複製代碼

VUE-REFS

VUE框架開發的時候,咱們應該儘量減小直接去操做DOM

咱們基於REF能夠把當前元素放置到 this.$refs對象中,從而實現對DOM的直接操做

(只有在mounted 渲染DOM完成 及以後才能夠獲取到)

<body>
	<div id="app">
		<h3 v-html='msg' ref='titleBox'></h3>
		<p ref='pBox'></p>
	</div>
	<!-- IMPORT JS -->
	<script src="./node_modules/vue/dist/vue.js"></script>
	<script>
		//=>VUE框架開發的時候,咱們應該儘量減小直接去操做DOM
		//=>咱們基於REF能夠把當前元素放置到this.$refs對象中,從而實現對DOM的直接操做(只有在mounted及以後才能夠獲取到)
		let vm = new Vue({
			el: '#app',
			data: {
				msg: '你好世界'
			},
			mounted() {
				console.log(this.$refs); //=>{titleBox:H3,pBox:P}
			}
		});
	</script>
</body>

複製代碼

VUE-TAB

li和div對應切換

<!-- IMPORT CSS -->
	<link rel="stylesheet" href="css/reset.min.css">
	<style>
		.tabBox {
			box-sizing: border-box;
			margin: 20px auto;
			width: 600px;
		}

		.tabBox .tab {
			display: flex;
			position: relative;
			top: 1px;
		}

		.tabBox .tab li {
			margin-right: 10px;
			padding: 0 20px;
			line-height: 35px;
			border: 1px solid #AAA;
			background: #EEE;
			cursor: pointer;
		}

		.tabBox .tab li.active {
			background: #FFF;
			border-bottom-color: #FFF;
		}

		.tabBox .content {
			box-sizing: border-box;
			padding: 10px;
			height: 300px;
			border: 1px solid #AAA;
		}
	</style>
</head>

<body>
	<div id="app">
		<div class="tabBox">
			<ul class="tab">
				<li v-for='(item,index) in TAB_DATA' v-html='item.name' :class="{active:index===curIndex}"
					@click='handle($event,index,item.id)'>
				</li>
			</ul>
			<div class="content" v-html='content'></div>
		</div>
	</div>
	<!-- IMPORT JS -->
	<script src="./node_modules/vue/dist/vue.js"></script>
	<script src="./node_modules/axios/dist/axios.min.js"></script>
	<script>
		let TAB_DATA = [{
			id: 1,
			name: '音樂'
		}, {
			id: 2,
			name: '影視'
		}, {
			id: 3,
			name: '動漫'
		}, {
			id: 4,
			name: '紀錄片'
		}];

		let vm = new Vue({
			el: '#app',
			data: {
				//選項卡數據
				TAB_DATA,
				//展現選項卡的索引
				curIndex: 0,
				//內容區域的數據
				content: ''
			},
			created() {
				//=>生命週期函數(VUE實例建立成功)
				this.queryDATA(TAB_DATA[this.curIndex]['id']);
			},
			methods: {
				queryDATA(curID) {
					axios.get('./data.json').then(response => {
						return response.data;
					}).then(result => {
						let itemDATA = result.find(item => parseInt(item.id) === parseInt(curID));
						if (itemDATA) {
							this.content = itemDATA.content;
							return;
						}
						return Promise.reject();
					}).catch(reason => {
						this.content = '查無此信息';
					});
				},
				handle(ev, index, id) {
					if (this.curIndex === index) return;
					this.curIndex = index;
					this.queryDATA(id);
				}
			}
		});
	</script>
</body>
複製代碼

多個li 一個div

<!-- IMPORT CSS -->
	<link rel="stylesheet" href="css/reset.min.css">
	<style>
		.tabBox {
			box-sizing: border-box;
			margin: 20px auto;
			width: 600px;
		}

		.tabBox .tab {
			display: flex;
			position: relative;
			top: 1px;
		}

		.tabBox .tab li {
			margin-right: 10px;
			padding: 0 20px;
			line-height: 35px;
			border: 1px solid #AAA;
			background: #EEE;
			cursor: pointer;
		}

		.tabBox .tab li.active {
			background: #FFF;
			border-bottom-color: #FFF;
		}

		.tabBox .content {
			box-sizing: border-box;
			padding: 10px;
			height: 300px;
			border: 1px solid #AAA;
		}
	</style>
</head>

<body>
	<div id="app">
		<div class="tabBox">
			<ul class="tab">
				<li v-for='(item,index) in TAB_DATA' v-html='item.name' :class="{active:index===curIndex}"
					@click='handle($event,index,item.id)'>
				</li>
			</ul>
			<div class="content" v-html='content'></div>
		</div>
	</div>
	<!-- IMPORT JS -->
	<script src="./node_modules/vue/dist/vue.js"></script>
	<script src="./node_modules/axios/dist/axios.min.js"></script>
	<script>
		let TAB_DATA = [{
			id: 1,
			name: '音樂'
		}, {
			id: 2,
			name: '影視'
		}, {
			id: 3,
			name: '動漫'
		}, {
			id: 4,
			name: '紀錄片'
		}];

		let vm = new Vue({
			el: '#app',
			data: {
				//選項卡數據
				TAB_DATA,
				//展現選項卡的索引
				curIndex: 0,
				//內容區域的數據
				content: ''
			},
			created() {
				//=>生命週期函數(VUE實例建立成功)
				this.queryDATA(TAB_DATA[this.curIndex]['id']);
			},
			methods: {
				queryDATA(curID) {
					axios.get('./data.json').then(response => {
						return response.data;
					}).then(result => {
						let itemDATA = result.find(item => parseInt(item.id) === parseInt(curID));
						if (itemDATA) {
							this.content = itemDATA.content;
							return;
						}
						return Promise.reject();
					}).catch(reason => {
						this.content = '查無此信息';
					});
				},
				handle(ev, index, id) {
					if (this.curIndex === index) return;
					this.curIndex = index;
					this.queryDATA(id);
				}
			}
		});
	</script>
</body>
複製代碼
相關文章
相關標籤/搜索