vue相關--本身看看的

vue

一 : Vue 介紹

  1. vue 中文網
  2. github 下載地址
  3. Vue.js (讀音 /vju:/ view)
  4. 漸進式 JavaScript 框架 3.1 漸進式 :

    小型項目 就可使用 vue 就高度了 隨着頁面的複雜程序提升,就要學習 vue-rouer 來管理更多的頁面 再隨着項目的數據愈來愈多,管理數據也變得麻煩起來了,就開始使用 vuex 來管理數據javascript

3.2 框架 : 一整套的解決方案php

框架和庫的區別 (面試-->控制翻轉)

1. 庫(Library) , 表明 : jquery

  • 庫就是一系列函數的集合, 咱們開發人員在使用庫的時候,想要完成什麼樣的功能,就調用庫中提供的某個方法

好比 : 想要添加樣式, 就調用 jquery 中的 .css() / .addClass()css

  • 庫起到了一個輔助的做用, 在使用庫的是時候,是由開發人員說了算, 也是由開發人員起主導做用.

好比 : 想給 A:設置樣式 A.css(), B:addClass() C:style.background='red'html

####2. 框架 (Framework), 表明:vue前端

  • 在使用框架的時候,是由框架說了算,由框架起到了主導做用,
  • 框架是一套完整的解決方案,框架中制定了一套規則,使用框架的時候,只須要按照規則,把代碼放到合適的地方,而後框架會在合適的時機,主動調用開發人員的代碼

好比 : 想用vue,組件裏遍歷就得使用 v-for, 下次不用 v-for 了,使用 for 不行 v-for='item in list'vue

3. 主要區別 : 控制反轉

也就是 : 誰起到了主導做用java

  • 使用庫的時候 : 開發人員起主導做用
  • 使用框架的時候:框架起到了主導做用
  • 從體量上看,框架通常比庫大
  • 會發現使用框架的時候,會受到不少限制
  • 咱們所說的前端框架與庫的區別?

三 : MVC + MVVM (面試)

第 3.1 MVC

  1. MVC 是一種軟件架構模式,也有人叫作設計模式
  2. M : Model 數據模型 (專門用來操做數據,數據的 CRUD)
  3. V : View 視圖 (對於前端來講,就是頁面)
  4. C : Controller 控制器 (是視圖和數據模型溝通的橋樑,用於處理業務邏輯)

第 3.2 MVVM

Vue 使用的是 MVVM 模式node

  • MVVM ===> M / V / VM
  • M : model 數據層
  • V : view 視圖層
  • VM : ViewModel 視圖模型
  • 核心 : M <===> VM <===> V

第 3.3 MVVM 優點

  • MVC 模式 將應用程序劃爲三個部分,實現職責分離
    • 可是,在前端中,常常要經過 js 代碼來進行一些邏輯操做,最終還要把這些邏輯操做展現頁面中, 也須要頻繁的操做DOM
    • 好比 : ajax 請求、添加、修改、設置樣式、動畫
  • MVVM 提出來的思想 經過 數據雙向綁定 讓數據自動的雙向同步
    • V (修改視圖) --> M
    • M (修改數據) --> V
  • 採用的是 : 數據驅動視圖的思想, 數據是核心
  • 之後若是想要操做 DOM, 立馬想到的不是應該是拿到元素設置,而是數據

第 3.4 Vue 中的 MVVM

  • 注意 : 不推薦直接手動操做 DOM

    每一個人操做 DOM 的方法不同,會形成性能不同 官網 : 雖然沒有徹底遵循 MVVM 模型,可是 Vue 的設計也受到了它的啓發。所以在文檔中常常會使用 vm (ViewModel 的縮寫) 這個變量名錶示 Vue 實例。jquery

第 3.5 學習 Vue 要轉化思想

  • 數據驅動視圖 : 不要再想着怎麼操做 DOM, 而是想着如何操做數據

四 : 起步 - Hello Vue

第 4.1 : 基本使用

  1. 安裝 : npm i vue (小寫)
  2. 導入 : <script src='./vue.js'></script>
  3. 實例 vue
const vm = new Vue({
  // 指定 vue 管理的邊界
  el: '#app',
  // 提供視圖中 須要的數據
  // 視圖能夠直接使用data中的數據
  data: {
    msg: 'xxx'
  }
})
複製代碼

第 4.2 : 使用注意點

  1. vm 官網建議
  2. Vue 構造函數首字母大寫
  3. 參數是一個對象
  4. id='#app', 其餘也能夠
  5. 邊界外的沒法使用 msg

4.3 {{}} 插值表達式

  1. {{}} Mustache 小鬍子語法, 插值表達式
  2. 做用 : 使用{{}}data中獲取數據,並展現在模板中
  3. 說明 : {{}} 中只能出現 js 表達式
  • 表達式 (有返回值的)
    • 常見的數據類型 1 'abc' false [] {}
    • 數據類型 和 運算符結合在一塊兒1+2 arr.join('-') true ? 123 : 321
  • 語句 if語句 for語句
  1. {{}} 語法 不能做用在 HTML 元素的屬性上
  2. 通常只有單標籤dom元素不可以使用插值表達式

五 : 數據雙向綁定演示

第 5.1 : 一個 input + v-model

v-model 指令 : 數據雙向綁定的指令
 做用 : 把data中的msg值 和  input上的值 綁定到一塊兒
 注意 : v-model只能用在 表單控件上 (input checkbox 等)
 > 能夠在瀏覽器分別演示 V => M  和 M =>V
複製代碼

第 5.2 : Object.defineProperty

let obj = {}
let temp

obj.name = 'zhanhgsan'

// 參數1 : 要給哪一個對象設置屬性
// 參數2 : 給對象設置什麼屬性
// 參數3 : 屬性的修飾符
Object.defineProperty(obj, 'name', {
  set: function(newVal) {
    console.log('賦值了', newVal)
  },
  get: function() {
    console.log('取值了')
    return temp
  }
})
複製代碼

第 5.3 : 數據雙向綁定的原理

  1. <input type="text" id="txt" />
  2. 演示 : V ==> M
//1. 拿到文本框
const txt = document.getElementById('txt')
//2. 時刻監聽txt ,拿到最新的值
txt.oninput = function() {
  console.log(this.value)
  obj.name = this.value
}

//3. 數據模型
var obj = {}
let temp

Object.defineProperty(obj, 'name', {
  // 給屬性賦值的時候會掉
  set: function(newVal) {
    console.log('調用了set', newVal)
    temp = newVal

    txt.value = newVal
  },
  get: function() {
    console.log('調用了get')
    return temp
  }
})
複製代碼
  1. V => M
//1. 獲取 input的值,最新值
//2. 經過監聽oninput 拿到最新值
//3. 把最新值賦值給 obj.name
//4. 就會掉了set方法,就會修改了數據
複製代碼
  1. M => V
//1. obj.name = 'xxx'
//2. 調用 set方法
//3. 把值賦值給input元素
複製代碼

六 : 指令學習

第 6.0 指令

  • 指令 : 就是一個特殊的標記, 起一個輔助做用, 使 html 具有原來沒有的功能
  • vue 中 全部的指令, 都是以 v-開頭的
  • 好比 : v-model v-bind v-if v-for 等等

第 6.1 v-model (經常使用)

說明 : 用在表單元素中, 用來實現數據雙向綁定 (input checkbox 等等) 做用 : 將 數據txt文本框的值 綁定到一塊兒, 任何一方發生改變,都會引發對方的改變 注意 : v-model 在不一樣類型的表單元素中,該指令的做用不一樣webpack

<!-- 文本輸入框 綁定的是值 -->
<input type="text" v-model="txt" />
<!-- 多選框、按鈕 綁定的選中狀態 -->
<input type="checkbox" v-model="isChecked" />
複製代碼

第 6.2 v-text 和 v-html

說明 : 設置文本內容

  1. v-text : 至關於以前的 innerText , 設置文本內容(不識別 html 標籤) == 標籤內部{{}} ===》注意v-text會徹底替換掉標籤裏的內容
  2. v-html : 至關於以前的 innerHTML , 設置文本內容(識別 html 標籤)
  3. 數據
msg1: '<a>這是一條信息</a>',
   msg2: '<a href="#">我也是一條信息</a>'
複製代碼

第 6.3 v-bind (經常使用)

說明 : 動態綁定數據 (單向) 出現緣由 : 在 HTML 屬性中, 沒法使用插值表達式 步驟:

// 加載靜態數據
 <a href="https://wbaidu.com">aaa</a>
// 想加載動態數據  {{ }}能夠獲取data中的數據
// 可是 {{}} 不能使用在屬性中
<a href="{{ src }}">aaa</a>
// 因此使用v-bind
<a v-bind:href="{{ src }}">aaa</a>   ok
 <img v-bind:src="src">   ok
複製代碼

縮略 : v-bind 所有省略 只留下一個: 改成 :

<a :href="src">aaa</a> ok
<img :src="src" /> ok
複製代碼

之後 使用 靜態加載數據 : <a href="https://wbaidu.com">aaa</a> 動態加載數據 : <a :href="href">aaa</a>

第 6.3.1 v-bind 和 v-model 的區別

