vue全部筆記

什么是Vue.js

  • Vue.js是目前最火的一個(gè)前端框架,React是最流行的一個(gè)前端框架,(React除了開(kāi)發(fā)網(wǎng)站,還可以開(kāi)發(fā)手機(jī)App,Vue語(yǔ)法也是可以用于手機(jī)App開(kāi)發(fā)的,需要借助于Weex)
  • Vue.js是前端的主流框架之一,和Angualr.js、React.js一起,并稱為前端三大主流框架
  • Vue.js是一套構(gòu)建用戶界面的框架,**只關(guān)注視圖層++,它不僅易上手,還便于與第三方庫(kù)或既有項(xiàng)目整合。(Vue有配套的第三方類庫(kù),可以整合起來(lái)做大型項(xiàng)目的開(kāi)發(fā))
  • 前端的主要工作?主要負(fù)責(zé)MVC中的V這一層,蛀牙工作就是和界面打交道。

為什么學(xué)習(xí)流行框架

  • 企業(yè)為了提高開(kāi)發(fā)效率,在企業(yè)中,時(shí)間就是效率,效率就是金錢。
  • 提高開(kāi)發(fā)效率的發(fā)展歷程:原生JS -> Jquery之類的類庫(kù) -> 前端模板引擎 -> Angular.js / Vue.js(能夠幫助我們減少不必要的DOM操作;提高渲染效率;雙向數(shù)據(jù)綁定的概念【通過(guò)跨年提供的指令,前端程序員只需要關(guān)心數(shù)據(jù)的業(yè)務(wù)邏輯,不在關(guān)心DOM是如何渲染的】)
  • 在Vue中,一個(gè)核心的概念,就是讓用戶不再操作DOM元素,解放了用戶的雙手,讓程序員可以更多的時(shí)候去關(guān)注業(yè)務(wù)邏輯。
  • 增強(qiáng)就業(yè)競(jìng)爭(zhēng)力

框架和庫(kù)的區(qū)別

  • 框架:是一套完整的解決方案:對(duì)項(xiàng)目的侵入性較大,項(xiàng)目如果需要更換框架,則需要重新架構(gòu)整個(gè)項(xiàng)目
  • 庫(kù)(插件):提供某一個(gè)小功能,對(duì)項(xiàng)目的侵入性較小。如果某個(gè)庫(kù)無(wú)法完成某些需求,可以很容易切換到其他庫(kù)實(shí)現(xiàn)需求。

Node(后端)中的MVC與前端中的MVVM之間的區(qū)別

  • MVC是后端的分層開(kāi)發(fā)概念。M指Model,主要處理數(shù)據(jù);V是視圖層,(前端頁(yè)面);C是業(yè)務(wù)邏輯層(路由、用戶登錄注銷)

  • MVVM是前端視圖層的概念,主要關(guān)注于視圖層分離。也就是說(shuō):MVVM把前端的視圖層,分為了三部分Model,View,VM ViewModel

  • 為什么有了MVC還要有MVVM

Vue.js基本代碼和MVVM之間的對(duì)應(yīng)關(guān)系

Vue之 基本代碼結(jié)構(gòu)插值表達(dá)式、v-cloak

Vue指令之v-texv-html

Vue指令之v-bind的三種用法

  1. 直接使用 指令v-bind
  2. 使用簡(jiǎn)化指令:
  3. 在綁定的時(shí)候,拼接綁定內(nèi)容::title="btnTitle + ',這是追加的內(nèi)容'"

Vue指令之v-on跑馬燈效果

跑馬燈效果

  1. HTML結(jié)構(gòu):

     <div id="app">
         <input type="button" value="快樂(lè)" @click="run">
         <input type="button" value="我不" @click="stop">
         <h4>{{ msg }}</h4>
     </div>
    

2.Vue實(shí)例

    //在vm實(shí)例中,如果要獲取data里的數(shù)據(jù)或調(diào)用methods中的方法,
    //必須通過(guò) this.數(shù)據(jù)屬性名 或 this.方法名來(lái)進(jìn)行訪問(wèn),this代表vm實(shí)例對(duì)象
    var vm = new Vue({
        el: '#app',
        data: {
            msg: '快樂(lè)的一只小青蛙~',
            intervalId: null //在data上定義定時(shí)器的Id,開(kāi)一個(gè)定時(shí)器就重新定義一遍
        },
        methods: {
            run() {
                
                // 判斷定時(shí)器是否為null,是否在靜止?fàn)顟B(tài)點(diǎn)擊的“快樂(lè)”按鈕,不是則返回,是則執(zhí)行下列代碼
                if(this.intervalId != null) return;

                //es6語(yǔ)法,不需要先獲取this再重新賦值
                //嵌套函數(shù)內(nèi)部的this與外部的this保持一致
                this.intervalId = setInterval( () => {
                    // 獲取頭部的第一個(gè)字符
                    var start = this.msg.substring(0,1)
                    // 獲取到后面的所有字符
                    var end = this.msg.substring(1)
                    // 重新拼接得到新的字符串,并賦值給 this.msg
                    this.msg = end + start

                    //vm實(shí)例會(huì)監(jiān)聽(tīng)自己內(nèi)部data中所有數(shù)據(jù)的改變,只要數(shù)據(jù)已發(fā)生編發(fā),就會(huì)自動(dòng)把最新的數(shù)據(jù),
                    //從data上同步到頁(yè)面中去,因此程序員只要關(guān)心數(shù)據(jù)的變化,不需要關(guān)心重新渲染
                }, 400)
                
            },
            stop() {
                clearInterval(this.intervalId)
                // 每當(dāng)清除了定時(shí)器之后,需要把定時(shí)器重新賦值給null
                this.intervalId = null
            }
        }
    })

    //分析
    //1. 給“快樂(lè)”按鈕,綁定一個(gè)點(diǎn)擊事件
    //2. 在按鈕的事件處理函數(shù)中,寫(xiě)相關(guān)的業(yè)務(wù)邏輯:拿到msg字符串,然后低哦用字符串的
    //substring來(lái)進(jìn)行字符串的截取操作,把第一個(gè)字符截取出來(lái)放到最后一個(gè)位置即可
    //3. 為了實(shí)現(xiàn)點(diǎn)擊下按鈕,自動(dòng)截取的功能,需要把步驟2中國(guó)的代碼,放到一個(gè)定時(shí)器中去。

Vue指令之v-on的縮寫(xiě)和事件修飾符

事件修飾符:

  • .stop 阻止冒泡
  • .prevent 阻止默認(rèn)事件
  • .capture 添加事件偵聽(tīng)器時(shí)使用事件捕獲模式
  • .self 只當(dāng)事件在該元素本身(比如不是子元素)觸發(fā)時(shí)觸發(fā)回調(diào)
  • .once事件只觸發(fā)一次

Vue指令之v-model雙向數(shù)據(jù)綁定

簡(jiǎn)易計(jì)算器案例

  1. HTML代碼結(jié)構(gòu)
    <div id="app">
        <input type="text" v-model="n1">

        <select v-model="opt">
            <option value="+">+</option>
            <option value="-">-</option>
            <option value="*">*</option>
            <option value="/">/</option>
        </select>

        <input type="text" v-model="n2">

        <input type="button" value="=" @click="calc">

        <input type="text" v-model="result">
        
    </div>
  1. vue實(shí)例

         var vm = new Vue({
         el: "#app",
         data: {
             n1: 0,
             n2: 0,
             result: 0,
             opt: '+'
         },
         methods: {
             calc () {
                 //1.算數(shù)方法
                 // switch(this.opt){
                 //     case '+':
                 //         this.result = parseInt(this.n1) + parseInt(this.n2)
                 //         break;
                 //     case '-':
                 //         this.result = parseInt(this.n1) - parseInt(this.n2)
                 //         break;
                 //     case '*':
                 //         this.result = parseInt(this.n1) * parseInt(this.n2)
                 //         break;
                 //     case '/':
                 //      this.result = parseInt(this.n1) / parseInt(this.n2)
                 //         break;
                 // }
                 
                 //2.投機(jī)取巧,正式開(kāi)發(fā)中,盡量少用
                 var codeStr = 'parseInt(this.n1)' + this.opt + 'parseInt(this.n2)'
                 this.result = eval(codeStr)
             }
         }
     });
    

在Vue中 使用樣式

使用class樣式

1.數(shù)組

<h1 :class="['red','thin']">這是一個(gè)熟悉的H1</h1>

2.數(shù)組中使用三元表達(dá)式

<h1 :class="['red','thin',isactive?'active':'']">這是一個(gè)熟悉的H1</h1>

3.數(shù)組中嵌套對(duì)象

<h1 :class="['red','thin',{'active':isactive}]>這是一個(gè)熟悉的H1</h1>

4.直接使用對(duì)象

<h1 :class="{red:true, italic:true, active:true, thin:true}">這是一個(gè)熟悉的H1</h1>

使用內(nèi)聯(lián)樣式

1.直接在元素上通過(guò) :style的形式,書(shū)寫(xiě)樣式對(duì)象

<h1 :style="{color:'red', 'font-size': '40px'}">這是一個(gè)熟悉的H1</h1>

2.將樣式對(duì)象,定義到data中,并直接引用到:style

  • 在data上定義樣式:
data: {
   h1StyleObj: {color: 'red', 'font-size': '40px', 'font-weight': '200'}
}
  • 在元素中,通過(guò)屬性綁定的形式,將樣式對(duì)象引用到元素中
<h1: style="h1StyleObj">這是一個(gè)熟悉的H1</h1>

3.在:style中通過(guò)數(shù)組,引用多個(gè)data上的樣式對(duì)象

  • 在data上定義樣式:
data: {
   h1StyleObj1: { color: 'red', 'font-size': '40px', 'font-wight': '200'},
   h1StyleObj2: { fontStyle: 'italic' }
}
  • 在元素中,通過(guò)屬性綁定的形式,將楊思對(duì)象應(yīng)用到元素中:
<h1 :style="{h1StyleObj,h2StyleObj2}">這是一個(gè)熟悉的H1</h1>

Vue指令之v-forkey屬性

1.迭代數(shù)組

    <ul>
        <li v-for="{item,i} in list">索引:{{i}} --- 姓名:{{item.name}} --- 年齡:{{item.age}}</li>
    </ul>

