vue基礎語法
一. 計算屬性
1.1. 計算屬性的本質
fullname: {set(), get()}
每個計算屬性都包含一個getter和一個setter
在上面的例子中,我們只是使用getter來讀取,
在某些情況下,你也可以提供一個setter方法(不常用),
在需要寫setter的時候,代碼如下:

1.2. 計算屬性和methods對比
計算屬性在多次使用時, 只會呼叫一次.
它是由快取的
我們可能會考慮這樣的一個問題:
methods和computed看起來都可以實作我們的功能,
那么為什么還要多一個計算屬性這個東西呢?
原因:計算屬性會進行快取,如果多次使用時,計算屬性只會呼叫一次,
我們來看下面的代碼:

1.3. ES6 語法
let/var (定義變數)

塊級作用域
變數作用域 :
ES5中的var是沒有作用域的
ES中的let是有作用域的(if / for)
變數在什么范圍內是可用的
var沒有作用域限制(會引起一些問題 )
沒有塊級作用域所引起的問題
沒有塊級作用域 資料得不到保證,在哪都能修改
const (定義長量)

物件字面量增強寫法

二. 事件監聽
2.1. 事件監聽基本使用
在前端開發中,我們需要經常和用于互動,
這個時候,我們就必須監聽用戶發生的時間,比如點擊、拖拽、鍵盤事件等等
在Vue中如何監聽事件呢?使用v-on指令
v-on介紹
作用:系結事件監聽器
縮寫:@
預期:Function | Inline Statement | Object
引數:event
這里,我們用一個監聽按鈕的點擊事件,來簡單看看v-on的使用
下面的代碼中,我們使用了v-on:click="counter++”
另外,我們可以將事件指向一個在methods中定義的函式

2.2. 引數問題
btnClick
btnClick(event) :!--2.在事件定義時, 寫方法時省略了小括號, 但是方法本身是需要一個引數的, 這個時候, Vue會默認將瀏覽器生產的event事件物件作為引數傳入到方法-->
btnClick(abc, event) -> $event : !--3.方法定義時, 我們需要event物件, 同時又需要其他引數-->
!-- 在呼叫方式, 如何手動的獲取到瀏覽器引數的event物件: $event-->
當通過methods中定義方法,以供@click呼叫時,需要注意引數問題:
情況一:如果該方法不需要額外引數,那么方法后的()可以不添加,
但是注意:如果方法本身中有一個引數,那么會默認將原生事件event引數傳遞進去
情況二:如果需要同時傳入某個引數,同時需要event時,可以通過$event傳入事件

Event 本身包含適用于所有事件的屬性和方法,
構造器:可以使用event()創建一個event物件
Event 物件代表事件的狀態,比如事件在其中發生的元素、鍵盤按鍵的狀態、滑鼠的位置、滑鼠按鈕的狀態,事件通常與函式結合使用,函式不會在事件發生前被執行!
2.3. 修飾符
stop
prevent
.enter
.once
.native
在某些情況下,我們拿到event的目的可能是進行一些事件處理,
Vue提供了修飾符來幫助我們方便的處理一些事件:
.stop - 呼叫 event.stopPropagation(),
.prevent - 呼叫 event.preventDefault(),
.{keyCode | keyAlias} - 只當事件是從特定鍵觸發時才觸發回呼,
.native - 監聽組件根元素的原生事件,
.once - 只觸發一次回呼,

三. 條件判斷
3.1. v-if/v-else-if/v-else
v-if、v-else-if、v-else
這三個指令與JavaScript的條件陳述句if、else、else if類似,
Vue的條件指令可以根據運算式的值在DOM中渲染或銷毀元素或組件
簡單的案例演示:

v-if的原理:
v-if后面的條件為false時,對應的元素以及其子元素不會渲染,
也就是根本沒有不會有對應的標簽出現在DOM中,
3.2. 登錄小案例
用戶再登錄時,可以切換使用用戶賬號登錄還是郵箱地址登錄,
類似如下情景:

小問題:
如果我們在有輸入內容的情況下,切換了型別,我們會發現文字依然顯示之前的輸入的內容,
但是按道理講,我們應該切換到另外一個input元素中了,
在另一個input元素中,我們并沒有輸入內容,
為什么會出現這個問題呢?
問題解答:
這是因為Vue在進行DOM渲染時,出于性能考慮,會盡可能的復用已經存在的元素,而不是重新創建新的元素,
在上面的案例中,Vue內部會發現原來的input元素不再使用,直接作為else中的input來使用了,
解決方案:
如果我們不希望Vue出現類似重復利用的問題,可以給對應的input添加key
并且我們需要保證key的不同

