Vue快速上門(1)-基礎知識圖文版

image.png

VUE家族系列:

  • Vue快速上門(1)-基礎知識
  • Vue快速上門(2)-模板語法
  • Vue快速上門(3)-組件與複用

01、基本概念

1.1、先了解下MVVM

VUE是基於MVVM思想實現的,❓那什麼是MVVM呢?—— MVVM,是Model-View-ViewModel的縮寫,是一種軟件架構模式。其核心思想就是分離視圖、數據、邏輯,VUE框架解決了數據Model到視圖View的雙向綁定,我們只關注業務邏輯ViewModel即可,極大的提高的編程效率。

  • M:Model,數據模型,通常來自後端服務、數據庫。
  • V:View,視圖,就是HTML頁面,Dom。
  • VM:ViewModel,視圖模型,連接模型和視圖,實現數據和視圖的相互綁定。包含了視圖狀態、行爲,如頁面展示的內容(邏輯)、頁面響應事件、數據獲取更新等,都封裝在 ViewModel 中。

image

VUE實現雙向綁定的基本原理:

🔸Dom Listeners:通過對DOM元素(表單輸入元素)的值變更監聽,同步視圖變化的數據到模型。

🔸Data Bindings:通過對模型數據攔截監聽,監測數據變化進行更新視圖。原理是基於基於ES5的特性Object.defineProperty(obj, propertyName, descriptor),通過其get、set訪問器來監聽數據變更,這也是Vue不支持IE8的原因。

image.png

🌰一個雙向綁定的簡單示例:

<div id="app">
    <h2>{{message}}--{{message}}</h2>
</div>
<form action="#">
    <input type="text" v-model="message">
</form>
<script>
    //定義一個數據ViewModel,數據實際存儲在$data中。
    let app = {
        $data: {}
    }

    //通過defineProperty的get、set攔截,檢測數據變化》更新數據
    Object.defineProperty(app, "message", {
        get() { return this.$data.message; },
        set(value) {
            this.$data.message = value;
            updateView(this);  //更新視圖
        }
    })
    //保存模板、綁定了數據的表單元素
    let template = document.querySelector("#app").innerHTML;
    let vinputs = document.querySelectorAll("input[v-model]");
    //更新視圖
    function updateView(data) {
        const html = template.replace(/{{(\w+)}}/g, (match, $1) => {
            return data[$1] || "";
        })
        document.querySelector("#app").innerHTML = html;
        //更新表單元素的數據綁定
        vinputs.forEach(el => {
            el.value = data[el.getAttribute('v-model')];
        });
    }

    //監聽輸入表單的值變更
    vinputs.forEach(el => {
        el.addEventListener("input", function (e) {
            app[e.target.getAttribute('v-model')] = e.target.value;
        });
    });

    //賦值
    app.message = "hello";
</script>

1.gif

» 基本過程如圖:

image

1.2、虛擬DOM

直接操作DOM,DOM頻繁變動會使得頁面不停的佈局、渲染,是很消耗性能的,虛擬DOM就是來解決這個問題的。虛擬DOM 就是先在內存中構建一個虛擬DOM結構(JS對象表示),批量操作完成後再一次性的更新到瀏覽器DOM樹上。VUE中的虛擬DOM操作思路也是如此,只是爲了更高效,實際要稍微複雜一點點。

  • ❶ 用JS 對象模擬 虛擬DOM樹
  • ❷ 比較DOM樹差異(修改、刪除、新增...)
  • ❸ 將差異更新到真正的DOM樹中。

1.3、VUE是什麼?

中文官網https://cn.vuejs.org | Vue3版本手冊 | Vue2版本手冊

Vue(讀音 /vjuː/,類似於 view) 是一套用於構建用戶界面的漸進式框架,同他周邊的生態共同構成了一個靈活的、漸進式的前端框架。

  • 2013年底作爲尤雨溪個人實驗項目開始開發。
  • 2014年公開發布。
  • 2016年10月發佈2.0版本。
  • 2020年發佈3.0版本。

🔸核心特性

  • 響應式數據驅動(雙向綁定),數據>視圖(數據監聽),視圖>數據(事件監聽)。
  • 組件化:組件化的應用構建。
  • 申明式渲染:採用模板語法申明式的將數據渲染到DOM。
  • 輕量級框架:只關注視圖層,是一個構建數據的視圖集合,壓縮後30+K;
  • 高效率:基於虛擬化Dom技術,DOM操作效率很高。

02、準備開始