2.迭代對(duì)象中的屬性

    <!-- 循環(huán)遍歷對(duì)象身上的屬性 -->
    <div v-for="{val,key,i} in userInfo>{{val}} --- {{key}} --- {{i}}</div>

3.迭代數(shù)字

    <p v-for="i in 10">這是第 {{i}} 個(gè)p標(biāo)簽</p>

2.2.0+版本里,當(dāng)在組件中使用 v-for 時(shí),key現(xiàn)在是必須的。

當(dāng) Vue.js 用 v-for 正在更新已渲染過(guò)的元素列表時(shí),它默認(rèn)用 “就地復(fù)用”策略。如果數(shù)據(jù)項(xiàng)的順序被改變,Vue將不是移動(dòng)DOM元素來(lái)匹配數(shù)據(jù)項(xiàng)的順序,而是簡(jiǎn)單復(fù)用此處每個(gè)元素,并且確保它在特定索引下顯示已被渲染過(guò)的每個(gè)元素。

為了給Vue 一個(gè)提示,以便它能跟蹤每個(gè)節(jié)點(diǎn)的身份,從而復(fù)用和重新排序現(xiàn)有元素,你需要為每項(xiàng)提供一個(gè)唯一 key 屬性。

Vue指令之v-ifv-show

一般來(lái)說(shuō),v-if有更高的切換消耗而v-show有更高的初始渲染消耗,因此,如果需要頻繁切換v-show較好,如果在運(yùn)行時(shí)條件不大可能改變v-if較好

Vue.js-Day2

品牌管理案例

添加新品牌

刪除品牌

根據(jù)條件篩選品牌

  1. 1.x版本中的filterBy指令,在2.x中已經(jīng)被廢除:

[filterBy - 指令]

<tr v-for="item in list:filterBy searchName in "name">

    <td>{{item.id}}</td>

    <td>{{item.name}}</td>

    <td>{{item.ctime))</td>

    <td>

        <a href="#" @click.prevent="del{item.id}">刪除</a>

    </td>

</tr>
  1. 在2.x版本中:

Vue調(diào)試工具vue-devtools的安裝步驟和使用

https://chrome.google.com/webstore/search/devtools?hl=zh-CN

過(guò)濾器

概念:Vue.js允許自定義過(guò)濾器,可被用作一些常見(jiàn)的文本格式化。過(guò)濾器可以用在兩個(gè)地方:sustache 插值和 v-bind 表達(dá)式。過(guò)濾器應(yīng)該被添加在JavaScript表達(dá)式的尾部,由“管道”符指示;

私有過(guò)濾器

  1. HTML元素
    <td>{{item.ctime | dataforms('yyyy-mmm-dd')}}</td>
  1. 私有filters定義方式:

     //定義一個(gè)私有的過(guò)濾器
     var vm2 = new Vue({
         el: '#app2',
         data: { 
             dt: new Date()
         },
         methods: { },
         //帶 s ,對(duì)象, 定義私有過(guò)濾器, 過(guò)濾器有兩個(gè)條件: [過(guò)濾器名稱 和 處理函數(shù)]
         //過(guò)濾器調(diào)用的時(shí)候,采用的是就近原則,如果私有過(guò)濾器和全局過(guò)濾器的名稱一樣,則優(yōu)先調(diào)用私有的
         filters: { 
             dataFormat: function(dateStr, pattern = '') {
         //根據(jù)給定的時(shí)間字符串,得到特定的時(shí)間
         var dt = new Date(dateStr)
    
         // yyyy - mm - dd
         var y = dt.getFullYear()
         //padStart(maxLength, fillString='')字符填充方法,最大長(zhǎng)度為2,不夠則在前面填充0
         //padEnd(maxLength, fillString='')同理,不同的是在后面添加
         var m = (dt.getMonth() + 1 ).toString().padStart(2,'0')
         var d = dt.getDate().toString().padStart(2,'0')
    
         //先轉(zhuǎn)成小寫(xiě)
         if(pattern.toLowerCase() === 'yyyy-mm-dd') {
             return `${y}-${m}-$u0z1t8os`
         }else {
             var hh = dt.getHours().toString().padStart(2,'0')
             var mm = dt.getMinutes().toString().padStart(2,'0')
             var ss = dt.getSeconds().toString().padStart(2,'0')
    
             return `${y}-${m}-$u0z1t8os ${hh}:${mm}:${ss}~~~~`
         }
     }
         }
     })
    

使用ES6中的字符串新方法 String.prototype.padStart(maxLength, fillString='') 或 String.prototype.padEnd(maxLength, fillSting='')來(lái)填充字符串;

全局過(guò)濾器

    //定義一個(gè)全局的過(guò)濾器, 進(jìn)行時(shí)間格式化,被所有的vm實(shí)例共用
    Vue.filter('dataFormat',function (dateStr, pattern="") {
        //根據(jù)給定的時(shí)間字符串,得到特定的時(shí)間
        var dt = new Date(dateStr)

        // yyyy - mm - dd, 獲取年月日
        var y = dt.getFullYear()
        var m = dt.getMonth() + 1 
        var d = dt.getDate()

        // return y + '-' + m +'-' +d //用以下形式代替:
        //return `${y}-${m}-$u0z1t8os`

        //先轉(zhuǎn)成小寫(xiě)
        //如果 傳遞進(jìn)來(lái)的字符串類型 ,轉(zhuǎn)為小寫(xiě)后,等于yyyy-mm-dd,那么就返回 年-月-日
        //否則,就返回 年-月-日 時(shí):分:秒
        if(pattern.toLowerCase() === 'yyyy-mm-dd') {
            return `${y}-${m}-$u0z1t8os`
        }else {
            //獲取時(shí)分秒
            var hh = dt.getHours()
            var mm = dt.getMinutes()
            var ss = dt.getSeconds()

            return `${y}-${m}-$u0z1t8os ${hh}:${mm}:${ss}`
        }
    })

注意:當(dāng)有局部和全局兩個(gè)名稱相同的過(guò)濾器的時(shí)候,會(huì)以就近原則進(jìn)行調(diào)用,即:局部過(guò)濾器優(yōu)先于全局過(guò)濾器被調(diào)用!

鍵盤(pán)修飾符以及自定義鍵盤(pán)修飾符

1. 1.x中自定義鍵盤(pán)修飾符【了解即可】

Vue.directive('on').keyCodes.f2 = 113;

2.x自定義鍵盤(pán)修飾符 https://cn.vuejs.org/v2/guide/events.html#%E6%8C%89%E9%94%AE%E7%A0%81

1.1 通過(guò)Vue.config.keyCodes.名稱 = 按鍵值來(lái)自定義按鍵修飾符的別名:

`Vue.config.keyCodes.f2 = 113;`

1.2 使用自定義的按鍵修飾符

`<input type="text" v-model="name" @keyup.f2="add">`

2.可以直接調(diào)用按鍵值(f2的按鍵值為113)

`<input type="text" v-model="name" @keyup.113="add">`

3.使用系統(tǒng)內(nèi)置的按鍵可以不用定義

`<input type="text" v-model="name" @keyup.enter="add">`

自定義指令 https://cn.vuejs.org/v2/guide/custom-directive.html

  1. 自定義全局和局部的 自定義指令:

全局

    // 注冊(cè)一個(gè)全局自定義指令 `v-focus`
    Vue.directive('focus', {
    // 當(dāng)被綁定的元素插入到 DOM 中時(shí)……
    inserted: function (el) {
    // 聚焦元素
    el.focus()
    }
    })

局部

    directives: {
        focus: {
        // 指令的定義
        inserted: function (el) {
         el.focus()
        }
        }
    }
  1. 鉤子函數(shù)

https://cn.vuejs.org/v2/guide/custom-directive.html#%E9%92%A9%E5%AD%90%E5%87%BD%E6%95%B0

    // 使用 Vue.derective() 自定義全局指令
    // 其中:參數(shù)1:指令的名稱,注意,在定義的時(shí)候,指令的名稱前面,不需要加 v- 前綴,
    // 但是: 在調(diào)用的時(shí)候,必須在指令名稱前加上 v- 前綴來(lái)進(jìn)行調(diào)用
    //參數(shù)2:是一個(gè)對(duì)象,這個(gè)對(duì)象身上,有一些指令相關(guān)的函數(shù),這些函數(shù)可以在特定的階段,執(zhí)行相關(guān)的操作
    Vue.directive('focus',{
        bind:function(el) {//每當(dāng)指令綁定到元素上的時(shí)候,就立即執(zhí)行 bind 函數(shù),只執(zhí)行一次
            /// 注意: 在每個(gè)函數(shù)中,第一個(gè)參數(shù)永遠(yuǎn)是 el ,表示被綁定了指令的元素,這個(gè) el 參數(shù),是一個(gè)原生的JS對(duì)象
            // 在元素剛綁定了指令的時(shí)候,還沒(méi)有插入到 DOM 中去,這時(shí)候,調(diào)用 focus 方法沒(méi)有作用
            // 因?yàn)?,一個(gè)元素,只有插入DOM之后,才能獲取焦點(diǎn)
            //el.focus()
        },
        inserted: function(el) {// inserted 表示元素插入到 DOM 中的時(shí)候,會(huì)執(zhí)行  inserted 函數(shù),只執(zhí)行一次
            el.focus()
            // 和 JS 行為有關(guān)的操作,最好在 inserted 中去執(zhí)行,防止 JS 行為不生效
        },
        updated: function() {// 當(dāng) VNode 更新的時(shí)候,會(huì)執(zhí)行 updated 函數(shù),可能被觸發(fā)多次

        }
    })
  1. 鉤子函數(shù)的參數(shù)

https://cn.vuejs.org/v2/guide/custom-directive.html#%E9%92%A9%E5%AD%90%E5%87%BD%E6%95%B0%E5%8F%82%E6%95%B0

  • el:指令所綁定的元素
  • binding
  • name:指令的名字,不包含v-前綴
  • value:指令的綁定值:例如:v-my-directive="1 + 1" 中,綁定值為 2
  • expression:字符串形式的表達(dá)式,例如 v-my-directive="1 + 1" 中,表達(dá)式為 "1 + 1"。

html:

<input type="text" class="form-control" v-model="keywords" id="search" v-focus v-color="'blue'">