3.3. v-show
v-show和v-if區別
v-show的用法和v-if非常相似,也用于決定一個元素是否渲染:
v-if和v-show對比
v-if和v-show都可以決定一個元素是否渲染,那么開發中我們如何選擇呢?
v-if當條件為false時,壓根不會有對應的元素在DOM中,
v-show當條件為false時,僅僅是將元素的display屬性設定為none而已,
開發中如何選擇呢?
當需要在顯示與隱藏之間切片很頻繁時,使用v-show
當只有一次切換時,通過使用v-if

四. 回圈遍歷
4.1. 遍歷陣列
當我們有一組資料需要進行渲染時,我們就可以使用v-for來完成,
v-for的語法類似于JavaScript中的for回圈,
格式如下:item in items的形式,
我們來看一個簡單的案例:
如果在遍歷的程序中不需要使用索引值
v-for="movie in movies"
依次從movies中取出movie,并且在元素的內容中,我們可以使用Mustache語法,來使用movie
如果在遍歷的程序中,我們需要拿到元素在陣列中的索引值呢?
語法格式:v-for=(item, index) in items
其中的index就代表了取出的item在原陣列的索引值,

totalPrice() {
// 1.普通的for回圈
// let totalPrice = 0
// for (let i = 0; i < this.books.length; i++) {
// totalPrice += this.books[i].price * this.books[i].count
// }
// return totalPrice
// 2.for (let i in this.books)
// let totalPrice = 0
// for (let i in this.books) {
// const book = this.books[i]
// totalPrice += book.price * book.count
// }
//
// return totalPrice
// 3.for (let i of this.books)
// let totalPrice = 0
// for (let item of this.books) {
// totalPrice += item.price * item.count
// }
// return totalPrice
return this.books.reduce(function (preValue, book) {
return preValue + book.price * book.count
}, 0)
}
4.2. 遍歷物件
value
value, key
value, key, index
v-for可以用戶遍歷物件:
比如某個物件中存盤著你的個人資訊,我們希望以串列的形式顯示出來,

4.3. 陣列哪些方法是回應式的
官方推薦我們在使用v-for時,給對應的元素或組件添加上一個:key屬性,
為什么需要這個key屬性呢(了解)?
這個其實和Vue的虛擬DOM的Diff演算法有關系,
這里我們借用React’s diff algorithm中的一張圖來簡單說明一下:
當某一層有很多相同的節點時,也就是串列節點時,我們希望插入一個新的節點
我們希望可以在B和C之間加一個F,Diff演算法默認執行起來是這樣的,
即把C更新成F,D更新成C,E更新成D,最后再插入E,是不是很沒有效率?
所以我們需要使用key來給每個節點做一個唯一標識
Diff演算法就可以正確的識別此節點
找到正確的位置區插入新的節點,
所以一句話,key的作用主要是為了高效的更新虛擬DOM,


因為Vue是回應式的,所以當資料發生變化時,Vue會自動檢測資料變化,視圖會發生對應的更新,
Vue中包含了一組觀察陣列編譯的方法,使用它們改變陣列也會觸發視圖的更新,
push() 往最后添加元素 (可以添加多個元素)
pop() 洗掉資料中的最后一個元素
shift() 洗掉我們陣列中的第一個元素
unshift() 在陣列最前面添加元素 (可以添加多個元素)
splice() 作用<洗掉元素 / 插入元素/ 替換元素>
洗掉元素 splice(1,2), 第二個引數傳入你要洗掉幾個元素(如果沒有傳洗掉,就洗掉后面所有的元素)
插入元素splice(1,3,'m','n','u','x') 第二個引數表示我們要替換幾個元素,后面是用于替換前面的元素
替換元素splice(1,0,'x','y','z') 第二個引數傳入0 ,并且后面跟上要插入的元素
sort() 排序
reverse() 反轉