//  v-model :  數據雙向綁定         表單元素上
//   :      :  動態綁定數據(單向)    任意元素動態讀取屬性

容易出錯點 : 
<!-- v-model 數據雙向綁定 -->
<!--場景 : 表單元素中 -->
<input type="checkbox" v-model="isChecked1" /> <br />
<!-- v-bind 數據動態綁定 (單向) -->
<!--場景 : 主要用在屬性中 -->
<input type="checkbox" :checked="isChecked2" />*
複製代碼

第 6.4 操做樣式

1.操做樣式

<!-- 1. 靜態類名 -->
<h1 class="red">哈哈</h1>

<!-- 2. 動態類名 -->
<h1 :class="cls">哈哈</h1>

<!-- 3. 最經常使用 -->
<!-- :class 裏的值是一個對象 鍵 : 類名 (可能會要,也能夠不要) 值 : 布爾值, true/false 肯定類要不要 -->
<h1 :class="{ red:isRed , fz:isFZ}">哈哈</h1>

<!-- 4. style -->
<h1 :style="{ color : 'red', fontSize : fz + 'px' }">哈哈</h1>
複製代碼

2.其餘操做

<!-- 1 -->
<!-- 重點 -->
<div :class="{ active: true }"></div>
===>
<div class="active"></div>

<!-- 2 -->
<div :class="['active', 'text-danger']"></div>
===>
<div class="active text-danger"></div>

<!-- 3 -->
<div :class="[{ active: true }, errorClass]"></div>
===>
<div class="active text-danger"></div>

--- style ---
<!-- 1 -->
<h1 :style="{ color : 'red', fontSize : fz + 'px' }">哈哈</h1>
<!-- fz : 80 -->

<!-- 2 將多個 樣式對象 應用到一個元素上-->
<!-- baseStyles 和 overridingStyles 都是對象 -->
<!-- 若是有相同的樣式,之後面的樣式爲準 -->
<div :style="[baseStyles, overridingStyles]"></div>
複製代碼

第 6.5 v-on 指令

註冊事件/綁定事件

  1. v-on:click 綁定了一個單擊事件

    : 後面是事件名稱

<button v-on:click="fn">按鈕</button>
複製代碼
  1. 縮寫 : @click='fn' <button @click='fn'>按鈕</button>

  2. 函數寫在 methods 裏面

fn : function(){ ... }
fn() { ... }
複製代碼
  1. 函數裏面的 this 指的就是 vm 實例
> 在函數裏面操做數據
- 獲取數據  this.msg
- 修改數據  this.msg = 'XXX'
複製代碼
  1. 傳參 5.1 正常傳參
@click='fn(123)'
複製代碼

5.2 事件對象 $event

<!-- 4.1 綁定事件對象的時候, 沒有添加小括號,此時,直接在方法中,經過參數 e 就能夠獲取到事件對象 -->
<!-- 4.2 若是添加小括號,就拿不到事件對象了,vue留了一個$event -->
<button @click="fn1($event,123)">我是按鈕</button>
複製代碼

6.5 v-for

  1. v-for 指令: 遍歷數據,爲數據中的每一項生成一個指令所在的標籤
  2. 代碼
<!-- 需求1 : 最經常使用 遍歷數組 -->
<!-- 做用 : 遍歷 list1 數據, 爲數據中的每一項生成一個li標籤 -->
<!-- item 數組裏的每一項元素 -->
<ul>
  <li v-for="(item,index) in list1">{{ item }} - {{ index }}</li>
</ul>
<!-- 需求2 : 遍歷元素是對象的數組 -->
<ul>
  <li v-for="item in list2">{{ item.name }} - id:{{ item.id }}</li>
</ul>

<!-- 需求3 : 遍歷對象 -->
<ul>
  <li v-for="(item,key) in obj">{{ item }}-{{key}}</li>
</ul>

<!-- 需求4 : 想要生成10個h1 -->
<h1 v-for="item in 10">我是h1 {{ item }}</h1>
複製代碼
  1. 重點是遍歷數組,,其餘的瞭解便可

    注意用v-for更新已經渲染過的元素列表的時候,他會默認就地複用策略,若是數組的順序發生改變,vue不會必定dom元素來匹配順序,而是簡單的複用此處的每一個元素,這樣每一個節點的狀態就會對應不上

    解決這時候就須要給每一個列表元素提供一個key,這個key須要是惟一的,以保證vue能準確的追蹤到每一個節點,key最好是列表中每項的id

七 : TODOMVC

###一 : 準備工做

  1. Vue-TodoMVC

  2. 演示效果 :

  3. 當前任務:敲代碼、視頻、遊戲

  4. 下載模板地址

    git clone https://github.com/tastejs/todomvc-app-template.git

  5. 安裝依賴包 : npm i

二 : 配置 vue

  1. 安裝 vue : npm i vue

  2. 導入 vue : <script src="./node_modules//vue/dist/vue.js"></script>

    index.html裏的app.js 導入以前導入,由於 app.js 裏 就要用到 vue 了

  3. 實例化 vue :在app.js中建立 vue 示例,並設置好邊界 el:'#app'

    找到 index.html ,給 section 標籤添加一個 id

  4. 測試 vue :

    data 中隨便來一個 msg 看能不能顯示到視圖中

生命週期函數

  • 全部的 vue 組件,都是 vue 實例, 一個組件對應一個實例,而且接收相同的選項對象(一些根實例特有的選項除外)
  • 實例生命週期也叫作 : 組件生命週期

這裏先甩一張圖

![](D:\study\筆記\個人整理\images\vue\Vue實例生命週期圖 - 新版.png)

生命週期介紹

vue 生命週期鉤子函數

  • 簡單說 : 一個組件(實例) 從開始到最後消滅所經歷的各類狀態,就是一個組件(實例)的生命週期
  • 生命週期鉤子函數的定義 : 從組件被建立,到組件掛在到頁面上運行,再到頁面關閉組件被銷燬,這三個階段老是伴隨着組件各類的事件,這些事件,統稱爲組件的生命週期函數 (簡稱 : 鉤子函數)
  • 開發人員能夠經過 vue 提供的鉤子函數,讓咱們寫的代碼參與到 vue 的生命週期裏面來,讓咱們的代碼在合適的階段起到相應的做用

#####注意 :

  1. 注意 : vue 在執行過程當中 會自動調用 生命週期鉤子函數, 咱們只須要提供這些鉤子函數便可
  2. 注意 : 鉤子函數的名稱都是 vue 中規定好的

學習 vue 組件生命週期 學什麼?

  1. Vue 內部執行的流程(難)
  2. 鉤子函數如何使用 (兩個重要的鉤子函數 created mounted)

鉤子函數 - beforeCreate

  • 說明 : 在實例初始化以前,數據觀測 和 event/watcher 事件配置以前被調用

  • 組件實例剛被建立,組件屬性計算以前, 例如 data 屬性 methods 屬性

  • 注意 : 此時,沒法獲取 data 中的數據 和 methoids 中的方法

  • 場景 : 幾乎不用


鉤子函數 - created (掌握)

  • 說明 : 組件實例建立完成,屬性已綁定, 能夠調用 methods 中的方法、能夠獲取 data 值

  • vue 實例生命週期 參考 1

  • vue 實例生命週期 參考 2

  • 使用場景 : 1-發送 ajax 2-本地存儲獲取數據

  • beforeCreate() {
        // 沒法獲取數據和事件
        console.warn('beforeCreate', this.msg, this.fn)
    },
    created() {
      console.warn('created', this.msg, this.fn)
    },
    複製代碼

Has 'el' option ?

  1. YES => 就是正常的 el 邊界
  2. NO => 能夠註釋,可是必需要手動添加 vm.$mount(el) 去指定邊界
vm.$mount('#app')
複製代碼

Has template option?

  1. No => 將 el 的 outerHtml 做爲模板進行編譯 ( outerHTML = 自身 + innerHTML )
  2. YES =>
// 若是提供了 template, 那麼 vue 就會將 template 的內容進行編譯,編譯後,替換頁面中 vue 管理的邊界
   template : ` <h1>嘻嘻</h1> `,
複製代碼

鉤子函數 - beforeMounted()

  • 說明 : 在掛載開始以前被調用 (掛載:能夠理解DOM 渲染)

鉤子函數 - mounted() (掌握)

  • 說明 : 掛載以後, DOM 完成渲染

  • 使用場景 : 1-發送 ajax 2-操做 DOM

  • 記得把template去掉 
    // 渲染DOM以前
     beforeMount() {
         // 渲染以前的 <h1 id="h1" @click="fn">{{ msg }}</h1>
       console.log(document.getElementById('h1'))
     },
     // 渲染DOM以後 <h1 id="h1">測試</h1>
     mounted() {
       console.log(document.getElementById('h1'))
     }
    複製代碼

鉤子函數 - beforeUpdated()

  • 說明:數據更新時調用,發生在虛擬 DOM 從新渲染和打補丁以前。你能夠在這個鉤子中進一步地更改狀態,這不會觸發附加的重渲染過程。

  • 注意:此處獲取的數據是更新後的數據,可是獲取頁面中的 DOM 元素是更新以前的

    小提示 : 打印 this.$el ,打開小三角是以後的,是由於打印是有監聽的功能,展現的是後面更改以後的