自定義指令:

    //自定義設(shè)置字體顏色的指令
    Vue.directive('color',{
        // 樣式只要通過(guò)指令綁定給了元素,不管這個(gè)元素有沒(méi)有被插入到頁(yè)面中去,這個(gè)元素肯定有一個(gè)內(nèi)聯(lián)樣式
        // 將來(lái)元素肯定會(huì)顯示到頁(yè)面上,這時(shí)候?yàn)g覽器的渲染引擎必然會(huì)解析樣式,應(yīng)用給這個(gè)元素
        bind:function(el,binding) {
            // el.style.color = 'red'
            // 和 樣式 相關(guān)的操作,一般都可以在 bind 中定義

            el.style.color = binding.value
        }
    })
  1. 簡(jiǎn)寫(xiě)函數(shù):在 bind 和 update 時(shí)觸發(fā)相同行為,而不關(guān)心其它的鉤子函數(shù)

下面的例子是自定義私有指令和簡(jiǎn)寫(xiě)函數(shù)

    directives: { // 自定義私有指令
       'fontweight': { // 設(shè)置字體粗細(xì)
           bind: function (el,binding) {
               el.style.fontWeight = binding.value
           }
        },
        'fontsize': function(el,binding) { //簡(jiǎn)寫(xiě)函數(shù),注意:這個(gè) function 等同于把代碼寫(xiě)到了 bind 和 update 中去
             el.style.fontSize = parseInt(binding.value) + 'px'
        }
    }

Vue實(shí)例的生命周期

生命周期

  • 什么是生命周期:從Vue實(shí)例創(chuàng)建、運(yùn)行、到銷毀期間,總是伴隨著各種各樣的事件,這些事件,統(tǒng)稱為生命周期。
  • 生命周期鉤子:就是生命周期事件的別名而已;
  • 生命周期鉤子 = 生命周期函數(shù) = 生命周期事件
  • 主要的生命周期函數(shù)分類:
  • 創(chuàng)建期間的生命周期函數(shù):
    • beforeCreate:實(shí)例剛在內(nèi)存中被創(chuàng)建出來(lái),此時(shí),還沒(méi)有初始化好 data 和 methods 屬性
    • created: 實(shí)例已經(jīng)在內(nèi)存中創(chuàng)建完成;此時(shí) data 和 methods 已經(jīng)創(chuàng)建完成,此時(shí)還沒(méi)有開(kāi)始編譯模板
    • beforeMount:此時(shí)已經(jīng)完成了模板的編譯,但是還沒(méi)有掛載到頁(yè)面中
    • mounted:此時(shí),已經(jīng)將編譯好的模板,掛載到了頁(yè)面指定的容器中顯示
  • 運(yùn)行期間的生命周期函數(shù):
    • beforeUpdate:狀態(tài)更新之前執(zhí)行此函數(shù),此時(shí) data 中的狀態(tài) 值是最新的,但是界面上顯示的數(shù)據(jù)還是舊的。因?yàn)榇藭r(shí)還沒(méi)有開(kāi)始重新渲染 DOM 節(jié)點(diǎn)
    • updated:實(shí)例更新完畢之后調(diào)用此函數(shù),此時(shí) data 中的狀態(tài)值 和 界面上顯示的數(shù)據(jù),都已經(jīng)完成了更新,界面已經(jīng)被重新渲染好了
  • 銷毀期間的生命周期函數(shù):
    • beforeDestroy:實(shí)例銷毀之前調(diào)用。在這一步,實(shí)例仍然完全可用
    • destroyed:Vue 實(shí)例銷毀后調(diào)用。調(diào)用后,Vue 實(shí)例指示的所有東西都會(huì)解除綁定,所有的事件監(jiān)聽(tīng)器會(huì)被移除,所有的子實(shí)例也會(huì)被銷毀。

vue-resource實(shí)現(xiàn)get,post,jsonp請(qǐng)求

除了 vue-resource 之外,還可以使用 axios的第三方包實(shí)現(xiàn)數(shù)據(jù)的請(qǐng)求

  1. 之前的學(xué)習(xí)中,如何發(fā)起數(shù)據(jù)請(qǐng)求?
  2. 常見(jiàn)的數(shù)據(jù)請(qǐng)求類型?get,post,jsonp
  3. 測(cè)試的URL請(qǐng)求資源地址
  4. JSONP的實(shí)現(xiàn)原理
    • 由于瀏覽器的安全性限制,不允許AJAX訪問(wèn)協(xié)議不同、域名不同、端口號(hào)不同的數(shù)據(jù)接口,瀏覽器認(rèn)為這種訪問(wèn)不安全;
    • 可以通過(guò)動(dòng)態(tài)創(chuàng)建script標(biāo)簽的形式,把script標(biāo)簽的src屬性,指向數(shù)據(jù)接口的地址,因?yàn)閟cript標(biāo)簽不存在跨域限制,這種 數(shù)據(jù)獲取方式,稱作為JSONP(注意:根據(jù)JSON的實(shí)現(xiàn)原理,知曉,JSONP只支持GET請(qǐng)求);
    • 具體實(shí)現(xiàn)過(guò)程;
      • 先在客戶端定義一個(gè)回調(diào)方法,預(yù)定義對(duì)數(shù)據(jù)的操作;
      • 再把這個(gè)回調(diào)方法的名稱,通過(guò)URL傳參的形式,提交都服務(wù)器的數(shù)據(jù)接口
      • 服務(wù)器數(shù)據(jù)接口組織好要發(fā)送給 客戶端的數(shù)據(jù),再拿著客戶端傳遞過(guò)來(lái)的回調(diào)方法名稱,拼接出一個(gè)調(diào)用這個(gè)方法的字符串,發(fā)送給客戶端去解析執(zhí)行;
      • 客戶端拿到服務(wù)器返回的字符串之后,當(dāng)作script腳本去解析執(zhí)行,這樣就能夠拿到JSONP的數(shù)據(jù)了;

配置本地?cái)?shù)據(jù)庫(kù)和數(shù)據(jù)接口API

  1. 先解壓安裝PHPStudy
  2. 解壓安裝Navicat這個(gè)數(shù)據(jù)庫(kù)可視化工具,并激活;
  3. 打開(kāi)Navicat工具,新建空白數(shù)據(jù)庫(kù),名為dtcmsdb4
  4. 雙擊新建的數(shù)據(jù)庫(kù),連接上這個(gè)空白數(shù)據(jù)庫(kù),在新建的數(shù)據(jù)庫(kù)上右鍵->運(yùn)行SQL文件,選擇并執(zhí)行dtcmsdb4.sql這個(gè)數(shù)據(jù)庫(kù)腳本文件;如果執(zhí)行不報(bào)錯(cuò),則數(shù)據(jù)庫(kù)導(dǎo)入完成;
  5. 進(jìn)入文件夾vuecms3_nodejsapi內(nèi)部,執(zhí)行npm i安裝所有的依賴項(xiàng);
  6. 先確保本機(jī)安裝 了nodemon,沒(méi)有安裝則運(yùn)行npm i nodemon -g進(jìn)行全局安裝,安裝完畢后,進(jìn)入到vuecms_nodejsapi目錄 ->src目錄 -> 雙擊運(yùn)行 start.bat
  7. 如果API啟動(dòng)失敗,請(qǐng)檢查 PHPStudy 中默認(rèn)的用戶名是 root,默認(rèn)的密碼也是 root

品牌管理改造

展示品牌列表

添加品牌數(shù)據(jù)

刪除品牌數(shù)據(jù)

Vue中的動(dòng)畫(huà)

為什么要有動(dòng)畫(huà):動(dòng)畫(huà)能夠提高用戶的體驗(yàn),幫助用戶更好的理解頁(yè)面中的功能

使用過(guò)渡類名

  1. HTML結(jié)構(gòu)

     <div id="app>
      <input type="button" value="動(dòng)起來(lái)" @click="myAnimate">
      <!-- 使用 transition 將需要過(guò)渡的元素包裹起來(lái) -->
      <transition name="false">
     <div v-show="isshow">動(dòng)畫(huà)</div>
      </transition>
     </div>
    
  2. VM實(shí)例

     // 創(chuàng)建 Vue實(shí)例,得到 ViewModel
     var vm = new Vue({
         el:'#app',
         data:{
             isshow: false
         },
         methods:{
             myAnimate:{
                 this.isshow = !this.isshow;
             }
         }
     }) 
    

Vue.js-Day3

定義Vue組件

什么是組件: 組件的出現(xiàn),就是為了拆分Vue實(shí)例的代碼量的,能夠讓我們以不同的組件,來(lái)劃分不同的功能模塊,將來(lái)我們需要什么樣的功能,就可以去調(diào)用對(duì)應(yīng)的組件即可;

組件化和模塊化的不同:

  • 模塊化:是從代碼邏輯的角度進(jìn)行劃分的;方便后臺(tái)代碼的分層開(kāi)發(fā),保證每一個(gè)功能模塊的職能單一;
  • 組件化:是從UI界面進(jìn)行劃分的;方便UI組件的復(fù)用;

全局組件定義的三種方式

  1. 使用 Vue.extend 配合 Vue.component 方法;

     var login = Vue.extend({
         template: '<h1>登錄</h1>'
         });
     Vue.component('login',login);
    
  2. 直接使用 Vue.component 方法:

     Vue.component('register',{
         template: '<h1>注冊(cè)</h1>'
         });
    
  3. 將模板字符串,定義到script標(biāo)簽中:

     <script id="tmpl" type="x-template">
         <div><a href="#">登錄</a> | <a href="#">注冊(cè)</a></div>
     </script>
    

同時(shí),需要使用 Vue.component 來(lái)定義組件:

    Vue.component('account',{
        template:'#tmpl'
    });

注意:組件中的DOM結(jié)構(gòu),有且只能有唯一的根元素(Root Element)來(lái)進(jìn)行包裹

組件中展示數(shù)據(jù)和響應(yīng)事件

  1. 在組件中 ,data需要被定義為一個(gè)方法。例如:

Vue.js - Day4

父組件向子組件傳值

  1. 組件實(shí)例定義方式,注意:一定要使用props屬性要定義父組件傳遞過(guò)來(lái)的數(shù)據(jù)
    <script>
    // 創(chuàng)建 Vue 實(shí)例,得到 ViewModel
    var vm = new Vue({
        el:'#app',
        data: {
            msg:'這是父組件的消息'
        },
        components: {
            son: {
                template: '<h1>這是子組件 --- {{finfo}}</h1>',
                props: [finfo]
            }
        }
    });
    </script>
  1. 使用v-bind或簡(jiǎn)化指令,將數(shù)據(jù)傳遞到子組件中:

     <div id="app">
         <son :finfo="msg"></son>
     </div>
    