注意: 通過索引值修改陣列中的元素(不是回應式)
// this.letters[0] = 'bbbbbb';
解決辦法this.letters.splice(0, 1, 'bbbbbb')
// set(要修改的物件, 索引值, 修改后的值)
// Vue.set(this.letters, 0, 'bbbbbb')
4.3. 陣列哪些方法是回應式的小案例 點擊 那個那個添加樣式
-
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <style> .active { color: red; } </style> </head> <body> <div id="app"> <ul> <li v-for="(item, index) in movies" : @click="liClick(index)"> {{index}}.{{item}} </li> </ul> </div> <script src="https://www.cnblogs.com/zgboy/archive/2021/01/js/vue.js"></script> <script> const app = new Vue({ el: '#app', data: { movies: ['海王', '海賊王', '加勒比海盜', '海爾兄弟'], currentIndex: 0 }, methods: { liClick(index) { this.currentIndex = index}}}) </script> </body> </html>
五. v-model的使用
默認情況下再給變數賦值都是字串型別
5.1. v-model的基本使用

5.2 表單系結v-model
v-model => v-bind:value v-on:input
表單控制元件在實際開發中是非常常見的,特別是對于用戶資訊的提交,需要大量的表單,
Vue中使用v-model指令來實作表單元素和資料的雙向系結,

案例的決議:
當我們在輸入框輸入內容時
因為input中的v-model系結了message,所以會實時將輸入的內容傳遞給message,message發生改變,
當message發生改變時,因為上面我們使用Mustache語法,將message的值插入到DOM中,所以DOM會發生回應的改變,
所以,通過v-model實作了雙向的系結,
當然,我們也可以將v-model用于textarea元素

5.3v-model原理
v-model其實是一個語法糖,它的背后本質上是包含兩個操作:
1.v-bind系結一個value屬性
2.v-on指令給當前元素系結input事件
也就是說下面的代碼:等同于下面的代碼:
<input type="text" v-model="message">
等同于
<input type="text" v-bind:value="https://www.cnblogs.com/zgboy/archive/2021/01/11/message" v-on:input="message = $event.target.value">

5.4. v-model和radio/checkbox/select
當存在多個單選框時

v-model:checkbox
單個勾選框:
v-model即為布林值,
此時input的value并不影響v-model的值
多個復選框:
當是多個復選框時,因為可以選中多個,所以對應的data中屬性是一個陣列,
當選中某一個時,就會將input的value添加到陣列中,


v-model:select
單選:只能選中一個值,
v-model系結的是一個值,
當我們選中option中的一個時,會將它對應的value賦值到mySelect中
多選:可以選中多個值,
v-model系結的是一個陣列,
當選中多個值時,就會將選中的option對應的value添加到陣列mySelects中

5.5. 修飾符
lazy:
默認情況下,v-model默認是在input事件中同步輸入框的資料的,
也就是說,一旦有資料發生改變對應的data中的資料就會自動發生改變,
lazy修飾符可以讓資料在失去焦點或者回車時才會更新:
number:
默認情況下,在輸入框中無論我們輸入的是字母還是數字,都會被當做字串型別進行處理,
但是如果我們希望處理的是數字型別,那么最好直接將內容當做數字處理,
number修飾符可以讓在輸入框中輸入的內容自動轉成數字型別:
trim:
如果輸入的內容首尾有很多空格,通常我們希望將其去除
trim修飾符可以過濾內容左右兩邊的空格

5.6值系結
初看Vue官方值系結的時候,我很疑惑:what the hell is that?
但是仔細閱讀之后,發現很簡單,就是動態的給value賦值而已:
我們前面的value中的值,可以回頭去看一下,都是在定義input的時候直接給定的,
但是真實開發中,這些input的值可能是從網路獲取或定義在data中的,
所以我們可以通過v-bind:value動態的給value系結值,
這不就是v-bind嗎?
這不就是v-bind在input中的應用嗎?搞的我看了很久,搞不清他想講什么,
這里不再給出對應的代碼,因為會用v-bind,就會值系結的應用了,
六. 組件化開發
6.1. 認識組件化
什么是組件化
人面對復雜問題的處理方式:
任何一個人處理資訊的邏輯能力都是有限的
所以,當面對一個非常復雜的問題時,我們不太可能一次性搞定一大堆的內容,
但是,我們人有一種天生的能力,就是將問題進行拆解,
如果將一個復雜的問題,拆分成很多個可以處理的小問題,再將其放在整體當中,你會發現大的問題也會迎刃而解,
組件化也是類似的思想:
如果我們將一個頁面中所有的處理邏輯全部放在一起,處理起來就會變得非常復雜,而且不利于后續的管理以及擴展,
但如果,我們講一個頁面拆分成一個個小的功能塊,每個功能塊完成屬于自己這部分獨立的功能,那么之后整個頁面的管理和維護就變得非常容易了,