鉤子函數 - updated()

  • 說明:組件 DOM 已經更新,因此你如今能夠執行依賴於 DOM 的操做。

  • beforeUpdate() {
        // 更新以前的值 : 信息
      console.warn('beforeUpdate', document.getElementById('h1').innerText)
    },
    updated() {
        // 更新以後的值 : 信息1111
      console.warn('updated', document.getElementById('h1').innerText)
    }
    複製代碼

鉤子函數 - beforeDestroy()

  • 說明:實例銷燬以前調用。在這一步,實例仍然徹底可用。
  • 使用場景:實例銷燬以前,執行清理任務,好比:清除定時器等
created() {

   this.timerId =   setInterval(() => {
      console.log(1111);

      }, 500);
   },

 // 若是當組件銷燬了,還不清除定時器會出現性能問題
 // 在瀏覽器中能夠嘗試銷燬 vm.$destroy()
 // 最後銷燬
beforeDestroy() {
      clearInterval(this.timerId)
 },
複製代碼

鉤子函數 - destroyed()

說明:Vue 實例銷燬後調用。調用後,Vue 實例指示的全部東西都會解綁定,全部的事件監聽器會被移除,全部的子實例也會被銷燬。


使用鉤子函數來完善 數據存儲

created {
    this.list = localStorage.getItem('list')
}
複製代碼

使用接口的形式發送數據

一 : json-server 提供假數據接口

  1. json-server 做用 : 根據指定的 JSON 文件, 提供假數據接口

  2. 地址 : json-server

  3. 使用步驟

    1. 全局安裝 json-server  : `npm i -g json-server`
    2. 準備一個json數據
    3. 執行 :  `json-server data.json`
    
    > json數據參考
    json數據能夠參考 :
    {
      "todos": [
        {
          "id": 1,
          "name": "吃飯",
          "age": 20
        }
      ]
    }
    複製代碼
  4. REST API 格式

* 1. 查詢 : GET
* 2. 添加 : POST
* 3. 刪除 : DELETE
* 4. 更新 : PUT 或者 PATCH(打補丁)
複製代碼
  1. 具體接口
* 1. 查詢所有數據 http://localhost:3000/todos
*    查詢指定數據 http://localhost:3000/todos/2
*
*  2. 添加一個對象 //localhost:3000/todos
*     POST
*     id 會自動幫咱們添加
*
* 3. 更新數據 http://localhost:3000/todos/3
*    PUT 或者 PATCH
*    PUT 須要提供該對象的全部數據
*    PATCH 只須要提供要修改的數據便可
*
* 4. 刪除數據
*    http://localhost:3000/todos/3
*    DELETE
複製代碼
  1. 能夠藉助 postman 測試接口;

二 : axios 發送請求 (重點掌握)

讀音 : /艾克笑絲/

  1. 做用 : 一個專門用來發送 ajax 請求的庫, 能夠在瀏覽器或者 node.js 中使用

    Promise based HTTP client for the browser and node.js
    	以Promise爲基礎的HTTP客戶端,適用於:瀏覽器和node.js
    	封裝ajax,用來發送請求,異步獲取數據
    複製代碼
  2. 使用步驟

    1. 本地安裝 axios : `npm i axios`
    2. 導入 axios
    3. 使用
    複製代碼
  3. axios 使用說明

  4. GTE 方式發送請求

    // 方式1
    axios.get('http://localhost:3000/todos/3').then(res => {
      console.log('獲取到數據了:', res.data)
    })
    // 方式2
    axios
      .get('http://localhost:3000/menus', {
        params: {
          id: 003
        }
      })
      .then(res => {
        console.log('獲取到數據了:', res.data)
      })
    複製代碼

    五、 POST 方式發送請求

    // post 請求
         axios
             // 第一個參數:表示接口地址
             // 第二個參數:表示接口須要的參數
             .post('http://localhost:3000/todos', {
               name: 'axios添加數據',
               done: true
             }).then ( res =>  打印 res)
    複製代碼
  5. 使用axios測試 todos 的幾種接口

//1. GET
      // 沒有參數
      axios.get('http://localhost:3000/todo').then(res => {
        console.log(res)
      })
      // 有參數
      axios.get('http://localhost:3000/todo/1').then(res => {
        console.log(res)
      })
      axios
        .get('http://localhost:3000/todo', {
          params: {
            id: 2
          }
        })
        .then(res => {
          console.log(res)
        })

      // 2. POST
      axios
        .post('http://localhost:3000/todo', {
          name: 'XXX',
          age: 1
        })
        .then(res => {
          console.log(res)
        })

      //3. 刪除
      axios.delete('http://localhost:3000/todo/8', {}).then(res => {
        console.log(res)
      })

      //4. 更新 - put
      axios
        .put('http://localhost:3000/todo/2', {
          name: '111',
          age: 300
        })
        .then(res => {
          console.log(res)
        })

      // 4. 更新 - patch
      axios
        .patch('http://localhost:3000/todo/1', {
          age: 3000
        })
        .then(res => {
          console.log(res)
        })
複製代碼

三 : 完善 TodoMVC

  1. 獲取所有

    axios.get('http://localhost:3000/list').then(res => {
        console.log(res.data);
        this.list = res.data;
    });
    複製代碼
  2. 刪除任務

    axios.delete('http://localhost:3000/list/' + id).then(res => {
        this.list = this.list.filter(item => item.id !== id);
        console.log(res);
    });
    複製代碼
  3. 添加任務

    # id 會自動加
    axios
        .post('http://localhost:3000/list', {
        name: todoName,
        done: false
    })
        .then(res => {
        console.log(res.data);
        this.list.push({
            // 屬性名 和屬性值 同樣的話,,能夠省略一個
            id,
            name: todoName,
            done: false
        });
    });
    複製代碼
  4. 更新任務 (在 hideEdit 裏實現)

    # 難點1 : 在 hideEdit 這個方法裏
    # 難點2 : 獲取的這個id 就是editId
    hideEdit(e) {
    
    axios.patch('http://localhost:3000/list/' + this.editId, {
        name: e.target.value
    }).then(res => {
        console.log(res);
    
        this.editId = -1;
    })
    
    },
    複製代碼
  5. 刪除已經完成 的

    # 由於 這個假接口沒有實現如下刪除 完畢
    clearCompleted() {
        // 清除已經完成的,,只須要過濾出來未完成的便可
    
        let arr = this.list.filter(item => item.done);
        arr = arr.map(item => item.id);
    
        for (let i = 0; i < arr.length; i++) {
            axios.delete('http://localhost:3000/list/' + arr[i]).then(res => {
                this.list = this.list.filter(item => item.id != arr[i]);
            });
        }
    },
    複製代碼
  6. 點擊修改狀態

    # 單獨給 checkbox 都註冊點擊事件
    clickBox(id) {
        let todo = this.list.find(item => item.id == id);
    
        axios.patch('http://localhost:3000/list/' + id, {
            done: !todo.done
            }).then(res => {
            console.log(res);
            });
    }
    複製代碼

單頁面應用程序

  • SPA : Single Page Application
  • MPA : Multiple Page Application 多頁面應用程序
單頁web應用,
  就是隻有一個web頁面的應用,
  是加載單個HTML頁面,
  並在用戶與應用程序交互時動態更新該頁面的web應用程序
複製代碼
  • 區別
對於傳統的多頁面應用程序來講, 每次請求服務器返回的都是一個完整的頁面

對於單頁應用程序來講,
  只有第一次會加載頁面,
  之後的每次請求,
  僅僅是獲取必要的數據.而後,
  由頁面中js解析獲取的數據,
  展現在頁面中
複製代碼
  • 單頁面優點 :
    1. 減小了請求體積,加快頁面響應速度,下降了對服務器的壓力
    2. 更好的用戶體驗,讓用戶在 web app 感覺 native app 的流暢, (局部刷新)
  • 單頁面劣勢 :
    1. 開發成本高
    2. 不利於SEO
  • 演示 : music.163.com/

組件 (重難點)

一 : 組件化開發

  • 概念 :將一個完整的頁面,抽離成一個個獨立的組件,最終,經過這一個個獨立組件完成整個的頁面(項目)的功能
  • 組件化開發的優點/做用 : 複用
  • 官網 : 組件是可複用的 Vue 實例

二 : 組件的基本使用

  1. Vue 中的兩種註冊組件的方法 1.全局註冊 2.局部註冊

    全局組件在全部的vue實例中均可以使用
    局部組件在全部的當前實例中可使用
    複製代碼
  1. 註冊全局組件 - 基本使用 1
/** * 第一個參數 : 組件名 * 第二個參數 : 是一個配置對象, 該配置對象與 Vue 實例的配置對象幾乎徹底相同 * 也就是說: vue實例中用到的配置項,和組件中的配置項幾乎相同 */
Vue.component('hello', {
  template: ` <h1 class="red">這是hello組件</h1> `
})
複製代碼
  1. 注意點
  • 註冊全局組件也是放到 vm 實例以前
  • 模板只有一個根節點
  • 組件的配置項和 vue 實例 的配置項同樣 (如:data、methods、filters、watch、computed、鉤子函數等)
  • 組件的 data 是一個函數 返回一個對象