子組件向父組件傳值

  1. 原理:父組件將方法的引用,傳遞到子組件內(nèi)部,子組件在內(nèi)部調(diào)用父組件傳遞過(guò)來(lái)的方法,同時(shí)把要發(fā)送給父組件的數(shù)據(jù),在調(diào)用方法的時(shí)候當(dāng)作參數(shù)傳遞進(jìn)去;
  2. 父組件將方法的引用傳遞給子組件,其中,getMsg是父組件中methods中定義的方法名稱,funo是子組件調(diào)用傳遞過(guò)來(lái)方法時(shí)候的方法名稱
    <son @funo="getMsg"></son>
  1. 子組件內(nèi)部通過(guò)this.$emit(‘方法名',要傳遞的數(shù)據(jù))方式,來(lái)調(diào)用父組件中的方法,同時(shí)把數(shù)據(jù)傳遞給父組件使用
    <div id="app">
        <!-- 引用父組件 -->
        <son @funo="getMsg"></son>

        <!-- 組件模板定義 -->
        <script type="x-template" id="son">
            <div>
                <input type="button" value="向父組件傳值" @click="sendMsg" />
            </div>
        </script>
    </div>

    <script>
    // 子組件的定義方式
    Vue.component('son',{
        template: '#son',//組件模板Id
        methods: {
            sendMsg() { // 按鈕的點(diǎn)擊事件
                this.$emit('funo,'OK'); // 調(diào)用父組件傳遞過(guò)來(lái)的方法,同時(shí)把數(shù)據(jù)傳遞出去
            }
        }
    });

    //創(chuàng)建 Vue 實(shí)例,得到 ViewModel
    var vm = new Vue({
        el: "#app",
        data: {},
        methods: {
            getMsg(val){ //子組件中,通過(guò) this.$emit() 實(shí)際調(diào)用的方法,在此進(jìn)行定義
                alert(val);
            }
        }
    });
    </script>

評(píng)論列表案例

目標(biāo):主要練習(xí)父子組件之間傳值

使用this.$refs來(lái)獲取元素和組件

<div id="app">
    <div>
        <input type="button" value="獲取元素內(nèi)容" @click="getElemrnt" />
        <!-- 使用 ref 獲取元素 -->
        <h1 ref="myh1">這是一個(gè)大大的H1</h1>
        
        <hr>
        <!-- 使用 ref 獲取子組件 -->
        <my-com ref="mycom"></my-com>
    </div>
</div>

<script>
    Vue.component('my-com',{
        template: '<h5>這是一個(gè)子組件<h5>',
        data() {
            return {
                name: '子組件'
            }
        }
    });

    //創(chuàng)建Vue實(shí)例,得到ViewModel
    var vm = new Vuew({
        el: "#app",
        data: {},
        methods: {
            getElement() {
            // 通過(guò) this.$refs 來(lái)獲取元素
            console.log(this.$refs.myh1.innerText);
            // 通過(guò) this.$refs 來(lái)獲取組件
            console.log(this.$refs.mycom.name);
            }
        }
    });
</script>

什么是路由

  1. 后端路由:對(duì)于普通的網(wǎng)站,所有的超鏈接都是URL地址,所有的URL地址都對(duì)應(yīng)服務(wù)器上對(duì)應(yīng)的資源;

  2. 前端路由:對(duì)于單頁(yè)面應(yīng)用程序來(lái)說(shuō),主要通過(guò)URL中的hash(#號(hào)),來(lái)實(shí)現(xiàn)不同頁(yè)面之間的切換,同時(shí),hash有一個(gè)特點(diǎn):HTTP請(qǐng)求中不會(huì)包含hash相關(guān)內(nèi)容;所以,單頁(yè)面程序中的頁(yè)面跳轉(zhuǎn)主要用hash實(shí)現(xiàn);

  3. 在單頁(yè)面應(yīng)用程序中,這種通過(guò)hash改變來(lái)切換頁(yè)面的方式,稱作前端路由(區(qū)別于后端路由);

在 vue 中使用 vue-router

  1. 導(dǎo)入 vue-router 組件類庫(kù):

     <!-- 1. 導(dǎo)入 vue-router 組件類庫(kù) -->
     <script src="./lib/vue-router-2.7.0.js></script>
    
  2. 使用 router-linx 組件來(lái)導(dǎo)航

     <!-- 2. 使用 router-link 組件來(lái)導(dǎo)航 -->
     <router-link to="/login">登錄<、router-link>
     <router-link to="/register">注冊(cè)<、router-link>
    
  3. 使用 touter-view 組件來(lái)顯示匹配到的組件

     <!-- 3. 使用 touter-view 組件來(lái)顯示匹配到的組件 -->
     <router-view></router-view>
    
  4. 創(chuàng)建使用Vue.extend創(chuàng)建組件

     // 4.1 使用`Vue.extend`來(lái)創(chuàng)建登錄組件
     var login = Vue.extend({
         template:'<h1>登錄組件</h1>'
     });
     
     // 4.2 使用`Vue.extend`來(lái)創(chuàng)建注冊(cè)組件
     var register = Vue.extend({
         template:'<h1>注冊(cè)組件</h1>'
     })
    
  5. 創(chuàng)建一個(gè)路由 router 實(shí)例,通過(guò) router 屬性來(lái)定義路由匹配規(guī)則

     // 5. 創(chuàng)建一個(gè)路由 router 實(shí)例,通過(guò) router 屬性來(lái)定義路由匹配規(guī)則    
     var router = new VueRouter({
         router: {
             { path: '/login',component: login },
             { path: '/register',component: register }
         }
     });
    
  6. 使用 router 屬性來(lái)使用路由規(guī)則

     // 6. 創(chuàng)建vue實(shí)例,得到ViewModel
     var vm = new Vue({
         el:'#app',
         router: router // 使用router屬性來(lái)使用路由規(guī)則
     });
    

使用tag屬性指定router-link渲染的標(biāo)簽類型

    <!-- router-link 默認(rèn)渲染為一個(gè) a 標(biāo)簽 -->
    <!-- tag 屬性指定 router-link 渲染為 什么元素 -->
    <!-- 不管渲染為什么元素,都是可點(diǎn)擊的元素 -->
    <router-link to="/login" tag="span">登錄</router-link>
    <router-link to="/register">注冊(cè)</router-link>

設(shè)置路由重定向

    // 2. 創(chuàng)建一個(gè)路由對(duì)象,當(dāng)導(dǎo)入 vue-router 包之后,在 winodow 全局對(duì)象中,就有了一個(gè) 路由的構(gòu)造函數(shù):VueRouter
    // 在 new 路由對(duì)象的時(shí)候,可以為構(gòu)造函數(shù),傳遞一個(gè)配置對(duì)象
    var routerObj = new VueRouter({
        // route //這個(gè)配置對(duì)象中的 route 表示 【路由匹配規(guī)則】 的意思
        routes: [ // 路由匹配規(guī)則
        //每個(gè)路由規(guī)則,都是一個(gè)對(duì)象,這個(gè)規(guī)則對(duì)象身上,有兩個(gè)必須的屬性:
        // 屬性1 是 path,表示監(jiān)聽(tīng)哪個(gè)路由鏈接地址
        // 屬性2 是 component,表示如果路由前面匹配到的 path,則展示 component 屬性對(duì)應(yīng)的那個(gè)組件
        // 注意:component 的屬性值,必須是一個(gè) 組件模板對(duì)象,不能是 組件的引用名稱('login')
            { path: '/', redirect: '/login'}, //如果請(qǐng)求的是默認(rèn)路徑,則重定向到 login 組件中
            { path: '/login', component: login},
            { path: '/register', component: register}
        ],
        linkActiveClass: 'myactive' // 為路由高亮指定類名,高亮?xí)r使用 .myactive 樣式,不會(huì)使用默認(rèn)的 .router-link-active 樣式
    })

設(shè)置路由高亮

方式一:使用vue提供的.router-link-active 進(jìn)行定義

    /* 實(shí)現(xiàn)路由高亮 */
    .router-link-active {
        color: red;
        font-weight: 800;
        font-style: italic;
        font-size: 80px;
        text-decoration: underline;
    }

方式二:為路由對(duì)象linkActiveClass重新設(shè)置一個(gè)自定義類名,這個(gè)類名可以是bootstrap的類名也可以是自定義的

linkActiveClass: 'myactive'

    .myactive {
        color: red;
        font-weight: 800;
        font-style: italic;
        font-size: 80px;
        text-decoration: underline;
        background-color: brown;

設(shè)置路由切換動(dòng)效

    <!-- 這是 vue-router 提供的元素,專門(mén)用來(lái)當(dāng)做占位符的,將來(lái),路由規(guī)則匹配到的組件,就會(huì)展示到這個(gè) router-view 中去 -->
    <transition mode="out-in"> <!-- 添加動(dòng)畫(huà)效果 -->
        <router-view></router-view>
    </transitio

    .v-enter,
    .v-leave-to {
        opacity: 0;
        transform: translateX(140px);
    }

    .v-enter-active,
    .v-leave-active {
        transition: all 0.5s ease;
    }

在路由規(guī)則中定義參數(shù)

方式一:

  1. 在規(guī)則中定義參數(shù):

     { path: 'register/:id/:name', component: register }
    
  2. 在路由中傳遞參數(shù):(12、zhangsan 分別對(duì)應(yīng)規(guī)則中的id、name)

     <router-link to="/login/12/zhangsan">注冊(cè)</router-link>
    
  3. 通過(guò)this.$router.params來(lái)獲取路由中的參數(shù):(this可省略)

     var register = Vue.extend({
         template: '<h1>注冊(cè)組件 --- {{ this.$router.params.id --- {{ this.$router.params.name }}</h1>'
     });
    

方式二:

  1. 直接在路由中傳遞參數(shù)

     <!-- 如果在路由中,使用 查詢字符串,給路由傳參,則不需要修改路由規(guī)則的 path 屬性 -->
     <router-link to="/login?id=10&name=zhangsan">登錄</router-link>
    
  2. 通過(guò)this.$router.query來(lái)獲取路由中的參數(shù):

     var login = {
         template: '<h1>登錄 --- {{ $route.query.id }} --- {{ $route.query.name }}</h1>',
         data() {
             return {
                 msg: '123'
             }
         },
         created() {
             // 組件的生命周期鉤子函數(shù)
             console.log(this.$route)
             console.log(this.$route.query.id)
         }
     }
    

使用children屬性實(shí)現(xiàn)路由嵌套

<div id="app">
    <router-link to="/account">Account</router-link>
    <router-view></router-view>
</div>

<script>
    // 父路由中的組件
    const account = Vue.extend({
        template: `<div>
    這是account組件
    <router-link to="/account/login">login</router-link> |
    <router-link to="/account/register">register</router-link>
    <router-view></router-view>
</div>`
    })

    // 子路由中的 login 組件
    const login = Vue.extend({
        template: `<div>登錄組件</div>`
    })

    // 子路由中的 register 組件
    const register = Vue.extend({
        template: `<div>注冊(cè)組件</div>`
    })

    // 路由實(shí)例
    var router = new VueRouter({
        routes:[
            { path: '/',redirect:'/account/login'},// 使用 redirect 實(shí)現(xiàn)路由重定向
            {
                path: '/account',
                component: account,
                children: [
                    // 通過(guò) children 數(shù)組屬性,來(lái)實(shí)現(xiàn)路由的嵌套
                    { path: 'login', component: login },//注意,子路由的開(kāi)頭位置,不需要加 / 路徑符
                    { path: 'register', component: register }
                ]
            }
        ]
    });

     var vm = new Vue({
        el : '#app',
        data : {  },
        methods : { },
        components: {
            account
        },
        router: router    
    });
</script>

命名視圖實(shí)現(xiàn)經(jīng)典布局

  1. 標(biāo)簽代碼結(jié)構(gòu):

     <div id="app">
    
         <router-view></router-view>
         <div class="container">
             <!-- name 屬性指定要放的組件 -->
             <router-view name="left"></router-view>
             <router-view name="main"></router-view>
         </div>
    
     </div>
    
  2. JS代碼

     <script>
    
     var header = {
         template: '<h1 class="header">Header頭部</h1>'
     }
    
     var leftBox = {
         template: '<h1 class="left">Left側(cè)邊欄區(qū)域</h1>'
     }
    
     var mainBox = {
         template: '<h1 class="main">mainBox主體區(qū)域</h1>'
     }
    
     // 創(chuàng)建路由對(duì)象
     var router = new VueRouter({
         routes: [
             // { path: '/', component: header },
             // { path: '/left', component: leftBox },
             // { path: '/main', component: mainBox },
    
             { path: '/', components: {
                 'default': header,
                 'left': leftBox,
                 'main': mainBox
             } 
             },
    
         ]
     })
    
      var vm = new Vue({
         el : '#app',
         data : {  },
         methods : { },
         router    
     });
     </script>
    
  3. CSS代碼:

     <style>
     html,body {
         margin: 0;
         padding: 0;
     }
    
     .header {
         height: 80px;
         background-color: orange;
     }
    
     h1 {
         margin: 0;
         padding: 0;
         font-size: 16px;
     }
    
     .container {
         display: flex;
         height: 600px;
     }
    
     .left {
         background-color: lightgreen;
         flex: 2;
     }
    
     .main {
         background-color: lightpink;
         flex: 8;
     }
     </style>
    

watch屬性的使用

html結(jié)構(gòu)

<div id="app">

    <input type="text" v-model="firstname"> +
    <input type="text" v-model="lastname"> =
    <input type="text" v-model="fullname">

</div>

JS代碼

<script>
     var vm = new Vue({
        el : '#app',
        data : { 
            firstname: '',
            lastname: '',
            fullname: ''
         },
        methods : { },
        watch: {
            // 使用這個(gè)屬性可以監(jiān)視 data 中指定數(shù)據(jù)的變化,然后觸發(fā) watch 中對(duì)應(yīng)的 function 處理函數(shù)
            // 監(jiān)視 firstname 的變化,改變了則調(diào)用 function 函數(shù),如果first-name(帶橫線),需要加上引號(hào)
            'firstname': function(newVal, oldVal) {
                // console.log('監(jiān)視到了 firstname 的變化')
                // this.fullname = this.firstname + '-' + this.lastname

                // console.log(newVal + '---' + oldVal)

                this.fullname = newVal + '-' + this.lastname

            },
            'lastname': function(newVal) {
                this.fullname = this.firstname + '-' + newVal
            }
        }    
    });
</script>

使用watch監(jiān)視路由地址的改變

html結(jié)構(gòu)

<div id="app">

    <!-- 6.鏈接 -->
    <router-link to="/login">登錄</router-link>
    <router-link to="/register">注冊(cè)</router-link>

    <!-- 5.容器 -->
    <router-view></router-view>
</div>

JS代碼

<script>
    // 2.創(chuàng)建子組件
    var login = {
        template: '<h1>登錄組件</h1>'
    }

    var register = {
        template: '<h1>注冊(cè)組件</h1>'
    }

    // 3.創(chuàng)建一個(gè)路由對(duì)象
    var router = new VueRouter({
        routes: [ //路由規(guī)則數(shù)組
            { path: '/', redirect: '/login' },// 默認(rèn)路徑重定向
            { path: '/login', component: login},
            { path: '/register', component: register}
        ],
        linkActiveClass: 'myactive' // 激活相關(guān)的類
    })

     var vm = new Vue({
        el : '#app',
        data : {  },
        methods : { },
        // 4. 掛載路由
        router,
        watch: {
            // this.$route.path 獲取路由
            '$route.path': function(newVal,oldVal) {
                console.log( newVal + '---' + oldVal )
                if ( newVal === '/login') {
                    console.log('歡迎進(jìn)入登錄頁(yè)面')
                } else if ( newVal === '/register') {
                    console.log('歡迎進(jìn)入注冊(cè)頁(yè)面')
                }
            }
        }    
    });
</script>

computed計(jì)算屬性的使用

html結(jié)構(gòu)

<div id="app">

    <input type="text" v-model="firstname"> +
    <input type="text" v-model="lastname"> =
    <input type="text" v-model="fullname">

    <p>{{ fullname }}</p>
    <p>{{ fullname }}</p>
    <p>{{ fullname }}</p>

</div>

JS代碼

<script>
     var vm = new Vue({
        el : '#app',
        data : { 
            firstname: '',
            lastname: ''
         },
        methods : { },
        computed: {
            // 在 computed 中,可以定義一些屬性,這些屬性叫做【計(jì)算屬性】,
            //本質(zhì)就是一個(gè)方法,只不過(guò)在使用這些計(jì)算屬性的時(shí)候,
            //是把他們的 名稱直接當(dāng)做 屬性來(lái)使用,并不會(huì)把計(jì)算屬性當(dāng)做方法去調(diào)用。

            // 1.注意:計(jì)算屬性,在引用的時(shí)候,一定不要加()調(diào)用 ,直接把它當(dāng)做普通屬性去使用
            // 2.注意:只要計(jì)算屬性這個(gè) function 內(nèi)部所用到的 data 中的數(shù)據(jù)發(fā)生了變化,就會(huì)立即重新計(jì)算這個(gè)計(jì)算屬性的值
            // 意思是 fullname 永遠(yuǎn)跟隨 firstname 和 lastname 的變化而變化
            // 3.注意:計(jì)算屬性的求值結(jié)果,會(huì)被緩存起來(lái),方便下次調(diào)用,如果 計(jì)算屬性方法中,所有的數(shù)據(jù)都沒(méi)有發(fā)生變化,就不會(huì)重新對(duì)計(jì)算屬性求值
            // 'fullname': function() {
            //     console.log('ok')
            //     return this.firstname + '-' + this.lastname
            // }

            fullname: {
                get:function() {
                    console.log('ok')
                    return this.firstname + '-' + this.lastname
                },
                set:function() {}
            }
        }    
    });
</script>

watchcomputed、methods之間的對(duì)比

  1. computed屬性的結(jié)果會(huì)被緩存,除非依賴的響應(yīng)式屬性變化才會(huì)重新計(jì)算,主要當(dāng)作屬性來(lái)使用;
  2. methods方法表示一個(gè)具體的操作,主要書(shū)寫(xiě)業(yè)務(wù)邏輯;
  3. watch一個(gè)對(duì)象,鍵是需要觀察的表達(dá)式,值是對(duì)應(yīng)回調(diào)函數(shù),主要用來(lái)監(jiān)聽(tīng)某些特定數(shù)據(jù)的變化,從而進(jìn)行某些具體的業(yè)務(wù)邏輯操作,可以看作是computedmethods的結(jié)合體;

nrm的安裝使用

作用:提供了一些最常用的NPM包鏡像地址,能夠讓我們快速的切換安裝包時(shí)候的服務(wù)器地址;
什么是鏡像:原來(lái)包剛一開(kāi)始是只存在于國(guó)外的NPM服務(wù)器,但是由于網(wǎng)絡(luò)原因,經(jīng)常訪問(wèn)不到,這時(shí)候,我們可以在國(guó)內(nèi),創(chuàng)建一個(gè)和官網(wǎng)完全一樣的NPM服務(wù)器,只不過(guò),數(shù)據(jù)都是從人家那里拿過(guò)來(lái)的,除此之外,使用方式完全一樣。

  1. 運(yùn)行npm i nrm -g全局安裝nrm包;
  2. 使用nrm ls查看當(dāng)前所有可用的鏡像源地址以及當(dāng)前所使用的鏡像源地址;
  3. 使用nrm use npmnrm use taobao切換不同的鏡像源地址;

注意:nrm只是單純提供了幾個(gè)常用的下載包的URL地址,并能夠讓我們?cè)谶@幾個(gè)地址之間,很方便的進(jìn)行切換,但是,我們每次裝包的時(shí)候,使用的裝包工具都是npm

相關(guān)文件

URL中的hash(#號(hào))

鍵盤(pán)對(duì)應(yīng)的碼值

Vue.js - Day5 - Webpack

在網(wǎng)頁(yè)中會(huì)引用哪些常見(jiàn)的靜態(tài)資源?

  • JS
  • .js .jsx .coffee .ts(TypeScript 類C#語(yǔ)言)
  • CSS
  • .css .less .sass .scss
  • Images
  • .jpg .png .gif .bmp .svg
  • 字體文件(Fonts)
  • .svg .ttf .eot .woff .woff2
  • 模板文件
  • .ejs .jade .vue[這是在webpack中定義組件的方式,推薦]

網(wǎng)頁(yè)中引入的靜態(tài)資源多了以后有什么問(wèn)題?

  1. 網(wǎng)頁(yè)加載速度慢,因?yàn)槲覀円l(fā)起很多的二次請(qǐng)求;
  2. 要處理錯(cuò)綜復(fù)雜的依賴關(guān)系

如何解決上述兩個(gè)問(wèn)題

  1. 合并、壓縮、精靈圖、小圖片的Base64編碼
  2. 可以使用requireJS。也可以使用webpack,可以解決各個(gè)包之間的復(fù)雜依賴關(guān)系

什么是webpack

webpack 是前端的一個(gè)項(xiàng)目構(gòu)建工具,它是基于node.js開(kāi)發(fā)出來(lái)的一個(gè)前端工具,因此要使用webpack必須先安裝node

如何完美實(shí)現(xiàn)上述的2種解決方案

  1. 使用Gulp,是基于task任務(wù)的;
  2. 使用Webpack,是基于整個(gè)項(xiàng)目進(jìn)行構(gòu)建的;
  • 借助于webpack這個(gè)前端自動(dòng)化構(gòu)建工具,可以完美實(shí)現(xiàn)資源的合并、打包、壓縮、混淆等諸多功能。
  • 根據(jù)官網(wǎng)的圖片介紹webpack打包過(guò)程
  • webpack官網(wǎng)

webpack 安裝的兩種方式

  1. 運(yùn)行npm i webpack -g全局安裝webpack,這樣就能在全局使用webpack的命令
  2. 在項(xiàng)目根目錄中運(yùn)行npm i webpack --save-dev安裝到項(xiàng)目依賴中

初步使用webpack打包構(gòu)建列表隔行變色案例

  1. 運(yùn)行npm init初始化項(xiàng)目,使用npm管理項(xiàng)目中的依賴包

VScode快捷鍵ctrl + · 打開(kāi)終端,注意那個(gè)點(diǎn)是鍵盤(pán)上 esc 下面的那個(gè);運(yùn)行npm init -y初始化,初始化完成后可以想見(jiàn)項(xiàng)目目錄多了package.json文件

    E:\Vue_Project\vue-study\day5\webpack-study> npm init -y
    Wrote to E:\Vue_Project\vue-study\day5\webpack-study\package.json:

    {
        "name": "webpack-study",
        "version": "1.0.
        "description": "",
         "main": "main.js",
        "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
    },
    "keywords": [],
    "author": "",
    "license": "ISC"
    }
  1. 創(chuàng)建項(xiàng)目基本的目錄結(jié)構(gòu)
  2. 使用cnpm i jquery --save安裝jquery類庫(kù)

運(yùn)行npm i jquery -S安裝jquery

    E:\Vue_Project\vue-study\day5\webpack-study> npm i jquery -S
    npm notice created a lockfile as package-lock.json. You should commit this file.
    npm WARN webpack-study@1.0.0 No description
    npm WARN webpack-study@1.0.0 No repository field.

    + jquery@3.4.1
    added 1 package from 1 contributor and audited 1 package in 2.161s
    found 0 vulnerabilities
  1. 創(chuàng)建main.js并書(shū)寫(xiě)各行變色的代碼邏輯:

     // 導(dǎo)入jquery類庫(kù)
     import $ from 'jquery'
     
     // 設(shè)置偶數(shù)行背景色,索引從0開(kāi)始,0是偶數(shù)
     $('#list li:even').css('backgroundColor','lightblue');
     // 設(shè)置奇數(shù)行背景色
     $('#list li:odd').css('backgroundColor','pink');
    
  2. 直接在頁(yè)面上引用main.js會(huì)報(bào)錯(cuò),因?yàn)闉g覽器不認(rèn)識(shí)import這種高級(jí)的JS語(yǔ)法。需要使用webpack進(jìn)行處理,webpack默認(rèn)會(huì)把這種高級(jí)的語(yǔ)法轉(zhuǎn)換為低級(jí)的瀏覽器能識(shí)別的語(yǔ)法;

運(yùn)行webpack 入口文件路徑 輸出文件路徑對(duì)main.js進(jìn)行處理:

    webpack src/js/main.js dist/bundle.js

注意:如果webpack版本過(guò)高,上述語(yǔ)句會(huì)報(bào)錯(cuò),需要用webpack .\src\main.js -o .\dist\bundle.js來(lái)打包,詳情webpack 打包報(bào)錯(cuò):Can't resolve '.\dist\bundle.js' in 'E:\vivian....'

  1. 由于每次修改main.js文件都需要重新使用webpack src/js/main.js dist/bundle.js進(jìn)行打包,累贅且麻煩,因此在項(xiàng)目根目錄引入配置文件webpack.config.js,聲明要打包的文件路徑和導(dǎo)出的文件路徑,下次項(xiàng)目更改需要重新打包時(shí),運(yùn)行webpack即可。

webpack.config.js配置文件內(nèi)容:

const path = require('path')

// 這個(gè)配置文件,其實(shí)就是一個(gè) JS 文件,通過(guò) node 中的模塊操作,向外暴露了一個(gè) 配置對(duì)象
module.exports = {
    mode: 'development',
    entry: path.join(__dirname, './src/main.js'), // 入口,表示要使用 webpack 打包那一個(gè)文件
    output: {
        //輸出文件相關(guān)配置
        path: path.join(__dirname, './dist'),//指定 打包好的文件,輸出到哪個(gè)目錄中去
        filename: 'bundle.js' // 指定 輸出文件的名稱
    }
}

// 當(dāng)我們?cè)诳刂婆_(tái),直接輸入 webpack 命令執(zhí)行的時(shí)候,webpack做了以下幾步:
// 1. 首先,webpack發(fā)現(xiàn)我們并沒(méi)有通過(guò)命令的形式,給它指定出口和入口
// 2. webpack 就會(huì)去 項(xiàng)目的根目錄 中,查找一個(gè)叫做'webpack.config.js'的配置文件
// 3. 當(dāng)找到配置文件后,webpack 會(huì)去解析執(zhí)行這個(gè) 配置文件,當(dāng)解析執(zhí)行完配置文件后,就得到了配置文件中導(dǎo)出的 配置對(duì)象
// 4. 當(dāng) webpack 拿到配置對(duì)象后,就拿到了配置對(duì)象中,指定的 入口 和出口,然后進(jìn)行打包構(gòu)建
  1. 再由于每次代碼更改都需要手動(dòng)重新打包編譯,使用webpack-dev-server這個(gè)工具進(jìn)行偷懶。運(yùn)行npm i webpack-dev-server -D,把這個(gè)工具安裝到項(xiàng)目的本地開(kāi)發(fā)依賴。

  2. webpack-dev-server要求webpack安裝在本地項(xiàng)目下,運(yùn)行npm i webpack -D安裝。

  3. webpack要求webpack-cli安裝在本地項(xiàng)目下,運(yùn)行npm i webpack-cli -D安裝。

  4. package.json內(nèi),添加dev

    {
    "name": "webpack-study",
    "version": "1.0.0",
    "description": "",
    "main": "main.js",
    "scripts": {
        "test": "echo \"Error: no test specified\" && exit 1",
    "dev": "webpack-dev-server" //添加webpack-dev-server
    },
    
  5. 運(yùn)行npm run dev使用webpack-dev-server工具。

  6. i ?wds?: Project is running at http://localhost:8080/ 可在終端查看到服務(wù)器端口http://localhost:8080/
    i ?wds?: webpack output is served from /可在終端查看到打包的bundle.js的路徑是根目錄下的絕對(duì)路徑,可以通過(guò)http://localhost:8080/bundle.js訪問(wèn)到bundle.js。此時(shí)引入bundl.js只需寫(xiě)根目錄的路徑即可<script src="/bundle.js"></script>

  7. 此時(shí)修改代碼只需保存,webpack-dev-server就會(huì)實(shí)時(shí)監(jiān)聽(tīng)代碼的改變和刷新瀏覽器,不需要再手動(dòng)打包,甚至不用刷新瀏覽器即可看到效果。

webpack-dev-server 幫我們打包生成的 bundle.js 文件,并沒(méi)有存放到實(shí)際的物理磁盤(pán)中,而是直接托管到了電腦的內(nèi)存中,所以,我們?cè)陧?xiàng)目的根目錄中,找不到打包好的bundle.js。 可以認(rèn)為,webpack-dev-server 把打包好的文件,以一種虛擬的形式,托管到了項(xiàng)目的根目錄中,雖然我們看不見(jiàn),但是可以認(rèn)為,和 dist src node_modules平級(jí),有一個(gè)看不見(jiàn)的bundle.js文件。正是這種虛擬的托管方式,大大提高了加載效率。

  1. 此時(shí)需要手動(dòng)打開(kāi)瀏覽器并且是固定端口"8080",且進(jìn)入的頁(yè)面是項(xiàng)目根目錄,十分不爽,因此修改package.json代碼:"dev": "webpack-dev-server --open --port 3000 --contentBase src"open意思是自動(dòng)打開(kāi)瀏覽器并運(yùn)行項(xiàng)目,port 3000意思是在3000端口下運(yùn)行,contentBase src的意思是打開(kāi)時(shí)默認(rèn)打開(kāi)src目錄下的頁(yè)面。

  2. 繼續(xù)修改package.json代碼:"dev": "webpack-dev-server --open --port 3000 --contentBase src --hot"。hot是熱更新的意思,意思是將修改的那一部分代碼作為補(bǔ)丁打在打包生成的bundle.js上,實(shí)現(xiàn)局部更新,加快加載進(jìn)度。

  3. 以上步驟完成后,運(yùn)行項(xiàng)目只需在項(xiàng)目根目錄下運(yùn)行npm run dev命令,webpack-dev-server就會(huì)幫我們自動(dòng)打開(kāi)瀏覽器并在我們指定的端口下運(yùn)行我們指定的頁(yè)面,修改代碼后僅需保存webpack-dev-server就會(huì)幫助我們自動(dòng)刷新瀏覽器。

配置 dev-server 的第二種形式

在webpack.config.js下添加

// 啟用熱更新的第二步
const webpack = require('webpack')

devServer: { // 這是配置 dev-server 命令參數(shù)的第二種形式,相對(duì)來(lái)說(shuō),這種方式麻煩一些
    // --open --port 3000 --contentBase src --hot
    open: true, // 自動(dòng)打開(kāi)瀏覽器
    port: 3000, // 設(shè)置啟動(dòng)時(shí)的運(yùn)行端口
    contentBase: 'src', // 指定托管的根目錄
    hot: true // 啟動(dòng)熱更新的第一步
}

plugins: [ // 配置插件的節(jié)點(diǎn)
    new webpack.HotModuleReplacementPlugin() // new 一個(gè)熱更新的模塊的對(duì)象,啟用熱更新的第3步
]

在 package.json 中 只需聲明"dev": "webpack-dev-server"

使用help-webpack-plugin插件配置啟動(dòng)頁(yè)面

由于使用--contentBase指令的過(guò)程比較繁瑣,需要綁定啟動(dòng)的目錄,同時(shí)還需要修改index.html中script標(biāo)簽的src屬性,所以推薦大家使用html-webpack-plugin插件配置啟動(dòng)頁(yè)面。

這個(gè)插件的兩個(gè)作用:1. 自動(dòng)在內(nèi)存中根據(jù)指定頁(yè)面生成一個(gè)內(nèi)存中的頁(yè)面。2. 自動(dòng)把打包好的 bundle.js 追加到頁(yè)面中去

  1. 運(yùn)行cnpm i html-webpack-plugin --save-dev安裝到開(kāi)發(fā)依賴

  2. 修改webpack.config.js配置文件如下:

     // 導(dǎo)入處理路徑的模塊
     var path = require('path');
     // 導(dǎo)入自動(dòng)生成HTML文件的插件
     var htmlWebpackPlugin = require('html-webpack-plugin');
     
     module.exports = {
         entry: path.resolve(_dirname, 'src/js/main.js'), // 項(xiàng)目入口文件
         output: { // 配置輸出選項(xiàng)
             path: path.resolve(_dirname, 'dist'), // 配置輸出的路徑
             filename: 'bundle.js' // 配置輸出的文件名
         },
         plugins: [ // 添加plugins節(jié)點(diǎn)配置插件
             new htmlWebpackPlugin({
                 template:path.resolve(_dirname,'src/index.html'), // 模塊路徑
                 filename: 'index.html' // 自動(dòng)生成的HTML文件的名稱
             })
         ]
     }
    
  3. 修改package.jsonscript節(jié)點(diǎn)中的dev指令如下:
    "dev": "webpack-dev-server"

  4. 將index.html中script標(biāo)簽注釋掉,因?yàn)?code>html-webpack-plugin插件會(huì)自動(dòng)把bundle.js注入到index.html頁(yè)面中。此時(shí)查看頁(yè)面源代碼可以看到底部已經(jīng)自動(dòng)引用了bundle.js