Vue組件化思想
組件化是Vue.js中的重要思想
它提供了一種抽象,讓我們可以開發出一個個獨立可復用的小組件來構造我們的應用,
任何的應用都會被抽象成一顆組件樹,

組件化思想的應用:
有了組件化的思想,我們在之后的開發中就要充分的利用它,
盡可能的將頁面拆分成一個個小的、可復用的組件,
這樣讓我們的代碼更加方便組織和管理,并且擴展性也更強,
所以,組件是Vue開發中,非常重要的一個篇章,要認真學習,
6.2. 組件的基本使用
注冊組件的基本步驟
組件的使用分成三個步驟:
創建組件構造器
注冊組件
使用組件,
我們來看看通過代碼如何注冊組件
查看運行結果
和直接使用一個div看起來并沒有什么區別,
但是我們可以設想,如果很多地方都要顯示這樣的資訊,我們是不是就可以直接使用

注冊組件步驟決議
這里的步驟都代表什么含義呢?
1.Vue.extend():
呼叫Vue.extend()創建的是一個組件構造器,
通常在創建組件構造器時,傳入template代表我們自定義組件的模板,
該模板就是在使用到組件的地方,要顯示的HTML代碼,
事實上,這種寫法在Vue2.x的檔案中幾乎已經看不到了,它會直接使用下面我們會講到的語法糖,但是在很多資料還是會提到這種方式,而且這種方式是學習后面方式的基礎,
2.Vue.component():
呼叫Vue.component()是將剛才的組件構造器注冊為一個組件,并且給它起一個組件的標簽名稱,
所以需要傳遞兩個引數:1、注冊組件的標簽名 2、組件構造器
3.組件必須掛載在某個Vue實體下,否則它不會生效,(見下頁)
我們來看下面我使用了三次
而第三次其實并沒有生效:

6.3. 全域組件和區域組件
當我們通過呼叫Vue.component()注冊組件時,組件的注冊是全域的
這意味著該組件可以在任意Vue示例下使用,
如果我們注冊的組件是掛載在某個實體中, 那么就是一個區域組件

6.4. 父組件和子組件
在前面我們看到了組件樹:
組件和組件之間存在層級關系
而其中一種非常重要的關系就是父子組件的關系
我們來看通過代碼如何組成的這種層級關系:
父子組件錯誤用法:以子標簽的形式在Vue實體中使用
因為當子組件注冊到父組件的components時,Vue會編譯好父組件的模塊
該模板的內容已經決定了父組件將要渲染的HTML(相當于父組件中已經有了子組件中的內容了)
類似這種用法,

6.5. 注冊的語法糖
在上面注冊組件的方式,可能會有些繁瑣,
Vue為了簡化這個程序,提供了注冊的語法糖,
主要是省去了呼叫Vue.extend()的步驟,而是可以直接使用一個物件來代替,
語法糖注冊全域組件和區域組件:

6.6.模板的分離寫法
script
template
剛才,我們通過語法糖簡化了Vue組件的注冊程序,另外還有一個地方的寫法比較麻煩,就是template模塊寫法,
如果我們能將其中的HTML分離出來寫,然后掛載到對應的組件上,必然結構會變得非常清晰,
Vue提供了兩種方案來定義HTML模塊內容:
使用<script>標簽
使用<template>標簽

6.7. 資料的存放
組件可以訪問Vue實體資料嗎?
組件是一個單獨功能模塊的封裝:
這個模塊有屬于自己的HTML模板,也應該有屬性自己的資料data,
組件中的資料是保存在哪里呢?頂層的Vue實體中嗎?
我們先來測驗一下,組件中能不能直接訪問Vue實體中的data

組件資料的存放
組件物件也有一個data屬性(也可以有methods等屬性,下面我們有用到)
只是這個data屬性必須是一個函式
而且這個函式回傳一個物件,物件內部保存著資料

子組件不能直接訪問父組件
子組件中有自己的data, 而且必須是一個函式.
為什么必須是一個函式.
為什么data在組件中必須是一個函式呢?
首先,如果不是一個函式,Vue直接就會報錯,
其次,原因是在于Vue讓每個組件物件都回傳一個新的物件,因為如果是同一個物件的,組件在多次使用后會相互影響,