2.1、安裝使用Vue2

  • 通過<script>標籤直接引用vue.js
<!-- 開發環境版本,包含了有幫助的命令行警告 -->
<script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script>

<!-- 生產環境版本,優化了尺寸和速度 -->
<script src="https://cdn.jsdelivr.net/npm/vue@2"></script>
  • 通過 vue-cli 腳手架搭建vue的開發框架。

2.2、命名規範

前端無非就是HTML、CSS、JS,坑爹的是他們的命名規範並不相同。前端常用的兩種命名方式:

  • 小駝峯命名(lowerCamelCase):首字母小寫,後面的單詞首字母大寫:userName
  • kebab-case命名:烤串命名法(kebab /kɪˈbɑːb/ 烤肉串),都小寫,單詞之間用短線連接:user-name
類型 命名方式 說明
HTML kebab-case 按照W3C規範,HTMl中(包括標籤名、attribute)不區分大小寫,HTML解析時都會轉換爲小寫,支持字母數字、下劃線_、短線-
自定義名稱一般都採用烤串命名,加短線主要是避免和HTML原生衝突(包括以後新的名稱)
CSS kebab-case 字母開頭,字母數字、下劃線_、短線-,一般都採用烤串命名
JavaScript lowerCamelCase 字母開頭,字母數字、下劃線_,不支持短線-(作爲對象屬性得引起來)。還有些細分:
🔸 類、構造函數採用大駝峯命名
🔸 常量採用全大寫+下劃線_

Vue中的命名就有一點特殊了(混合),默認是JavaScript的小駝峯命名,但當會用於Dom時,就要採用烤串命名了,比如:

  • 組件的id:作爲元素標籤名
  • props參數:作爲元素attribute
  • 自定義事件名:作爲元素attribute
  • 自定義指令(包括指令參數、修飾符):作爲元素attribute

📢自動轉換:參數props、組件id可以採用小駝峯命名,Vue會自動轉換。如果使用字符模板,就不歸瀏覽器管了,就沒有命名的限制問題了!

Vue中其他命名規範:

  • 組件名,大駝峯,首字母大寫。

2.3、開發插件

  • Vue Devtools:瀏覽器調試插件 ,在瀏覽器的調試面板中使用,推薦Edge瀏覽器安裝。
  • Vetur:VSCode插件,Vue開發必備⭐,核心功能:
    • ✅代碼高亮:語法、語義代碼高亮。
    • ✅代碼片段:常用代碼片段的提示輸入,以及自定義代碼片段。
    • ✅代碼檢查和格式化。
    • ✅自定義代碼模板。
  • Volar,Vue3版本的vetur

03、Vue基礎結構

3.1、創建一個Vue實例

每一個Vue組件都是通過Vue()函數創建的一個Vue實例,他就是對應頁面Dom的 ViewModel

<div id="app2">
    <h2>{{title}}</h2>
    <div>
        <span v-text="user.name"></span>---<span v-text="age"></span>
        <button v-on:click="showUpperCase">提交</button>
    </div>
</div>
<script>
    let vm = new Vue({
        el: "#app2",
        data: { user: { name: "sam", birthday: '2000-12-1'}, title: "hello world!" },
        computed: {
            age() { return (new Date().getFullYear() - new Date(this.user.birthday).getFullYear()); }
        },
        methods: {
            showUpperCase: function (e) { this.title = this.title.toUpperCase(); },
        }
    })
</script>

Vue()的構造函數參數,就是Vue的選項對象,提供了Vue實例的各項配置,常用配置:

  • el:綁定視圖Dom元素,通過app.$el訪問。
  • data:數據模型,會被Vue遞歸實現數據響應(數據監聽),通過Vue對象的get、set訪問器訪問數據,數據實際都存放在vm.$data上。這裏的數據都是響應式的,支持數據雙向綁定,數據變化會自動更新同步。
  • computed:計算屬性(支持邏輯的屬性),值是一個(getter)函數,使用同data。會基於其依賴的響應式屬性進行緩存:響應式屬性變更會觸發更新,緩存計算值,重複調用(綁定)複用結果。
  • methods:方法,實現各種業務邏輯,常用於綁定事件

3.2、Vue選項🔖

💠Vue的構造函數參數=Vue選項:

Vue選項 描述
💠選項-數據
data Vue的數據對象,會被遞歸實現propert響應,vm.$data訪問原始數據。
computed 計算屬性,值是一個(getter)函數,使用同data。會基於其依賴的響應式屬性進行緩存:響應式屬性變更會觸發更新;緩存計算值,重複調用(綁定)複用結果。
methods 方法,定義方法的地方,可以綁定事件、表達式調用、訪問。
watch 對property的監聽回調,當屬性值變更時觸發。也可通過實例方法添加vm.$watch(pName,func)
props 定義組件的參數,作爲組件特性使用:Array<string> &#124; Objectprops: ['item','title']
propsData 創建實例時傳遞 props,便於測試。{ [key: string]: any }
💠選項-Dom
el Vue的DOM根元素,值爲一個已存在Dom,(id)選擇器或元素實例。
template 字符串模板,優先於el元素內容模板,template: <h3>{{user.name}}</h3>&#96;
render 渲染函數,優先於template
renderError render的替身, render 函數錯誤時替補
💠選項-資源
directives 指令,註冊局部指令,directives: {id:{}}
filters 過濾器,filters{id:func(value,...arg)}
components 註冊局部組件,components: { 'todo-box': com_todoBox }
💠選項-組合
parent 指定父級實例
mixins 混入(複用)選項,Array<Object>mixins:[cmixin]
extends 繼承另一個組件,複用代碼。extends: CompA
provide / inject 依賴注入,父類向子類發紅包,在父級定一個provider: {key:obj},後代inject :key,獲得父類的紅包。用於一些特定對象的注入,後代需要才接收、可跨級。
💠選項-其他
inheritAttrs bool值-默認true,是否繼承組件上定義的(非Prop)特性Attribute,不會影響class、style綁定
model 修改v-model綁定的Prop和event,對於文本input默認v-model綁定的是valueinput事件。

computed計算屬性

計算屬性computed選項中,用於一些複雜邏輯數據的計算。值爲(getter)函數,使用同data作爲vm的屬性用。

主要特點:會基於其依賴的響應式屬性進行緩存:響應式屬性變更會觸發更新,緩存計算值,重複調用(綁定)複用結果。如果用方法methods,每次有任何更新都會被調用。

<div id="app4">
    <p>age:{{age}},{{age}},{{getAge()}},{{getAge()}}</p>
</div>
<script>
    let app4 = new Vue({
        el: "#app4",
        data: { user: { name: "sam", birthday: "2000-1-1" } },
        computed: {
            age() {   //多次調用緩存屬性值
                console.log("computed.age"); //computed.age
                return new Date().getFullYear() - new Date(this.user.birthday).getFullYear();
            }
        },
        methods: {
            getAge() {  //多次調用會重複執行
                console.log("methods.getAge"); //methods.getAge methods.getAge
                return new Date().getFullYear() - new Date(this.user.birthday).getFullYear();
            }
        }
    })
</script>

計算屬性默認是沒有setter的,不過也可以實現setter。

computed: {
  age: {
    get: function () { },
    set: function (value) { },
  }
},

watch監聽器

針對data中的響應式屬性的值變更監聽,也可以監聽計算屬性,存放在watch選項裏,用於實現值變更的一些自定義業務邏輯。不需要返回值,支持異步處理,computed計算屬性是必須要返回值的,異步就沒有意義了。

基礎語法屬性名: function (newValue, oldValue),更多參考 vm.$watch API

watch: {
    question: function (newValue) {
        //當用戶問題變更時觸發
        this.answer = "正在思考...";
        // ajax請求搜索答案,這裏應該用防抖函數處理一下,避免頻繁無意義的調用。
        fetchJsonp("https://www.baidu.com/s?wd=" + newValue)
            .then(res => res.text())
            .then(text => { console.log(text); this.answer = text; }); //跨域請求失敗
    },
    //或者對象的形式
    question:{deep:true,handler(newValue,oldValue){}}
}
  • 屬性名可以支持鏈式屬性路徑"user.age":function(){ },不支持數組內部對象。
  • 參數{deep:true}可以深度監聽對象下面的所有屬性,但oldValue可能不準確。{immediate: true}可以立即觸發一次監聽。

3.3、Vue選項-實例生命週期

Vue實例從①創建階段、到②運行階段、再到③銷燬終結的過程,就是Vue輝煌的一生。在這個過程中Vue提供了一些鉤子函數,這些函數都沒有參數,this指向組件自身。