使用webpack打包c(diǎn)ss文件

  1. 運(yùn)行cnpm i style-loader css-loader --save-dev

  2. 修改webpack.config.js文件

     module: { // 用來(lái)配置第三方loader模塊的
         rules: [ // 文件的匹配規(guī)則
             { test: /\.css$/,use: ['style-loader', 'css-loader']} // 處理css文件的規(guī)則 
         ]
     }
    
  3. 注意:css表示使用哪些模塊來(lái)處理test所匹配到的文件;use中相關(guān)loader模塊的調(diào)用順序是從后向前調(diào)用的;

使用webpack打包less文件

  1. 運(yùn)行cnpm i less-loader less -D
  2. 修改webpack.config.js這個(gè)配置文件:
    { test: /\.less$/,use: ['style-loader', 'css-loader','less-loader']},

使用webpack打包scss文件

  1. 運(yùn)行npm i sass-loader -D,終端提示需要安裝node-sass依賴

  2. 運(yùn)行cnpm i node-sass -D(注意:只有極少數(shù)情況才能使用npm成功安裝node-sass,所以這里推薦使用cnpm安裝)

  3. 修改webpack.config.js這個(gè)配置文件:
    { test: /\.scss$/,use: ['style-loader', 'css-loader','sass-loader']},

  4. 本人在運(yùn)行npm run dev命令后報(bào)錯(cuò)ERROR in ./src/css/index.scss (./node_modules/css-loader/dist/cjs.js!./node_modules/_sass-loader@7.3.1@sass-loader/dist/cjs.js!./src/css/index.scss),百度了一下問(wèn)題解決方法webpack打包node-sass編譯報(bào)錯(cuò),可行,運(yùn)行成功。