var Component = function() {}
      // 使用對象
      Component.prototype.data = {
        demo: 123
      }
      // 使用函數
      Component.prototype.data = function() {
        return {
          demo: 111
        }
      }
      var component1 = new Component()
      var component2 = new Component()
      component1.data().demo = '8888'
      console.log(component2.data().demo) // 456
複製代碼

示例:

<h1 @click='fn' class="red">這是hello組件</h1>
  methods: {
          fn() {
            console.log('fn')
          }
        },
        computed: {},
        watch: {},
        filters: {}
}
複製代碼

三: 改造 TodoMVC 成 組件化結構

  1. 安裝 vue + 實例化
  2. 建立一個 components 文件夾
  3. 具體步驟
  • 建立一個 todo-head.js
  • 導入 <script src="./components/todo-head.js"></script>
  • 使用 <todo-head></todo-head>

四 : 組件通信 (介紹)

  • 組件是一個獨立、封閉的個體
  • 也就是說 : 組件中的數據默認狀況下, 只能在組件內部使用,沒法直接在組件外部使用
  • 能夠將 vue 實例看作一個組件
  • 對於組件之間須要相互使用彼此的狀況,應該使用 組件通信 機制來解決
  • 組件通信的三種狀況 :
  1. 父組件將數據傳遞給子組件(父 -> 子)
  2. 子組件將數據傳遞給父組件 (子 => 父)
  3. 非父子組件(兄弟組件)

五 : 父 ==> 子 (重點) 兩步

  1. 將要傳遞的數據,經過屬性傳遞給子組件
<child :msg="pmsg"></child>
複製代碼
  1. 子組件經過 props 配置項,來指定要接收的數據
props: ['msg']
複製代碼

完善 TodoMVC => 完成 傳值 + 渲染列表頁

六 : 子 ==> 父 (重點) 三步

1 父組件中提供一個方法

pfn(arg) {

    console.log('父組件中接受到子組件傳遞過來的數據:', arg)
 }
複製代碼

2 將這個方法傳遞給子組件

// 自定義事件 <child @fn="pfn"></child>
複製代碼

3 子組件調用這個方法( 觸發父組件中傳遞過來的自定義事件 )

// 這個方法是點擊事件觸發的
 handleClick() {
    // 調用父組件中的方法 fn
    // 注意:經過 $emit 方法來觸發事件 fn
    // 第一個參數:表示要觸發的自定義事件名稱,也就是 @fn
    // 第二個參數:表示要傳遞給父組件的數據
    this.$emit('fn', 'child msg')
}
複製代碼

完善 TodoMVC => 完成 傳值 +添加+ 刪除+清除完成

七 : 目前爲止存屬性的地方

  1. data
  2. 計算屬性
  3. props

八 : 單向數據流(組件與組件之間) (瞭解)

全部的 prop 都使得其父子 prop 之間造成了一個單向下行綁定:父級 prop 的更新會向下流動到子組件中,可是反過來則不行。這樣會防止從子組件意外改變父級組件的狀態,從而致使你的應用的數據流向難以理解。 看圖 當 todo-head 中的 todoName 設置數據後回車添加到 todoList,todoList 的長度就會發生變化, 而後就會根據(組件與組件之間的)單向數據流,把數據單向下流到子組件中 並且必須是經過 props 往下傳遞的才能夠

props 的特色 : 只讀

  1. 驗證 props 只讀

  2. 正常下是不須要子組件修改父組件傳過來的值的,可是.....

  3. 修改父組件傳給子組件的數據

    思路 : 把接收過來的數據,保存到 data 中一個臨時值

Vue.component('child', {
        template: ` <div>子組件 {{ cmsg }} </div> `,
        data() {
          return {
            cmsg: this.msg
          }
        },
        props: ['msg'],
        created() {
          this.cmsg = 666
        }
      })
複製代碼

prop 的大小寫

  1. 官 : HTML 中的特性名是大小寫不敏感的,因此瀏覽器會把全部大寫字符解釋爲小寫字符。

    html 的標籤和 屬性 都是同樣,忽略大小寫 <H1 TITLE="哈哈">我是h1</H1>

  2. 官 : 這意味着當你使用 DOM 中的模板時,camelCase (駝峯命名法) 的 prop 名很差使了

  • <child :cMsg="pmsg"></child> 會報警告,父傳子也接收不到了
  • 緣由是 : 接收的屬性是:cMsg, 接收的數據名,由於忽略大小寫,數據已爲 : cmsg
  • 因此已經準備要讀取的 是 cmsg 的值,找不到,因此要報警告 You should probably use "c-msg" instead of "cMsg".
  1. 方式 1 : 全用小寫,不要使用駝峯命名

    接收 : cmsg props/讀取 :cmsg

  2. 方式 2 官 : 須要使用其等價的 kebab-case (短橫線分隔命名) 命名:

    接收 : :c-msg='pmsg' props/讀取 : cMsg

九 : 完善 TodoMVC : 底部隱藏+剩餘完成數+清除完成

計算屬性 : 已知值(todoList 在 根組件) ==> 獲得一個新值(子組件裏使用)

父 => 子通信

十 : 非父子之間通信 ( 組件 => 組件 ) (重點)

需求 : 組件 jack ===> 恁弄啥哩 ===> 組件 rose

  • 是經過 事件總線 (event bus 公交車) 的機制 來實現的
  • 事件總線 : 實際上就是一個 空Vue實例
  • 能夠實現任意兩個組件之間的通信,而無論兩個組件到底有什麼樣的層級關係
  • 看圖
  • 示例 :
// 第一步 : 事件總線
var bus = new Vue()

// 第二步 : 發送數據 可在點擊事件裏 觸發事件
// 參數1 : 惟一標識 參數2:參數
bus.$emit('todo', '恁弄啥哩?')

// 第三步 : 接收數據 可在 created 裏 註冊事件
bus.$on('todo', arg => {
  console.log('接收過來的', arg)
})
複製代碼

十二 : 註冊局部組件

  • 局部組件只能在當前父組件的模板中使用
  • 不能再其餘子組件裏的子組件裏顯示
  • 示例 :
// 註冊局部組件:
components: {
  // child表示組件名稱
  // 值爲配置對象,與 Vue.component 中的第二個參數相同
  // 注意:子組件child屬於 Vue實例,所以,只能在 Vue實例的模板中使用
  child: {
    template: ` <div>這是局部組件 child</div> `
  }
}
複製代碼

十三 : 獲取組件(或DOM元素) - refs

  • 說明 : vm.$refs 一個對象, 持有已註冊過 ref 的全部子組件 ( HTML 元素)

  • 使用 :

    1. 註冊
    // 標籤
    <div ref="div">哈哈</div>
    // 組件 
    <child ref="child"></child>
    複製代碼
    1. js 中使用
    // mounted 操做DOM
    * this.$refs.div
    * this.$refs.child
    
    複製代碼
  • 注意點 : 若是獲取的是一個子組件,那麼經過 ref 就能獲取到子組件中的 datamethods

    this.$refs.child.num
    this.$refs.child.fn
    複製代碼
  • 場景 : 通常在第三方的組件中, 可能會用到這個功能

  • 示例 :

// 組件
 <div ref="div">哈哈</div>
 <child ref="child"></child>
// js
 mounted() {
    console.log(this.$refs.div)
    console.log(this.$refs.child.fn)
  }
複製代碼

單頁面應用與路由

單頁面應用程序

  • SPA : Single Page Application
  • MPA : Multiple Page Application 多頁面應用程序
單頁web應用,
  就是隻有一個web頁面的應用,
  是加載單個HTML頁面,
  並在用戶與應用程序交互時動態更新該頁面的web應用程序
複製代碼
  • 區別
對於傳統的多頁面應用程序來講, 每次請求服務器返回的都是一個完整的頁面

對於單頁應用程序來講,
  只有第一次會加載頁面,
  之後的每次請求,
  僅僅是獲取必要的數據.而後,
  由頁面中js解析獲取的數據,
  展現在頁面中
複製代碼
  • 單頁面優點 :
    1. 減小了請求體積,加快頁面響應速度,下降了對服務器的壓力
    2. 更好的用戶體驗,讓用戶在 web app 感覺 native app 的流暢, (局部刷新)
  • 單頁面劣勢 :
    1. 開發成本高
    2. 不利於SEO
  • 演示 : music.163.com/