Vue選項-生命週期鉤子
beforeCreate 創建前:各項屬性配置都還不可用,幾乎不能幹什麼
created 創建後:實例化完成後同步調用。數據、事件、計算屬性已完成,還未掛載模板,可發起ajax請求
beforeMount 掛載el前:模板已完成編譯(各項指令都解析完成了),但還未加入到頁面Dom中
mounted 掛載後-完成渲染:實例被掛載後調用,vm.$el已創建,瀏覽器Dom完成渲染,用戶看到正式的頁面了
beforeUpdate 更新前:數據發生改變後(數據最新),虛擬DOM 更新之前(頁面未更新)
updated 更新後:頁面Dom已更新完成,數據和頁面都是最新的,首次渲染不會觸發
beforeDestroy 實例銷燬之前調用,此時組件還是正常的。
destroyed 實例銷燬後調用,組件已銷燬並從Dom中移除。
activated 組件激活/顯示,被 <keep-alive> 緩存的組件激活時調用
deactivated 組件失活/隱藏,被 <keep-alive> 緩存的組件失活時調用
errorCaptured 捕獲後代組件的錯誤

» 畫個圖:VUE生命週期(ProcessOn版本

image

📢注意:不要在選項 property 或回調上使用箭頭函數,箭頭函數沒有this,會導致默認的this(vm)丟失。

3.4、Vue實例🔖

💠實例屬性 描述
$data vue對象的data實際存儲的數據,vue代理了他的數據訪問
$el el掛載的視圖Dom元素
$options Vue()實例化的選項參數
$refs 通過過ref attribute 註冊的所有 DOM 元素和組件實例的一個對象,this.$refs.header
$parent 父實例,根實例的 $parentnull
$root 組建樹的根實例,根實例的 $root 爲自己
$children 子組件示例數組Array<Vue instance>
$slots 插槽分發的內容,{ [name: string]: ?Array<VNode> }
$scopedSlots 作用域插槽 { [name: string]: props => Array<VNode> &#124; undefined }
$listeners 包含了父作用域中的 (不含 .native 修飾器的) v-on 事件監聽器
$props 組件定義的參數列表
$attrs 父作用域中的非Prop的Attribute特性(不含class、style)
$isServer 是否運行於服務器,服務端渲染

💠實例方法
$watch( expOrFn, callback, [options] ) 添加屬性變更監聽器vm.$watch("title", function (val, old) {});
$set( target, proName/index, value ) 添加響應式的property,並更新視圖。用於後續增加的屬性,同Vue.set()
$delete( target, proName/index ) 刪除對象的 property,同Vue.delete()

💠實例事件
$on( eventName, callback ) 添加一個事件監聽,監聽當前實例上的自定義事件,事件可以由 vm.$emit 觸發
$once( eventName, callback ) 添加一個事件監聽,但是隻觸發一次,觸發後被移除。
$off( [eventName, callback] ) 移除自定義事件監聽器
$emit( eventName, […args] ) 觸發當前實例上的事件,參數eventName爲事件名稱,注意採用小寫命名方式

💠實例方法-生命週期
$mount( [elementOrSelector] ) vue實例掛載一個Dom元素,元素或CSS選擇器
$forceUpdate() 強制更新渲染
$nextTick( [callback] ) Vue.nextTick
$destroy() 完全銷燬一個實例

Vue靜態API

Vue全局靜態屬性/方法 描述
Vue.extend( options ) 創建一個Vue“子類”(不是實例),選項的data必須是函數,避免組件實例共享數據
Vue.nextTick( [callback, context] ) Dom更新後立即調用回調,常用於手動操作Dom(需等Dom更新完),他返回的是一個Promise
🔸Vue更新都是異步的,類似JS的事件循環隊列,不會立即執行,便於去重提高性能
Vue.set( target, proName/index, value ) 向響應式對象中添加一個響應式 property,並觸發視圖更新。可用於強制更新視圖
Vue.delete( target, proName/index ) 刪除對象的 property,會觸發更新
Vue.directive( id, [definition] ) 註冊或獲取全局指令
Vue.filter( id, [definition] ) 註冊或獲取全局過濾器
Vue.component( id, [definition] ) 註冊或獲取全局組件
Vue.use( plugin ) 安裝 Vue.js 插件,爲Vue添加一些全局的功能,如 vue-router
Vue.mixin( mixin ) 全局註冊一個混入,小心使用,會影響後面所有的Vue實例。
Vue.compile( template ) 將一個模板字符串編譯成 render 函數
Vue.observable( object ) 讓一個對象可響應
Vue.version 版本號,Vue.version //'2.7.14'

©️版權申明:版權所有@安木夕,本文內容僅供學習,歡迎指正、交流,轉載請註明出處!原文編輯地址-語雀

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章