6.8. 父子組件的通信
在上一個小節中,我們提到了子組件是不能參考父組件或者Vue實體的資料的,
但是,在開發中,往往一些資料確實需要從上層傳遞到下層:
比如在一個頁面中,我們從服務器請求到了很多的資料,
其中一部分資料,并非是我們整個頁面的大組件來展示的,而是需要下面的子組件進行展示,
這個時候,并不會讓子組件再次發送一個網路請求,而是直接讓大組件(父組件)將資料傳遞給小組件(子組件),
如何進行父子組件間的通信呢?Vue官方提到
通過props向子組件傳遞資料
通過事件向父組件發送訊息

在下面的代碼中,我直接將Vue實體當做父組件,并且其中包含子組件來簡化代碼,
真實的開發中,Vue實體和子組件的通信和父組件和子組件的通信程序是一樣的,
父傳子: props
在組件中,使用選項props來宣告需要從父級接收到的資料,
props的值有兩種方式:
方式一:字串陣列,陣列中的字串就是傳遞時的名稱,
方式二:物件,物件可以設定傳遞時的型別,也可以設定默認值等,
我們先來看一個最簡單的props傳遞:

props資料驗證
在前面,我們的props選項是使用一個陣列,
我們說過,除了陣列之外,我們也可以使用物件,當需要對props進行型別等驗證時,就需要物件寫法了,
驗證都支持哪些資料型別呢?
String
Number
Boolean
Array
Object
Date
Function
Symbol

當我們有自定義建構式時,驗證也支持自定義的型別

子傳父: $emit
props用于父組件向子組件傳遞資料,還有一種比較常見的是子組件傳遞資料或事件到父組件中,
我們應該如何處理呢?這個時候,我們需要使用自定義事件來完成,
什么時候需要自定義事件呢?
當子組件需要向父組件傳遞資料時,就要用到自定義事件了,
我們之前學習的v-on不僅僅可以用于監聽DOM事件,也可以用于組件間的自定義事件,
自定義事件的流程:
在子組件中,通過$emit()來觸發事件,
在父組件中,通過v-on來監聽子組件事件,
我們來看一個簡單的例子:
我們之前做過一個兩個按鈕+1和-1,點擊后修改counter,
我們整個操作的程序還是在子組件中完成,但是之后的展示交給父組件,
這樣,我們就需要將子組件中的counter,傳給父組件的某個屬性,比如total,
自定義事件代碼

6.9. 專案
npm install 安裝依賴node
npm run serve 啟動專案
七.JavaScript 高階函式使用
編程范式: 命令式編程/宣告式編程
編程范式: 面向物件編程(第一公民:物件)/函式式編程(第一公民:函式)
filter/map/reduce
filter中的回呼函式有一個要求: 必須回傳一個boolean值
true: 當回傳true時, 函式內部會自動將這次回呼的n加入到新的陣列中
false: 當回傳false時, 函式內部會過濾掉這次的n
const nums = [10, 20, 111, 222, 444, 40, 50]
let total = nums.filter(n => n < 100).map(n => n * 2).reduce((pre, n) => pre + n);
console.log(total);
let total = nums.filter(function (n) {
return n < 100
}).map(function (n) {
return n * 2
}).reduce(function (prevValue, n) {
return prevValue + n
}, 0)
console.log(total);
1.filter函式的使用
// 10, 20, 40, 50
let newNums = nums.filter(function (n) {
return n < 100
})
console.log(newNums);
2.map函式的使用
20, 40, 80, 100
let new2Nums = newNums.map(function (n) { // 20
return n * 2
})
console.log(new2Nums);
3.reduce函式的使用
reduce作用對陣列中所有的內容進行匯總
let total = new2Nums.reduce(function (preValue, n) {
return preValue + n
}, 0)
console.log(total);
第一次: preValue 0 n 20
第二次: preValue 20 n 40
第二次: preValue 60 n 80
第二次: preValue 140 n 100
240
1.需求: 取出所有小于100的數字
let newNums = []
for (let n of nums) {
if (n < 100) {
newNums.push(n)
}
}
// 2.需求:將所有小于100的數字進行轉化: 全部*2
let new2Nums = []
for (let n of newNums) {
new2Nums.push(n * 2)
}
console.log(new2Nums);
// 3.需求:將所有new2Nums數字相加,得到最終的記過
let total = 0
for (let n of new2Nums) {
total += n
}
console.log(total);
轉載請註明出處,本文鏈接:https://www.uj5u.com/qiye/247128.html
標籤:其他