路由

  • 路由 : 是瀏覽器 URL 中的哈希值( # hash) 與 展現視圖內容 之間的對應規則
在 web App 中, 經過一個頁面來展現和管理整個應用的功能.
SPA 每每是功能複雜的應用,爲了有效管理全部視圖內容,前端路由 應運而生. (爲何要學習路由??)
簡單來講,路由就是一套映射規則(一對一的對應規則), 由開發人員制定規則.
當 URL 中的哈希值( `#` hash) 發生改變後,路由會根據制定好的規則, 展現對應的視圖內容
複製代碼
  • vue 中的路由 : 是 hashcomponent 的對應關係, 一個哈希值對應一個組件

基本使用

    1. 安裝路由 : npm i vue-router
    1. 引入路由
<script src="./vue.js"></script>
    // 千萬注意 :引入路由必定要在引入vue以後,由於vue-router是基於vue工做的
    <script src="./node_modules/vue-router/dist/vue-router.js"></script>
複製代碼
    1. 詳細使用步驟
  • 3.0 實例路由對象+掛載到 vue 上

    const router = new VueRouter() 路由實例 與 Vue 實例 關聯到一塊兒 驗證路由是否掛載成功, 就看打開頁面,最後面有沒有個 #/

  • 3.1 入口 (#哈希值)

// 方式1 : url地址爲入口 調試開發用
輸入url地址 改變哈希值
`01-路由的基本使用.html#/one`

// 方式2 : router-link+to

複製代碼
  • 3.2 設置路由規則
// path : 路由路徑
// component : 未來要展現的路由組件
routes: [{ path: '/one', component: One }, { path: '/two', component: Two }]
複製代碼
  • 3.3 組件

    一個哈希值對應一個組件

const One = Vue.component('one', {
  template: ` <div> 子組件 one </div> `
})
複製代碼
  • 3.4 出口
<!-- 出口 組件要展現的地方-->
<router-view></router-view>
複製代碼
  1. 分析執行過程(看圖)

使用注意事項

  1. 入口(哈希)
  • 最經常使用的入口
<!-- 1. 入口 -->
<!-- to 屬性 , 實際上就是哈希值,未來要參與路由規則中進行與組件匹配 router-link 組件最終渲染爲 : a標籤, to屬性轉化爲 a標籤的href屬性 -->
<router-link to="/one">首頁</router-link>
複製代碼
  1. 組件

    組件能夠改成對象格式

const One = {
  template: ` <div> 子組件 one </div> `
}
複製代碼
  1. 過程 : 入口 ==> 路由規則 ==> 組件 ==> 出口

  2. 演示 : 多個組件匹配

    能夠有多個入口,但只須要一個出口

  3. 示例 :

<div id="app">
  <!-- 1 路由入口:連接導航 -->
  <router-link to="/one">One</router-link>
  <router-link to="/two">Two</router-link>

  <!-- 4 路由出口:用來展現匹配路由視圖內容 -->
  <router-view></router-view>
</div>

<!--  導入 vue.js -->
<script src="./vue.js"></script>
<!--  導入 路由文件 -->
<script src="./node_modules/vue-router/dist/vue-router.js"></script>
<script>
  // 3 建立兩個組件
  const One = Vue.component('one', {
    template: '<h1>這是 one 組件</h1>'
  })
  const Two = Vue.component('two', {
    template: '<h1>這是 two 組件</h1>'
  })

  // 0 建立路由對象
  const router = new VueRouter({
    // 2. 路由規則
    routes: [
      { path: '/one', component: One },
      { path: '/two', component: Two }
    ]
  })

  const vm = new Vue({
    el: '#app',
    //0. 不要忘記,將路由與vue實例關聯到一塊兒!
    router
  })
</script>
複製代碼

複習一遍代碼 + 流程

入口導航菜單高亮處理

  1. 點擊導航發現代碼有兩個類 :
<a href="#/one" class="router-link-exact-active router-link-active">One</a>
<a href="#/two" class="">Two</a>
複製代碼
  1. 修改方式 1 : 直接修改類的內容
.router-link-exact-active,
.router-link-active {
  color: red;
  font-size: 50px;
}
複製代碼
  1. 修飾方式 2 : 修改默認高亮類名 (推薦)

    由於有時候項目中可能已經針對導航有過設置樣式,後來再加的路由,因此若是再從新像方式 1 再加一次,會重複 因此 :能夠 修改默認高亮的 a 標籤的類名

const router = new VueRouter({
  routes: [],

  // 修改默認高亮的a標籤的類名
  // red 是已經存在過的
  linkActiveClass: 'red'
})
複製代碼

精確匹配和模糊匹配

  • 精確匹配 : router-link-exact-active 類名 : 只有當 瀏覽器地址欄中的哈希值 與 router-link 的 to 屬性值,徹底匹配對,纔會添加該類
  • 模糊匹配: router-link-active 類名 : 只要 瀏覽器地址欄中的哈希值 包含 router-link 的 to 屬性值,就會添加該類名
  • 解決辦法 : 加個 exact
<router-link to="/" exact>
  One
</router-link>
複製代碼
  • 注意 : 精確匹配和模糊匹配,只對添加類名這個機制有效,與路由的匹配規則無關!!!

路由參數

看圖分析: 列表 => 詳情組件

  1. 導航入口
<!-- 1. 入口 -->
<router-link to="/detail/1">手機1</router-link>
<router-link to="/detail/2">手機2</router-link>
<router-link to="/detail/3">手機3</router-link>
複製代碼
  1. 傳參: 最笨的方式
routes: [
  // 2 . 路由規則
  { path: '/detail/1', component: Detail },
  { path: '/detail/2', component: Detail },
  { path: '/detail/3', component: Detail }
]

//3. 組件
const Detail = Vue.component('detail', {
  template: ` <div> 顯示詳情頁內容....{{ $route.path }} </div> `
})
複製代碼
  1. 正確的方式 : 把傳過去的 1/2/3 當成參數 3.1 路由規則的正確方式 :
routes: [
  // 2 . 路由規則
  { path: '/detail/:id', component: Detail }
]
複製代碼

3.2 獲取參數的三種正確方式

const Detail = Vue.component('detail', {
  template: ` // 方式1 : 組件中直接讀取 <div> 顯示詳情頁內容....{{ $route.params.id }} </div> `,
  created() {
    // 方式2 : js直接讀取
    // 打印只會打印一次,由於組件是複用的,每次進來鉤子函數只會執行一次
    console.log(this.$route.params.id)
  },
  // 方式3 : 監聽路由的參數變化 爲何不須要深度監聽,由於它不是data中的
  watch: {
    $route(to, from) {
      console.log(to.params.id)
    }
  }
})
複製代碼
  1. 若是輸入的沒有帶參數的

    有參數的對應 : 下面都是正確打開方式

detail/1 ==> 顯示詳情頁內容....1
detail/2 ==> 顯示詳情頁內容....2
detail/3 ==> 顯示詳情頁內容....3
複製代碼

若是經過改變 url 地址,不輸入參數 就看不到 顯示詳情頁內容 這些字 說明沒有正確匹配到 detail組件

  • 有可能不輸入參數 :後面加個? 表明可傳可不傳
  • ** { path: '/detail/:id?', component: Detail }**
// 可識別的路徑是這樣的
* detail
* detial/1
* detial/2
* detial/3
複製代碼
  1. 示例 :
// 連接:
<router-link to="/user/1001">用戶 Jack</router-link>
<router-link to="/user/1002">用戶 Rose</router-link>

// 路由:
{ path: '/user/:id', component: User }

// User組件:
const User = {
  template: `<div>User {{ $route.params.id }}</div>`
}
複製代碼

重定向

  • 解釋:將 / 重定向到 /home
{ path: '/', redirect: '/home' }
複製代碼

子組件 (項目中講)

Webpack

概念 ==> webpack 是什麼?? 前端模塊化打包(構建)工具

webpack能夠解決這些依賴關係,並對他們進行打包

webpack 的兩個方面

1 - 打包 2 - 模塊化

1、打包 : 前端打包(構建)都能作什麼??

  1. 語法轉換

    - Less/SASS 預編譯CSS -> CSS -> 瀏覽器中使用
    - ES6 新語法有兼容性問題 -> ES5 -> 瀏覽器中使用
    - const fn = () => {} ===> var fn = function() {}
    複製代碼
  2. 文件壓縮、合併

    JS/HTML/CSS 壓縮後,才能發佈上線
    文件合併( 無論有多個JS、CSS,默認打包直接生成一個JS文件 )
    複製代碼
  3. 開發期間提供一個服務器環境

    自動打開瀏覽器、監視文件變化,自動刷新瀏覽器
    複製代碼
  4. 項目上線,打包後才能上線

  5. 總結

    webpack 這個打包(構建)工具,就是提供了前端開發須要的一整套完整的流程,也就是
     webpack 可以滲透的前端開發的各個環節、各個流程中,幫你實現 複雜、繁瑣、重複的工做,有了 webpack 後,開發人員只須要關注當前要實現的業務便可。
    複製代碼

2、模塊化功能

  • 模塊化 : 邏輯

  • 組件化 : 界面

  • webpack爲前端提供了模塊化開發環境,並且webpack是基於node,有了webpack,就能夠像寫Node代碼同樣,寫前端代碼了

  • 在 webpack 看來全部的資源都是模塊,無論是: CSS、圖片、字體、JS、html 等

  • 在webpack提供的模塊化環境中,
    1 想要加載一個JS文件,只須要 require('./a.js')
    2 想要加載一個CSS文件,只須要 require('../css/index.css')
    3 想要加載一個圖片文件,只須要 require('../iamges/a.png')
    4 ...
    複製代碼

Webpack 四個核心概念:

入口(entry)出口(output)加載器(loader)插件(plugins)

  • 入口 : 要打包哪一個文件
  • 出口 : 要打包到哪裏
  • 加載器 : 加載除了js文件其餘文件的功能
  • 插件 : 處理加載器完成不了的功能, 使用插件

學習 手動配置 webpack 的目的

  • 爲了咱們後面使用腳手架作準備,
  • 可以完成webpack的基本安裝
  • 可以瞭解webpack配置文件的做用
  • 可以說出webpack中loader 的做用
  • 可以使用webpack處理常見的資源(css/less/圖片)
  • 可以說出webpack-dev-server的做用以及配置
  • 目標 : 能跟着 視頻 + 筆記 照着敲完一遍便可

webpack 使用步驟 (最新版)

第一階段

命名初始化階段

文件名不能有漢字,不能取名叫 webpack

  1. 生成 package.json, 命令 : npm init -y
  2. 安裝 : npm i -D webpack webpack-cli
webpack  : 是 webpack 工具的核心包
webpack-cli : 提供了一些在終端中使用的命令
-D(--save-dev) : 表示項目開發期間的依賴,也就是 : 線上代碼中用不到這些包了
複製代碼
  1. 建立一個main.js文件
console.log('我就要被打包了,哦也');
複製代碼
  1. package.jsonscripts中,添加腳本
"scripts": {
    "build": "webpack main.js"
  },
// webpack 是webpack-cli 中提供的命令, 用來實現打包的
// ./main.js 入口文件,要打包哪一個文件
複製代碼
  1. 運行 : npm run build
  2. 設置開發狀態 : mode
"build" : "webpack ./main.js --mode development"

// WARNING in configuration
// The 'mode' option has not been set, webpack will fallback to 'production' for this value.
// 若是沒有設置 mode 配置項, webpack 會默認提供 開發環境(production)

// Set 'mode' option to 'development' or 'production' to enable defaults for each environment.
// 項目開發的兩種環境
  1. 開發環境 (development) : 開發過程就是開發環境
  2. 生產環境 (production) : 線上環境, 也就是 : 項目作好了,發佈上線
  生產環境下, 打包生產的js文件都是壓縮後的,  開發環境下代碼通常是不壓縮的
複製代碼

第一階段 隔行變色案例

  1. 建立 src/index.html
  2. 隔行案例 => html => ul#list>li{我是 li \$}\*10
  3. 安裝 juqery : npm i jquery, 而且引入 jquery
  4. 暫時引入 main.js , 在 main.js 裏寫入
// 使用ES6的模塊化語法
import $ from 'jquery' // 優勢 不用沿着路徑去找

$('#list > li:odd').css('backgroundColor', 'red')
$('#list > li:even').css('backgroundColor', 'green')
// 語法報錯
複製代碼
  1. 問題 :
// 引入 main.js 會報錯,由於瀏覽器不支持這個import 的Es6語法
// npm run build 以後
// 引入 dist/main.js 後會ok,由於webpack 幫咱們轉化爲瀏覽器可以識別的es5語法了
複製代碼
  1. 歷程 :
//1. 若是index.html 中引入 jquery , 再引入 mian.js (沒有引入jquery了) => ok
//2. 若是index.html 中沒有引入 jquery , 直接使用es6的模塊化語法 import , 引入main.js就會報錯
//3. 若是index.html 中沒有引入 jquery , 直接使用es6的模塊化語法 import , webapck打包出 dist/main.js 引入 dist/main.js ==> ok
複製代碼
  1. 爲何 dist文件下的main.js 文件裏的代碼忽然這麼多

    看圖 (打包流程)

  2. code 記得保存一份

第二階段

配置文件

  1. 準備工做 : src源文件 : index.htmlmain.js

  2. webpack 打包有兩種方式

    1-命令行 2-配置項

  3. 方式 1 : 命令行

*    "build"  : "webpack ./mian.js" --mode development
*     npm run build
*   通常狀況下 : 改成
*     "build" : 入口  --output 出口
*     "build": "webpack ./src/js/main.js --output ./dist/bundle.js --mode development",
*
*     驗證 : index.html 引入 bundle.js
複製代碼
  1. 方式 2 : 配置項
第一步 : 項目`根目錄`下, 建立一個 `webpack.config.js`文件 (文件名固定死)
         專門指定其餘文件 : --config  webpack.XX.js
第二步 : 在 `webpack.config.js` 中,進行配置
// webpack 是基於 node的 , 因此配置文件符合 node 方式書寫配置
// 注意 : 不要再這個文件中使用ES6的的模塊化 import語法
// main.js裏可使用,是由於要經過webpack轉化爲es5的
// 而這個是webpack 的配置文件,,它是要轉化別人的,因此必需要經過
第三步 : 修改 `package.json` 中的 `scripts` , 腳本命令爲: "build": "webpack"
第四步 : 執行命令 : `npm run build`
複製代碼
  1. 示例代碼(webpack.config.js) :
const path = require('path')

module.exports = {
  // 入口
  entry: path.join(__dirname, './src/js/main.js'),
  // 出口
  output: {
    // 出口目錄
    path: path.join(__dirname, './dist'),
    filename: 'bundle.js'
  },
  // 開發模式
  mode: 'development'
}
複製代碼

配置文件 html-webpack-plugin

  1. html-webpack-plugin 必備的插件
做用 :
  1. 可以根據指定的模板文件 (index.html),自動生成一個新的 index.html,而且注入到dist文件夾下
  2. 可以自動引入js文件
複製代碼
  1. 安裝 : npm i html-webpack-plugin
  2. 配置 :
第一步: 引入模塊
const htmlWebpackPlugin = require('html-webpack-plugin')
第二步: 配置
// 插件
plugins: [
  // 使用插件 指定模板
  new htmlWebpackPlugin({
    template: path.join(__dirname, './src/index.html')
  })
]
複製代碼

配置文件 : webpack-dev-server

  1. webpack-dev-server 使用 webpack 必備的功能(插件)

做用 : 爲使用 webpack 打包提供一個服務器環境

  • 1.1 自動爲咱們的項目建立一個服務器
  • 1.2 自動打開瀏覽器
  • 1.3 自動監視文件變化,自動刷新瀏覽器...
  1. 使用步驟 :
  • 2.1 安裝 : npm i -D webpack-dev-server
  • 2.2 兩種使用方式: 1-命令行 2-配置文件(推薦)
  1. 方式 1 : 命令行配置
  • 腳本 : "dev" : "webpack-dev-server"
  • 運行到 npm run dev
  • 查看路徑 : "http://localhost:8080/"
  • 「wds」: Project is running at http://localhost:8080/
  • 問題 1 : 自動打開?
  • 解決 : 添加 --open
  • 問題 2 : 指定端口號
  • 解決 : 添加 --port 3001
  • 問題 3 : 熱更新
  • 解決 : --hot ( 整個頁面和整個項目打包 )
  1. 方式 2 : 配置文件配置
// hot 不要寫在配置文件裏面,,否則的話還要配其餘插件麻煩
 "dev" : "webpack-dev-server --hot",

  devServer : {
    open : true,
    port : 3001
  }
複製代碼

第三階段 項目打包上線的說明

  1. 開發模式 : npm run dev ==> 不會打包的 ,只會把項目放到服務器裏
  2. 假設項目開發完成了,要上線,怎麼操做?
2.1 執行 : `npm run build` 對項目進行打包,生成dist文件
2.2 模擬本地服務器 : 安裝 : `npm i -g http-server`
2.3 把dist文件裏的內容放到服務器裏便可, 直接運行`http-server`
複製代碼

第四階段

打包非js文件

webpack 只能處理 js 文件,非 js(css.less.圖片.字體等)處理處理不了, 藉助 loader 加載器

1 : 處理 css 文件

  1. 建立一個 css 文件, 而後在 main.js中引入 import '../css/index.css';

    ul { style-list : none }

  2. 安裝 : npm i -D style-loader css-loader

  3. webpack.config.js 中,添加個新的配置項 module

  4. module 中添加 loader 來處理 css

// loader
module: {
  rules: [
    //1.處理 css
      // 注意點 use執行loader 順序 從右往左
      // css-loader : 讀取css文件內容,將其轉化爲一個模塊
      // style-loader :拿到模塊, 建立一個style標籤,插入頁面中
    { test: /\.css$/, use: ['style-loader', 'css-loader'] }
  ]
}
複製代碼

2 : 處理 less 文件

  1. 建立一個 less 文件, 而後再 main.js 中 引入 import '../css/index.less';
  2. 安裝 : npm i -D less-loader less style-loader css-loader
  3. 在 webpack.config.js 中, 配置 module->rules
  4. 在 module 中, 添加 loader 來處理 less
ul {
  background-color: aqua;
  li {
    &:hover {
      color: yellow;
    }
  }
}
複製代碼
  1. 配置 :

    { test :/\.less$/, use : ['style-loader','css-loader','less-loader'] },
    複製代碼

3 : 處理 圖片 文件

設置背景圖片

.cls {

width: 300px;

height: 300px;

background: url('../css/4.jpg');

background-size: 100%;

}

  1. 安裝 : npm i -D url-loader file-loader

    url-loader (推薦) 和 file-loader 二選一便可

  2. 在 webpack.config.js 添加 loader 規則

// 處理圖片
  { test : /\.(jpg|png)$/, use : ['url-loader'] },
複製代碼
  1. url-loader 默認會將圖片轉化爲 base64 編碼格式, 目的:提升性能
  2. file-loader 在車裏圖片時, 會對文件進行重命名 :
原始:    background-image: url(../images/1.jpg);
處理後:  background-image: url(9c9690b56876ea9b4d092c0baef31bb3.jpg);
複製代碼
  1. base64 編碼格式的圖片說明 :
  • 精靈圖 : 將一些小圖片合併爲一張圖片,減小請求次數,提升性能
  • 字體圖標 :直接將一些小的圖片,合併到字體文件中,而且不會失真
  • base64 : 是一種編碼格式,可以將圖片、文字等常見的文件,轉化爲 base64 格式,這種字符串格式, 瀏覽器可以識別而且讀取顯示到頁面中;
  • base64 是一個字符串,也能夠直接被內嵌到頁面中, 或者 css 中
  • 注意 : 大圖片不適合用 base64 處理, 只有小的圖標才適合 base64 處理
  1. 設置配置
方式1 :{ test : /\.(jpg|png)$/, use : ['url-loader?limit=57417'] }, 
方式2 : 
{
        test: /\.(jpg|png)$/, use: [
          {
            loader: 'url-loader',
            options: {
              // 比57417這個小 => 轉化爲base64
              // 大於等於這個57417值 => 不會轉base64 內部調用 file-loader 加載圖片
              limit: 57417
            }
          }
        ]
      },
複製代碼

4: 處理 字體 文件

  1. 準備字體圖標: 字體圖標文件 iconfont 或者 從阿里矢量圖標裏下載

  2. 拷貝到項目中的 css 文件夾中

  3. main.js 中引入 css 文件

    import '../css/iconfont/iconfont.css'
    複製代碼
  4. 使用 :

  5. 在 webpack.config.js 中配置

// 4. 處理字體圖標
  { test:/\.(svg|woff|woff2|ttf|eot)$/,use:'url-loader'}
複製代碼

5:處理 ES6 語法

  1. 如今的項目都是使用 ES6 開發的, 可是這些新的 ES6 語法, 並非全部的瀏覽器都支持, 因此就須要有一個工具,幫咱們轉成 es5 語法, 這個就是: babel
  2. babel
  3. Babel is a JavaScript compiler. ==> babel 是一個 JavaScript 編譯器
  4. webpack 只能處理 import / export 這個 es6 模塊化語法 而其餘的 js 新語法,應該使用 babel 來處理
  5. 好比 : var o = { ...obj } 在谷歌上能夠,edge 就不能夠
  6. babel 的使用 :
  • 6.1 安裝 1 : npm i -D babel-core babel-loader@7
    • babel-core 是 babel 的核心包
    • babel-loader 加載 js 文件, 並將 js 代碼內容交給 babel-core 解析爲 es5 低版本的 js
  • 6.2 安裝 2 : npm i -D babel-preset-env babel-preset-stage-2
    • babel-preset-* 表示可以解析什麼版本的 js 語法
    • babel-preset-env : 表示可以解析 es2015,es2016,es2017,es2018 這些標準的語法
    • babel-preset-stage-2 : 用來解析通過會遇到,可是尚未被採納爲標準的語法
    • 好比 : 'abc'.padStart(10, '6') : 準備 10 位字符,有 abc,前面不夠用 6 補充,是 es2017 的語法,
    • babel-polyfill與babel-plugin-transform-runtime 也是作兼容處理的,之前都是用這個,兼容更早的
  • 6.3 配置 : 在 webpack.config.js 中添加一個 loader
{ test: /\.js$/, use: 'babel-loader', exclude: /node_modules/ }
複製代碼
  • 6.4 在項目根目錄中建立 babel 的配置文件,叫:.babelrc
{
  "presets": [
    "env",
    "stage-2"
  ],

  -----------
  // 暫時不用
  // 若是將來某一天真的用到了polify
    "plugins": [
        ["transform-runtime", {
                "helpers": false,
                "polyfill": true,
                "regenerator": true,
                "moduleName": "babel-runtime"
    }]
複製代碼
  • 6.5 測試 : 谷歌 和 edge
var obj = {
  name: 'zs',
  age: 20
}

var o = { ...obj }
console.log(o)
複製代碼

webpack中文連接

項目準備

一 : vue 是 單文件組件

直接註冊組件的缺點

  • 語法不會高亮
  • 格式很差
  • 沒有專門寫css樣式的地方

單文件組件

  1. 什麼是單文件組件 ?=> 後綴爲 .vue 的文件
  2. 單文件組件的三個組成部分 (代碼塊 : scaffold 自動提示)
  • template (模板結構)
  • script 組件的代碼邏輯
  • style 樣式
  1. 注意點 :
    • 單文件組件,沒法直接在瀏覽器中使用,必須通過 webpack 這種打包工具,處理後,才能在瀏覽器中使用

二 : 腳手架 介紹

腳手架 2.X ==> 2.Xvue

腳手架 3.X ==> 3.X vue

  1. vue-cli 是 vue 的腳手架工具

  2. 做用 : vue-cli 提供了一條命令, 咱們直接經過這條命令就能夠快速的生成一個 vue 項目 (vue init XX) 。 項目的基本結構、以及 webpack 配置項 所有配置 好了

  3. 爲何會有腳手架工具 ???

    由於 webpack 配置繁瑣, 阻止一批想用 vue 可是不會 webpack 的開發人員,因此做者直接將全部 vue 項目中用到的配置所有幫你寫好了,這樣,就不須要開發人員再去配置基礎 webpack 配置項了,使用 vue-cli 這個腳手架工具後,再也不用擔憂 webpack 配置問題了, 咱們前端只須要寫 vue 代碼, 來實現功能便可

三 : 腳手架工具使用

  • 安裝 : npm i -g vue-cli
  • 初始化 vue 項目 : vue init webpack 項目名稱
    • 好比 : vue init webpack vue-demo01
  • 項目安裝過程 :
? Project name # 回車
? Project description # 回車
? Author  # 回車
? Vue build standalone  # => 運行時+編譯 => 詳見下面的問題1 
? Install vue-router? # Yes
? Use ESLint to lint your code? # Yes => 詳見下面的問題2
? Pick an ESLint preset Standard  # standard
? Set up unit tests # No
? Setup e2e tests with Nightwatch? # No
? Should we run `npm install` for you after the project has been created? # (recommended) npm
複製代碼
  • 如何開始
To get started:
cd vue-demo01
npm run dev
複製代碼
  • "dev": "webpack-dev-server --inline --progress --config build/webpack.dev.conf.js",
    • --inline 意思是信息顯示在哪裏
    • -progress 進度條
    • 指定哪一個文件做爲 webpack 的配置文件 開發的

四 : 文件項目介紹

第一遍:文件夾, 第二遍再細化文件

# build - webpack 相關配置

- build.js - 生產環境構建代碼
- check-version.js 檢查 node、npm 等版本
- util.js 構建工具相關
- vue-loader.config.js vue-loader 的配置文件
- webpack.base.conf.js - webpack 的基礎配置
- webpack.dev.conf.js - webpack 開發環境配置
- webpack.prod.conf.js - webpack 發佈環境配置

# config - vue 基本配置文件(好比:監聽端口(17), 使用 eslint:(26))

- dev.env.js - 開發環境變量
- index.js 項目的一些配置
- prod.env.js 生成環境變量

# node_modules - node 安裝的依賴包

# src - 資源文件夾, 之後咱們就在這個目錄下寫代碼

- assets - 靜態資源 (圖片 css 都放在這)
- components - 公用組件
- router - 路由
- App.vue - 項目的根組件
- main.js - 項目的入口文件(總邏輯)

# static - 靜態資源 (圖片 json 數據之類的)

- .gitkeep git 保持文件,由於 git 上傳,會忽略空文件夾

# .babelrc - babel 配置文件, (es6 語法編譯配置,將 es6 轉化爲瀏覽器可以識別的代碼)

# .editorconfig - 定義代碼格式

- charset = utf-8 編碼 utf8
- indent_style = space 縮進 空格
- indent_size = 2 縮進字符
- end_of_line = lf 回車做爲換行的標記
- insert_final_newline = true 最近一空白行做爲結尾
- trim_trailing_whitespace = true 清除最開始的空白
- 若是使用 ?
- 1. 安裝 vscode 的 editorConfig for vscode
- 2. eslint 檢測修復後

# .eslintignore - eslint 檢測忽略的地方

- /build/
- /config/
- /dist/
- /\*.js 根目錄下帶.js 的

# .eslintrc.js - eslint 的配置文件

# .gitignore - git 的忽略文件

# .postcssrc.js - css 配置文件 (啥也沒有處理)

# index.html - 頁面入口

# package.json - 項目配置文件

複製代碼

4.1 參考 : standard

4.2 參考 : src

  • assets 靜態資源

  • components 組件

  • App.vue 根組件 => 指定路由出口

    • 腳手架以後,全部的組件都將渲染到 app.vue 中
  • app 中的 #app 仍是 index.html 中的 #app, app.vue 中的會覆蓋前者 能夠經過分別添加 title 屬性驗證一下

  • 路由出口要寫在 app.vue 組件模板中

  • main.js

    • 入口 js 文件
    • 做用 : 建立 vue 實例,導入其餘組件並掛在到 vue 實例上
    • Vue.config.productionTip = false 不要打印提示
    • 檢測 no new : 見後面的檢測警告
    new Vue({
      el: '#app', // 目標顯示
      router,   // 掛載路由
      components: { App }, // 註冊組件 App
      template: '<App/>' // 模板顯示組件 app
    })
    複製代碼
  • route/index.js => 路由

  • 必定要記住 :Vue.use(Router) 模塊化公工程中必定要安裝路由插件 .js 就是一個模塊

  • 官網裏 也提到 https://router.vuejs.org/zh/installation.html

五 : 問題處理

5.1 - 問題1 : 兩種編譯模式 和 @

參考 : vue.js => 安裝 => 對不一樣構建本版本的解釋

  • 咱們選擇的是 Runtime + Compiler 模式 : ( 運行時 + 編輯器)
  • 運行時模式 : 用來建立 Vue 實例、渲染並處理虛擬 DOM 等的代碼。基本上就是除去編譯器的其它一切。
  • 編譯器:用來將模板字符串編譯成爲 JavaScript 渲染函數的代碼。
// 須要編譯器
new Vue({
  template: '<div>{{ hi }}</div>'
})

// 不須要編譯器
new Vue({
  render (h) {
    return h('div', this.hi)
  }
})
複製代碼
  • 完整版版本選用 : ES Module (基於構建工具使用) : vue.esm.js
    • build => webpack.base.config.js => 37 行 alias(別名) 'vue$': 'vue/dist/vue.esm.js',
  • @ : 就是src的絕對路徑
    • build => webpack.base.config.js => 38 行 alias(別名) '@': resolve('src'),
router/index.js =>
	import HelloWorld from '@/components/HelloWorld'
	import HelloWorld from 'C:/users/.../src/components/HelloWorld'
複製代碼

5.2 - 問題2 : ESLint

  • 概念 : ESLint 是在 JavaScript 代碼中識別和報告模式匹配的工具,它的目標是保證代碼的一致性和避免錯誤。

    • 在 vscode等編輯工具 中, 能夠提示語法錯誤
    • 在許多方面,它和 JSLint、JSHint 類似,除了少數的例外:
  • 如何使用 eslint ?

    • 1-安裝vscode插件 ESlint
    • 2-vscode設置裏添加一些配置
    "editor.formatOnSave": true, //#每次保存的時候自動格式化
      "eslint.autoFixOnSave": true, // #每次保存的時候將代碼按eslint格式進行修復
      "eslint.validate": [
        { "language": "html", "autoFix": true },
        { "language": "vue", "autoFix": true },
        { "language": "javascript", "autoFix": true },
        { "language": "wpy", "autoFix": true }
      ],
      "prettier.eslintIntegration": true, // #讓prettier使用eslint的代碼格式進行校驗
      "javascript.format.insertSpaceBeforeFunctionParenthesis": true,
      "editor.formatOnType": true //#讓函數(名)和後面的括號之間加個空格
    複製代碼
  • 關閉 Eslint :

    • 參考 : config/index.js ==> 26行 : dev.useEslint 設置爲false
    • 重啓項目: npm run dev
    • 測試 : 刪除 main.js 中的 /* eslint-disable no-new */ 關閉後 會報波浪線,可是不會報錯了

5.3 問題3 : vscode安裝 格式化插件 Prettier

  • 安裝 vscode 插件 Prettier
  • 功能1 : shift + alt + F => 格式化代碼
  • 功能2 : 配合 eslint : 見上一個問題的配置

5.4 問題4 : 檢測警告

eslint-disable-next-line # 忽略檢測下一行  可使用單行註釋/多行註釋,其餘都是多行註釋
eslint-disable # 忽略當前整個文件

eslint-disable no-new # 忽略前面是new開頭
複製代碼

六 : 項目演示

準備 :開啓服務器+數據庫

vue 項目學什麼?

  1. 如何使用 vue 配合腳手架工具來完成一個項目
  2. 學習 ElementUI 組件庫的使用
  3. 業務
  • 3.1 登陸和退出
  • 3.2 用戶+角色+受權+菜單
  • 3.3 商品模塊

七 : 開啓本地服務器

畫圖 : 接口訪問路徑 : 前端頁面 ===> 接口服務器 ===> 數據庫服務器 ==> 數據庫

第一小步 : 打開 : 數據庫服務器

打開 phpStudy ,點擊啓動

第二小步 : 導入數據庫

  1. 打開 navicat

  2. 點擊鏈接 : 建立一個MySQL鏈接

  3. 用戶名和密碼 : root-root(不能亂寫) 這個是和 config 裏的配置同樣的

  4. 建立一個數據庫 : shop_admin 不要亂寫, 選擇倒數找到 unt-8

  5. 雙擊打開數據庫

  6. 導入 sql語句 => 右鍵運行 SQL 文件 => shop-api 最後一個 sql 文件

    若是沒有反應 : 表 => 右鍵刷新

第三小步 : 開啓接口服務器

  1. 打開 shop-api
  2. 運行 npm start
  3. 顯示成功 : API 接口服務啓動成功,佔用端口 8888

第四小步 : 測試接口

http://localhost:8888/api/private/v1/login?username=admin&password=123456

項目使用接口 : (記得保存)
// shop-api裏面有
複製代碼

第五小步 : 使用

  • 天天作項目以前 :
    1. 每次都要先開啓 phpStudy 中的 mySql
    1. 每次都要打開shop-api , 運行 npm start

八 : ES6的模塊語法 (基於webpack基類演示)

8.1 : export default 默認導出一個模塊 ( 簡單類型 + 複雜類型 )
  • 導出 : export default

  • 默認 只能導出一個

    let str = 'abc'
    let num = 20;
    let obj = { name :'zs' }
    
    export default num
    // export default obj
    複製代碼
  • 導入 : import

  • 導入的名字能夠任意

  • import res from './a.js'
    console.log(res)
    複製代碼

8.2 export 導出多個模塊, 都放在一個對象裏

  • **導出 : export **

  • // 邏輯模塊 
    // 登陸一個函數
    export let login = () =>  {
      console.log('登陸');
    }
    // 註冊一個函數
    export let register = () =>  {
      console.log('註冊');
    }
    複製代碼
  • 導入 : import

  • // 方式1
    import * as res from './a'
    console.log(res);
    res.login()
    res.register()
    // 方式2
    import { login, register as reg } from './a'
    login()
    register()
    複製代碼

8.3 import 模塊

import axios from 'axios';
複製代碼

項目相關思路

一 : 初始化項目

vue init webpack shop_admin_35 清除不要的東西 (logo 和 hello world 組件 )

二 : 手動配置路由

安裝 : npm i vue-router 建立一個router文件夾 / router.js 實例化路由 導出路由模塊 , main.js 引入 ,掛載到vue實例上

/**

  • 準備工做

    1. 安裝 npm i vue-router
    1. 引入 import VueRouter from 'vue-router'
    1. 注意點 : vue-router 和 vuex 在模塊化(把他們單獨提到一個js文件裏)工程中,須要使用 Vue.use(安裝一下)
    1. 實例化 + 掛載 (導出去再掛載)
  • 四個步驟

    1. 先把須要的組件建立出來 Login.vue Home.vue
    1. 走流程
    1. 入口 (url測試)
    1. 匹配規則
    1. 組件 (引入)
    1. 出口 */

三 : 建立兩個子組件而且配置路由

1.先建立組件 /login/Login.vue 2.走流程

  1. 入口 : url手動寫
  2. 規則 : {path :'/login', component: Login}
  3. 組件 : 引入便可
  4. 出口 : 在 app.vue 根組件 裏 寫一個出口

四 : Element-ui

連接 : element-cn.eleme.io/#/zh-CN/com… 概念 : element 是一個(基於 vue 2.X )組件庫 安裝 : npm i element-ui ( -S == --save == 不寫 ) (-D 開發階段須要 發佈階段不須要) 快速上手 :引入(main.js)

// 引入 element
import ElementUI from 'element-ui';
import 'element-ui/lib/theme-chalk/index.css';

// 安裝一下 element-ui
Vue.use(ElementUI);
複製代碼

測試 : 找到官網裏的組件,拿到一個 按鈕 注意點 :template 裏面只能由一個根元素 one root element

五 > Login 頁面 表單

el-form el-form-item

六. 發送請求 登陸

  1. 接口 (本地服務器, 接口文檔 )
  2. 請求工具 : axios

安裝 axios 引入 使用

七 : 跳轉

聲明式導航 ==> 組件 標籤 編程式導航 this.$router.push('/home') ==> 事件裏

八 : route 和router

router : 路由實例  編程式導航(跳轉)  登陸攔截(導航守衛)route : 路由對象 , 包含url的信息對象, (path query, params) 解析 地址 #後面的信息

九 : 處理表單居中

注意1 : num='8' ==> 把字符串8 賦值給了num :num='8' ==> : 把 8 原來的類型賦值給num 注意2 : 若是想讓label和input在一行 => 設置 label-width='100px' => el-form 若是想讓 label 和 input 不在一行 =>不要設置 label-width

相關文章
相關標籤/搜索