// 注意: webpack 處理第三方文件類型的過(guò)程:
// 1. 發(fā)現(xiàn)這個(gè)要處理的文件不是 JS 文件,然后就去配置文件中查找有沒(méi)有對(duì)應(yīng)第三方 loader 規(guī)則
// 2. 如果能找到對(duì)應(yīng)的規(guī)則,就會(huì)調(diào)用對(duì)應(yīng)的 loader 處理這種文件類型;
// 3. 在調(diào)用 loader 的時(shí)候,是從后往前調(diào)用的
// 4. 當(dāng)最后的一個(gè) loader 調(diào)用完畢,會(huì)把處理的結(jié)果交給 webpack 打包合并,最終輸出到 bundle.js 中去

使用webpack識(shí)別url地址

  1. 運(yùn)行npm i url-loader file-loader -D命令,安裝url-loader第三方模塊,同時(shí)該模塊依賴file-loader,因此一起安裝了。

  2. 修改webpack.config.js這個(gè)配置文件:{ test: /\.(jpg|png|gif|bmp|jpeg)$/,use: 'url-loader'}

  3. 可以通過(guò)傳參來(lái)指定多大的圖片才轉(zhuǎn)碼。比如有一張圖片是40062字節(jié)的,此時(shí)修改{ test: /\.(jpg|png|gif|bmp|jpeg)$/,use: 'url-loader?limit=40063'},limit 給定的值是圖片的大小,單位是 byte,如果圖片大于給定的 limit 值,則不會(huì)被轉(zhuǎn)為 base64 格式的字符串,如果圖片小于或等于給定的 limit,則會(huì)被轉(zhuǎn)為 base64 字符串

     圖片大小40062 = limit值40062 轉(zhuǎn)
     圖片大小40062 > limit值40061 不轉(zhuǎn)
     圖片大小40062 < limit值40063 轉(zhuǎn)
    
  4. 可以通過(guò)傳參來(lái)指定不轉(zhuǎn)碼時(shí)圖片的名稱。修改{ test: /\.(jpg|png|gif|bmp|jpeg)$/,use: 'url-loader?limit=40061&name=[name].[ext]'},[name]指圖片原來(lái)的名字叫什么就是什么,不會(huì)被改變,[ext]指圖片原來(lái)的格式不會(huì)被改變。

  5. 經(jīng)過(guò)上一步,圖片不轉(zhuǎn)碼時(shí)名稱不會(huì)被改變,但是當(dāng)引用了兩張一樣名字的圖片時(shí),先引用的圖片會(huì)被后引用的覆蓋,此時(shí)修改{ test: /\.(jpg|png|gif|bmp|jpeg)$/,use: 'url-loader?limit=40061&name=[hash:8]-[name].[ext]'}[hash:8]-表示圖片前面添加8位的哈希值,最高可添加32位。這樣就能避免同名圖片被覆蓋。

webpack使用url-loader處理字體文件

  1. 運(yùn)行cnpm i bootstrap -S安裝bootatrap。
  2. 在webpack.config.js內(nèi)添加{ test: /\.(ttf|eot|svg|wpff|woff2)$/,use: 'url-loader' },在index.js添加import 'bootstrap/dist/css/bootstrap.css'

組件中的css作用域問(wèn)題

抽離路由器為單獨(dú)的模塊

使用 餓了么的MintUI組件

Github倉(cāng)儲(chǔ)地址

Mint-UI官方文檔

完整引入

  1. 導(dǎo)入所有的MintUI組件
    import MintUI from 'mint-ui'
  1. 導(dǎo)入樣式表:
    import 'mint-ui/lib/style.css'
  1. 將Mint-UI注冊(cè)到 Vue 身上
    Vue.use(MintUI)
  1. vue 中使用 MintUI 中的 Button 按鈕,使用例子:
    <mt-button type="primary" size="large">primary</mt-button>

完整引入之后,使用css組件只需導(dǎo)入標(biāo)簽即可
<mt-button type="default">default</mt-button>

vue中使用 Mint-UI的js組件

  1. 導(dǎo)入 js 組件(以 Toast彈框提示 為例)
    import { Toast } from 'mint-ui';

  2. 暴露接口

     export default {
         data() {
             return {}
         },
         methods: {
             show() {
                 Toast("提示信息");
             }
         }
     }
    
  3. 在 html 中添加點(diǎn)擊事件
    <mt-button type="default" @click="show">default</mt-button>

webpack中bootstrap圖標(biāo) 不顯示

Mint-UI中按需導(dǎo)入的配置方式

  1. 安裝 babel-plugin-component:

npm install babel-plugin-component -D

  1. 修改.babelrc

     {
         "presets": [
             ["es2015", { "modules": false }]
         ],
         "plugins": [["component", [
         {
             "libraryName": "mint-ui",
             "style": true
         }
         ]]]
     }
    
  2. 按需導(dǎo)入 Mint-UI組件

import { Button } from 'mint-ui'

  1. 使用 Vue.compoent 注冊(cè) 按鈕組件

Vue.component('mybtn',Button)

Vue.component(Button.name,Button)

  1. 在相對(duì)應(yīng)的vue文件中添加標(biāo)簽

<mybtn></mybtn>或直接引用<mt-button type="default" @click="show">default</mt-button>

使用 MUI 代碼片段

注意:MUI不同于 Mint-UI,MUI 只是開(kāi)發(fā)出來(lái)的一套好用的代碼片段,里面提供了配套的樣式,配套的HTML代碼段,類似于 Bootstrap;而Mint-UI,是真正的組件套,是使用 Vue 技術(shù)封裝出來(lái)的 成套的組件,可以無(wú)縫的和 VUE 項(xiàng)目進(jìn)行集成開(kāi)發(fā);

因此,從體驗(yàn)上來(lái)說(shuō),Mint-UI體驗(yàn)更好,因?yàn)檫@是別人幫我們開(kāi)發(fā)好的現(xiàn)成的Vue組件;

從體驗(yàn)上來(lái)說(shuō),MUI 和 Bootstrap 類似;

理論上,任何項(xiàng)目都可以使用 MUI 或 Bootstrap,但是,Mint-UI只適用于 Vue 項(xiàng)目;

官網(wǎng)首頁(yè)

文檔地址

  1. 導(dǎo)入 MUI 的樣式表:
    import '../lib/mui/css/mui.min.css'
  1. webpack.config.js中添加新的 loader 規(guī)則:
    { test:/\.{png|jpg|gif|ttf}$/,use:'url-loader'}
  1. 根據(jù)官方提供的文檔和example,嘗試使用相關(guān)的組件

將項(xiàng)目源碼托管到oschina中

  1. 點(diǎn)擊頭像 -> 修改資料 -> SSH公鑰 如何生成SSH公鑰

  2. 創(chuàng)建自己的空倉(cāng)庫(kù),使用 git config --global user.name "用戶名"git config --global user.email **@**.com來(lái)全局配置提交時(shí)用戶的名稱和郵箱

  3. 使用git init在本地初始化項(xiàng)目

  4. 使用touch README.mdtouch .gitignore來(lái)創(chuàng)建項(xiàng)目的說(shuō)明文件和忽略文件;

  5. 使用git add .將所有文件托管到git中

  6. 使用git commit -m "init project"將項(xiàng)目進(jìn)行本地提交

新建項(xiàng)目步驟

  • 新建項(xiàng)目文件夾-用vscode打開(kāi)

  • 初始化項(xiàng)目:在終端運(yùn)行“npm init”,生成“package.json”

  • 在項(xiàng)目根目錄下新建文件夾“src”,和“dist”,在“src”目錄下新建“main.js"和”index.html"

  • 安裝“webpack-dev-server”,在終端輸入“npm i webpack-wdev-server"

  • webpack-dev-server要求webpack安裝在本地項(xiàng)目下,在終端執(zhí)行命令"npm i webpack",webpack要求webpack-cli安裝在本地項(xiàng)目下,執(zhí)行命令"npm i webpack-cli"

  • 在根目錄下新建“webpack.config.js",配置webpack。

      module.exports = {
      mode: 'development',
      entry: path.join(__dirname, './src/main.js'), // 入口,表示要使用 webpack 打包那一個(gè)文件
      output: {
          //輸出文件相關(guān)配置
          path: path.join(__dirname, './dist'),//指定 打包好的文件,輸出到哪個(gè)目錄中去
          filename: 'bundle.js' // 指定 輸出文件的名稱
      }
      }
    
  • 在“package.json”文件下添加webpack-dev-server工具

    "dev": "webpack-dev-server --open --port 3000 --contentBase src --hot"

  • 運(yùn)行"npm i html-webpack-plugin -D"安裝插件自動(dòng)生成bundle.js

  • 在配置文件webpack.config.js中添加

    var htmlWebpackPlugin = require('html-webpack-plugin')

  • 在配置文件webpack.config.js中添加配置節(jié)點(diǎn)

      //所有webpack插件的配置愛(ài)節(jié)點(diǎn)
      plugins: [
      new htmlWebpackPlugin({
          template:path.resolve(__dirname,'src/index.html'), // 模塊路徑
          filename: 'index.html' // 自動(dòng)生成的HTML文件的名稱
      })
      ]
    
  • 運(yùn)行"npm run dev"不再報(bào)錯(cuò)。

配置css文件步驟

  • 運(yùn)行"npm i style-lloader css-loader"安裝插件,在webpack.config.js文件下添加配置節(jié)點(diǎn)

      module: { // 用來(lái)配置第三方loader模塊的
      rules: [ // 文件的匹配規(guī)則
          { test: /\.css$/,use: ['style-loader', 'css-loader']} // 處理css文件的規(guī)則 
      ]
      }
    
  • 在main.js中引入css文件:import './css/index.css'

Vue.js - day6

注意:

有時(shí)候使用npm i node-sass -D裝不上,這時(shí)候,就必須使用cnpm i node-sass -D

在普通頁(yè)面中使用render函數(shù)渲染組件

在webpack中配置.vue組件頁(yè)面的解析

  1. 運(yùn)行 cnpm i vue -S將Vue安裝為運(yùn)行依賴;
  2. 運(yùn)行cnpm i vue-loader vue-template-compiler -D將解析轉(zhuǎn)換vue的包安裝為開(kāi)發(fā)依賴;
  3. 運(yùn)行cnpm i style-loader css-loader -D將解析轉(zhuǎn)換css的包安裝為開(kāi)發(fā)依賴,因?yàn)?vue文件中會(huì)寫(xiě)css樣式;
  4. webpack.config.js中,添加module規(guī)則:
    { test:/\.js$/, use: 'babel-loader', exclude:/node_modules/ },

在使用webpack構(gòu)建的Vue項(xiàng)目中使用模板對(duì)象

  1. webpack.config.js中添加resolve屬性:
    resolve: {
        alias: {
            'vue$': 'vue/dist/vue.esm.js'
        }
    }
  1. 在 main.js文件下導(dǎo)入模板對(duì)象

import Vue from 'vue'

使用第三方loader處理高級(jí)語(yǔ)法

// 在 webpack 中,默認(rèn)只能處理一部分 ES6 的新語(yǔ)法,一些更高級(jí)的 ES6 語(yǔ)法或者 ES7 語(yǔ)法,
// webpack 是處理不了的,這時(shí)候,就需要借助于第三方的 loader,來(lái)幫助 webpack 處理這些高級(jí)的語(yǔ)法
// 當(dāng)?shù)谌?loader 把高級(jí)的語(yǔ)法轉(zhuǎn)為低級(jí)的語(yǔ)法之后,會(huì)把結(jié)果交給 webpack 去打包到 bundle.js 中

通過(guò) babel,可以幫我們將高級(jí)的語(yǔ)法轉(zhuǎn)為 低級(jí)的語(yǔ)法

  1. 在 webpack中,可以運(yùn)行如下命令,安裝兩套包,去安裝 babel 相關(guān)的 loader功能:
  • 1.1 第一套包: npm i babel-core babel-loader babel-plugin-transform-runtime -D
  • 1.2 第二套包: npm i babel-preset-env babel-preset-stage-0 -D
  1. 打開(kāi) webp 的配置文件,在 module 節(jié)點(diǎn)下的 rules 數(shù)組中,添加一個(gè) 新的匹配規(guī)則:
  • 2.1 { test:/.js$/, use: 'babel-loader', exclude:/node_modules/ }
  • 2.2 注意: 在配置 babel 的 loader 規(guī)則的時(shí)候,必須把 node_modules 目錄,通過(guò) exclude選項(xiàng)排除掉,原因如下:
    • 2.2.1 如果不排除 node_modules,則 babel 會(huì)把 node_modules 中所有的第三方 js 文件都打包編譯,消耗cpu,打包速度變慢
    • 2.2.2 如果 babel 把 node_modules 中的js轉(zhuǎn)換完畢,項(xiàng)目也無(wú)法正常運(yùn)行
  1. 在項(xiàng)目的根目錄中,新建一個(gè) .babelrc 的babel 配置文件,這個(gè)配置文件,屬于 JSON 格式,所以必須符合 JSON 的語(yǔ)法規(guī)范
  • 3.1 在 babelrc 中 寫(xiě)如下的配置:

         { 
             "presets": ["env","stage-0"],//語(yǔ)法
             "plugins": ["transform-runtime"] //插件
         }
    
  1. 目前安裝的 babel-preset-env 是比較新的es語(yǔ)法插件

webpack 中如何使用 vue

  1. 安裝 vue的包: cnpm i vue -S
  2. 由于在 webpack 中,推薦使用 .vue 這個(gè)組件模板文件定義組件,所以,需要安裝能解析這種文件的 loader:cnpm i vue-loader vue-template-complier -D
  3. 在 main.js 中,導(dǎo)入 vue 模板 :import Vue from 'vue'
  4. 定義一個(gè) .vue 結(jié)尾的組件,其中,組件由三部分組成: template script style
  5. 使用 import login from './login.vue'導(dǎo)入這個(gè)組件
  6. 創(chuàng)建 vm 實(shí)例,var vm = new Vue({ el: 'app',render: c => c(login) })
  7. 在頁(yè)面中創(chuàng)建一個(gè) id 為 app 的 div 元素,作為我們 vm 實(shí)例要控制的區(qū)域
    8.注意:. Vue-loader在15.*之后的版本都是 vue-loader的使用都是需要伴生 VueLoaderPlugin的。所以,需要在 webpack.config.js 中 引入 const VueLoaderPlugin = require('vue-loader/lib/plugin'); 在 plugin 中加入 new VueLoaderPlugin()

結(jié)合webpack使用vue-router

  1. 在項(xiàng)目入口文件main.js中

導(dǎo)入 vue-router 包

import VueRouter from 'vue-router'

手動(dòng)安裝 VueRouter

Vue.use(VueRouter)

  1. 導(dǎo)入自定義的路由模塊

import router from './router.js'

  1. 將路由對(duì)象掛載到 vm 實(shí)例上

     var vm = new Vue({
         el:'#app',
         render: c => c(app),// render 會(huì)把 el 指定的容器中所有內(nèi)容都清空覆蓋,所以不能把路由的 router-view 和 router-link 寫(xiě)在里面
         // 4. 將路由對(duì)象掛載到 vm 上
         router
    
     })
    
  2. 自定義路由模塊文件router.js示例

     import VueRouter from 'vue-router'
     // 導(dǎo)入 Account 組件
     import account from './main/Account.vue'
     // 導(dǎo)入 GoodsList 組件
     import goodslist from './main/GoodsList.vue'
     //導(dǎo)入Account的兩個(gè)子組件
     import login from './subcom/login.vue'
     import register from './subcom/register.vue'
    
     //3. 創(chuàng)建路由對(duì)象
     var router = new VueRouter({
         routes: [
             // acount goodslist
             { path: '/account',component: account,
             children: [
                 { path: 'login', component: login },
                 { path: 'register', component: register }
             ]
             },
             { path: '/goodslist',component: goodslist },
         ]
     })
    
     // 把路由對(duì)象暴露出去
     export default router
    
  3. 在對(duì)應(yīng)的 vue 文件中添加容器示例

     <router-link to="/account/login">登錄</router-link>
     <router-link to="/account/register">注冊(cè)</router-link>
    
     <router-view></router-view>
    
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容