vue.js

引入

1、cdn引入

開發(fā)環(huán)境cdn:

<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>

生產(chǎn)環(huán)境cdn:

<script src="https://cdn.jsdelivr.net/npm/vue"></script>

2、下載與引入

通過(guò)官網(wǎng)下載源碼,并且通過(guò)<script>引入

3、npm安裝

vue的MVVM

Vue的原理

  1. 通過(guò)建立虛擬dom樹document.createDocumentFragment(),方法創(chuàng)建虛擬dom樹。

  2. 一旦被監(jiān)測(cè)的數(shù)據(jù)改變,會(huì)通過(guò)Object.defineProperty定義的數(shù)據(jù)攔截,截取到數(shù)據(jù)的變化。

  3. 截取到的數(shù)據(jù)變化,從而通過(guò)訂閱者——發(fā)布者模式,觸發(fā)Watcher(觀察者),從而改變虛擬dom的中的具體數(shù)據(jù)。

  4. 最后,通過(guò)更新虛擬dom的元素值,從而改變最后渲染dom樹的值,完成雙向綁定。

Vue的模式是m-v-vm模式,即(model-view-modelView),通過(guò)modelView作為中間層(即vm的實(shí)例),進(jìn)行雙向數(shù)據(jù)的綁定與變化。

而實(shí)現(xiàn)這種雙向綁定的關(guān)鍵就在于:

Object.defineProperty訂閱——發(fā)布者模式這兩點(diǎn)。

下面我們通過(guò)實(shí)例來(lái)實(shí)現(xiàn)Vue的基本雙向綁定。

Vue的options選項(xiàng)

el:vue實(shí)例管理哪一個(gè)DOM

data:組件化中必須傳對(duì)象

methods:vue實(shí)例中的方法

components:組件

computed:計(jì)算屬性

watch:監(jiān)視,是一個(gè)對(duì)象。

鍵是需要觀察的表達(dá)式,

值是:

  • 回調(diào)函數(shù)
  • 方法名
  • 包含選項(xiàng)的對(duì)象

created :function(){}

mounted:

Vue的生命周期

生命周期

誕生到消亡的整個(gè)過(guò)程。

Vue指令

插值指令

v-once 后面沒(méi)有表達(dá)式。讓顯示的東西不響應(yīng)式,即后期修改了對(duì)象屬性值頁(yè)面上的顯示的不同步變化。

v-html 后面寫屬性名。把屬性值以html的形式插入到此標(biāo)簽里面。

v-text 后面寫屬性名。把屬性值以文本的形式插入到此標(biāo)簽里面。標(biāo)簽原有的內(nèi)容會(huì)被覆蓋。

v-pre 后面沒(méi)有表達(dá)式。去除{{}}表達(dá)式效果,使里面的文本原封不動(dòng)顯示出來(lái)。

v-cloak 后面沒(méi)有表達(dá)式。給元素添加一個(gè)屬性,這個(gè)屬性可以添加css樣式,使其隱藏。vue解析以后就去除這個(gè)屬性。用于解決界面閃爍。

v-for

循環(huán)數(shù)據(jù)。

<body>
<div id="app">
    <!-- v-for -->
    <ul>
        菜式
        <li v-for="(item,index) in food">{{index+1}}、{{item}}</li>
        <!-- item為屬性值,index為索引值,v-for會(huì)循環(huán)每一個(gè)元素并且創(chuàng)建相同的元素節(jié)點(diǎn)顯示數(shù)據(jù) -->
        <li v-for="(value,key,index) in person">{{index+1}},{{key}},{{value}}</li>
        客人
        <!--v-for還可以遍歷對(duì)象,value為對(duì)象屬性值,key為對(duì)象屬性名,index為索引-->
        <li v-for="(item,index) in food" :key="item">{{index+1}}、{{item}}</li>
        <!--可以為對(duì)應(yīng)的元素添加key屬性,當(dāng)我們對(duì)數(shù)組進(jìn)行增刪改時(shí),可以提高更新虛擬DOM的性能-->
    </ul>
</div>
</body>
<script>
    const app = new Vue({
        el:"#app",
        data:{
            food:["大雞腿","土豆絲","土豆絲","嫩鮑魚"],
            person:{
                name:"xiaoming",
                age:19,
                height:178
            }
        },
    })
</script>

以下方法對(duì)數(shù)組元素進(jìn)行操作時(shí),dom同步更新。(響應(yīng)式)

  1. push() 后面添加
  2. pop() 后面刪除
  3. shift() 前面刪除
  4. unshift() 前面添加
  5. splice() 切割、拼接
  6. sort() 排序
  7. reverse() 倒序

通過(guò)索引值修改數(shù)組元素不會(huì)同步更新到頁(yè)面 --> arr[0]="aaaaaa";

通過(guò)Vue實(shí)現(xiàn)的修改數(shù)組元素方法實(shí)現(xiàn)響應(yīng)式Vue.set(arr,index,value) -(目標(biāo)數(shù)組,目標(biāo)索引,要修改的值)。

v-bind

? 動(dòng)態(tài)綁定屬性值。會(huì)把標(biāo)簽里面屬性值當(dāng)作一個(gè)變量傳到vue中,把變量的值返回到標(biāo)簽得屬性。

<body>
<div id="app">
    <!-- v-bind -->
    <a v-bind:href="src">v-bind的使用</a>
    <a :href="src">v-bind的簡(jiǎn)寫</a>
    <div :my="src">v-bind可以為任意的屬性賦值</div>
    <p class="title" :class="{active:true,line:flag}">
        對(duì)象語(yǔ)法:通過(guò)對(duì)象的鍵作為類名,值(boolean)作為判斷是否采用,值也可以用data里面的屬性代替。會(huì)拼接原有的class。</p>
    <p :class="arr">數(shù)組語(yǔ)法:跟對(duì)象語(yǔ)法相似。</p>
    <div :style="style">直接綁定設(shè)置style</div>
    <input :value="age">設(shè)置計(jì)算屬性,計(jì)算屬性設(shè)置在computed里,雖然定義是函數(shù),但是是一個(gè)屬性,使用時(shí)不加()。
</div>
</body>
<script>
    const app = new Vue({
        el:"#app",
        data:{
            src:"https://www.baidu.com",
            flag:false,
            arr:["active","line"],
            style:{
                width:"100px",
                height:"100px",
                backgroundColor:"green"
            },
            value:10
        },
        computed:{
            age:function(){
                return this.value + 12;
            }
            /*
            上面的計(jì)算屬性的真面目
            age:{
                set:function(value){
                    //this.value=value; 實(shí)際上我們會(huì)讓set空著,只是用get。
                },
                get:function(value){
                    return this.value + 12;
                }
            }
             */
        }
    })
</script>

computed和methods

也可以把計(jì)算屬性直接定義在methods里面,但是為什么要使用computed呢?

因?yàn)樵趍ethods里的function,每一次使用都會(huì)執(zhí)行。

但是多次調(diào)用computed里的計(jì)算屬性時(shí),他只執(zhí)行了一次后形成了緩存,如果value值不發(fā)生變化,后續(xù)都使用這個(gè)緩存。性能比methods好。

v-on

事件監(jiān)聽(tīng),當(dāng)用戶觸發(fā)事件時(shí)執(zhí)行特定的方法。

</body>
<div id="app">
    <button v-on:click="fn1()">v-on的使用</button>
    <button @click="fn2(2)">v-on可以簡(jiǎn)寫為@click,函數(shù)體還可以傳遞參數(shù)</button>
    <button @click="fn3(name)">以對(duì)象屬性作為參數(shù)</button>
    <button @click="fn4($event)">獲取事件對(duì)象用$event</button>
    <div @click="Div()">
        <p @click.stop="Button()">使用.stop修飾符取消事件冒泡</p>
    </div>
<form action="test.html">
    <input type="text" @keyup.enter="keyUp()">當(dāng)用戶使用鍵盤事件且點(diǎn)擊Enter時(shí)觸發(fā)事件<br/>
    <input type="submit" value="提交" @click.prevent="mySubmit()">使用.prevent修飾符阻止默認(rèn)事件
</form>
    <button @click.once="Once()">用戶第一次點(diǎn)擊時(shí)觸發(fā)</button>
</div>
</body>
<script>
    const app = new Vue({
        el:"#app",
        data:{
            name:"shabi"
        },
        methods:{
            fn1(){console.log(1);},
            fn2(a){console.log(a)},
            fn3(name){console.log(name);},
            fn4(e){console.log(e);},
            Div(){console.log("div")},
            Button(){console.log("button")},
            mySubmit(){console.log("submit")},
            keyUp(){console.log("key up!")},
            Once(){console.log(1)}
        }
    })
</script>

.prevent 阻止默認(rèn)行為,相當(dāng)于原生preventDefault

.stop 阻止冒泡傳播,相當(dāng)于stopPropergation

.once 當(dāng)前函數(shù)指回執(zhí)行一次

.self 只有點(diǎn)擊元素本身才會(huì)觸發(fā)這個(gè)函數(shù)

.capture 在捕獲階段執(zhí)行,相當(dāng)于ele.addEventListener('click',fn,==false==)

.passive 先執(zhí)行默認(rèn),后執(zhí)行此函數(shù)

v-if , v-else-if , v-else

條件判斷,使元素進(jìn)行顯示或者不顯示。

<body>
<div id="app">
    <div v-if="flag">
        <h4>if的值或條件判斷結(jié)果為true時(shí)顯示</h4>
    </div>
    <div v-else>當(dāng)v-if不顯示時(shí)顯示</div>
    ----------------------------------
    <div v-if="score>=90">優(yōu)秀</div>
    <div v-else-if="score>=80">良好</div>
    <div v-else-if="score>=60">及格</div>
    <div v-else>不及格</div>
</div>
</body>
<script>
    const app = new Vue({
        el:"#app",
        data:{
            flag:true,
            score:85
        },
    })
</script>

v-show

語(yǔ)法與v-if一樣。

但是不顯示時(shí),v-if的元素不存在于document上,v-show元素存在只是display=none。

v-if是對(duì)dom進(jìn)行增加和刪除,v-show是對(duì)dom進(jìn)行display=block/none;

v-model

Vue的核心特性之一是雙向綁定,vue的響應(yīng)式原理是實(shí)現(xiàn)了數(shù)據(jù)->視圖,接下來(lái)我們要學(xué)習(xí) 視圖->數(shù)據(jù)的原理。

v-model是一個(gè)指令,限制在<input>、<select>、<textarea>、components中使用。

<body>
<div id="app">
    <form action="#">
        <input type="text" v-model="name">v-model的使用,在表單元素上添加v-model,他的值為data里面的變量。</br>
        <h4>{{name}}</h4>輸入框文字變化,name的值動(dòng)態(tài)變化,即雙向綁定。</br>
        <input type="text" :value="name" @input="name = $event.target.value">雙向綁定原理</br>

        v-model的單選框radio使用:
        男<input type="radio" value="男" name="sex" v-model="sex">
        女<input type="radio" value="女" name="sex" v-model="sex"><br>

        v-model的多選框checkbox使用:
        蘋果 <input type="checkbox" value="蘋果" name="fruit" v-model="fruit">
        香蕉 <input type="checkbox" value="香蕉" name="fruit" v-model="fruit">
        西瓜 <input type="checkbox" value="西瓜" name="fruit" v-model="fruit">
        (使用數(shù)組接收)<br>

        v-model的下拉框select的使用:
        <select v-model="sport">
            <option value="唱">唱</option>
            <option value="跳">跳</option>
            <option value="rap">rap</option>
            <option value="籃球">籃球</option>
        </select>
    </form>
</div>
</body>
<script>
    const app = new Vue({
        el:"#app",
        data:{
            name:"小明",
            sex:'',
            fruit:[],
            sport:'rap'
        },
    })
</script>

v-model值綁定:使用單選,多選,下拉框的時(shí)候,不用再html上寫死,可以把可選項(xiàng)寫到data數(shù)組里面,再用v-for寫入到html中,是頁(yè)面更加靈活。

.lazy(取代 input 監(jiān)聽(tīng) change 事件),使得輸入框失去焦點(diǎn)時(shí)數(shù)據(jù)才更新。

.number(輸入字符串轉(zhuǎn)為有效的數(shù)字),輸入框的內(nèi)容都當(dāng)作字符串處理,這個(gè)可以讓他轉(zhuǎn)換為數(shù)字類型。

.trim(輸入首尾空格過(guò)濾),過(guò)濾內(nèi)容兩邊的空格。

Vue組件化

組件化是vue.js中的重要思想

  • 它提供一種抽象,讓我們可以開發(fā)出一個(gè)個(gè)獨(dú)立使用的小組件來(lái)構(gòu)造我們的應(yīng)用。
  • 任何的應(yīng)用都會(huì)被抽象成一棵組件樹。

注冊(cè)組件基本步驟

  • 創(chuàng)建組件構(gòu)造器
  • 注冊(cè)組件
  • 使用組件
<body>
<div id="app">
    <my-cpn></my-cpn><!--3、組件的使用-->
</div>
</body>
<script>
    // 1、創(chuàng)建組件構(gòu)造器對(duì)象
    const cpnC = Vue.extend({
        template:
    `<div>
        <h1>標(biāo)題</h1>
        <p>內(nèi)容1</p>
        <p>內(nèi)容2</p>
    </div>`
    })
    // 2、注冊(cè)組件
    Vue.component('my-cpn',cpnC);//參數(shù)為標(biāo)簽名,組件構(gòu)造器
</script>

全局組件和局部組件

全局組件

意味著可以在多個(gè)Vue實(shí)例中使用。上面那種方式就是全局組件的創(chuàng)建方式,把創(chuàng)建和注冊(cè)的步驟寫在實(shí)例的外面。

局部組件

在特定的Vue實(shí)例中使用。第二步注冊(cè)的是否在要使用的Vue實(shí)例的Components里面注冊(cè)局部組件。

const app = new Vue({
    el:"#app",
    data:{},
    components:{
        // 2、注冊(cè)局部組件  標(biāo)簽名:構(gòu)造器對(duì)象
        cpn:cpnC
    }
})

父組件和子組件

Vue實(shí)例也可以看作是最大的父組件,叫做root component,其他的組件都屬于他的子組件。

必須在Vue實(shí)例中注冊(cè)了才可以在HTML中使用。

組件注冊(cè)語(yǔ)法糖

// 省去Vue.extend創(chuàng)建組件對(duì)象,注冊(cè)組件時(shí)直接創(chuàng)建對(duì)象。
Vue.component('my-cpn',{
    template:
        `<div>
            <h1>標(biāo)題</h1> 
            <p>內(nèi)容1</p>
            <p>內(nèi)容2</p>
        </div>`
});
//使用<my-cpn></my-cpn>
//如果是局部組件就在component里面寫:
components:{
    Cpn:{
        template:
        `<div>
            <h1>標(biāo)題</h1>
            <p>內(nèi)容</p>
         </div>`
    }
}

組件模板抽離

使用script標(biāo)簽

把模板寫到script標(biāo)簽里面,type="text/x-template",通過(guò)id獲取。

<script type="text/x-template" id="cpn"></script>

使用template標(biāo)簽

把模板寫到template標(biāo)簽里面,通過(guò)id獲取。

<template id="cpn"></template>

組件的數(shù)據(jù)存放

組件內(nèi)部不能直接訪問(wèn)Vue實(shí)例里面的data,而在注冊(cè)組件時(shí),可以有自己的data、methods等。這個(gè)data不是一個(gè)對(duì)象類型而是一個(gè)函數(shù),并且需要return一個(gè)對(duì)象,這個(gè)對(duì)象才是組件真正能訪問(wèn)的數(shù)據(jù)。

<template id="cpn">
    <div>模板
        <h2>{{title}}</h2>
        <p>{{content}}</p>
    </div>
</template>

<script>
    Vue.component("cpn",{
        template: '#cpn',
        data(){
            //這是組件訪問(wèn)數(shù)據(jù)的地方。
            return{
                title:"這是一個(gè)標(biāo)題",
                content:"這是一段文字"
            }
        }
    })
</script>

為什么組件的data是一個(gè)函數(shù)?

因?yàn)楹瘮?shù)返回的時(shí)一個(gè)對(duì)象,每個(gè)組件訪問(wèn)data時(shí)都會(huì)返回唯一的一個(gè)對(duì)象,當(dāng)組件需要對(duì)數(shù)據(jù)進(jìn)行操作的時(shí)候,指揮操作自己的對(duì)象數(shù)據(jù),而不會(huì)影響到其他組件的數(shù)據(jù)。如果data時(shí)一個(gè)對(duì)象,那么每次操作數(shù)據(jù)時(shí)其他組件也會(huì)同步變化。

父子組件之間的通信

子組件不能直接訪問(wèn)父組件的數(shù)據(jù),所以需要父組件與子組件之間進(jìn)行通信。

  • props 父-->子
  • $emit 子-->父
父?jìng)髯?props

props可以是數(shù)組、對(duì)象、字符串、Boolean、Function等...

// props:["film"],可以寫成數(shù)組形式  
props:{//也可以寫成對(duì)象
    film:{
        type:Array,//類型
        required:true,//是否必須傳值
        default:'當(dāng)沒(méi)有傳值時(shí)默認(rèn)的值',
        default(){
            //也可以寫成函數(shù)形式
            return 0;
        }
    }
}

1、父組件定義一個(gè)屬性info,應(yīng)用子組件的標(biāo)簽雙向綁定或普通綁定自定義屬性:myinfo="info";

2、子組件的option寫一個(gè)props,里面有一個(gè)屬性叫myinfo的空對(duì)象用于接收數(shù)據(jù)

3、在子組件模板使用myinfo

props屬性校驗(yàn)

在子組件中進(jìn)行,即使驗(yàn)證失敗會(huì)有錯(cuò)誤提示,但是組件會(huì)正常渲染。

props: {
    data: {
        type: String,//type的類型是任意類型
        default: "defalutData",
                     //如果type類型是Array或Object,dafalut必須是一個(gè)函數(shù),他的返回值為默認(rèn)值
        require: true//聲明這個(gè)參數(shù)是否必須傳入
    }
}
子傳父 $emit

$emit用于觸發(fā)當(dāng)前實(shí)例上的事件,附加參數(shù)都會(huì)傳給監(jiān)聽(tīng)器回調(diào)。

使用:

原理:

1、子組件定義屬性categories,并且在組件某個(gè)地方觸發(fā)發(fā)送函數(shù)btnClick

2、btnClick通過(guò)this.$emit('my-event',this.categories)把自定義事件發(fā)送個(gè)事件池。

3、父組件在事件池中取出@my-event="myfn(a)"自定義事件和方法

4、myfn(a)通過(guò)接收的參數(shù)a獲取到emit過(guò)來(lái)的參數(shù)。

on:監(jiān)聽(tīng)當(dāng)前實(shí)例上的自定義事件。事件可以由 vm.emit 觸發(fā)?;卣{(diào)函數(shù)會(huì)接收所有傳入事件觸發(fā)函數(shù)的額外參數(shù)。

this.$on('my-event',(value)={
    console.log(value);
})

監(jiān)聽(tīng)自定義事件my-event,每當(dāng)觸發(fā)此事件后都會(huì)觸發(fā)$on。

父子組件的訪問(wèn)方式

父組件訪問(wèn)子組件children/refs

$children

methods:{
    btnClick(){
        console.log(this.$children.name);
        //this.$children保存組件的某些信息,可通過(guò)這個(gè)來(lái)訪問(wèn)組件的屬性
    }
}

可以在mounted或者函數(shù)里面打印this.$children,是一個(gè)數(shù)組,包含了所有組件的信息。

通常來(lái)說(shuō)我們不使用children,因?yàn)? mathimg=children是一個(gè)數(shù)組,里面存了全部組件對(duì)象,而且不是響應(yīng)式的。當(dāng)我們添加了組件時(shí),數(shù)組下標(biāo)就發(fā)生了變化,此時(shí)以前指定的組件就變了。

$refs

更好的方法

<div id="app">
    <tag ref="one"></tag>
    <tag ref="two"></tag>
    <!--在子組件上添加ref屬性-->
    <tag></tag>
    <button @click="btnClick">btn</button>
</div>
<script>
    //父組件的方法可以直接獲取到refs對(duì)象,包含了有ref屬性的所有組件
    methods:{
        btnClick(){
            this.$refs.one.showMessage();
            this.$refs.two.showMessage();
            //通過(guò)設(shè)置的ref精準(zhǔn)獲取到特定的組件
        }
    }
</script>

子組件標(biāo)簽上設(shè)置ref屬性,觸發(fā)事件就可以打印refs,通過(guò)refs.name就可以找到對(duì)應(yīng)的組件

子組件訪問(wèn)父組件$parent

$parent指代組件的上一層組件,不建議使用。

因?yàn)榻M件是可以復(fù)用的,當(dāng)復(fù)用的情況不一樣是會(huì)造成$parent指代不明。

<template id="temp">
    <div>
        <p>子組件</p>
        <button @click="btnClick">btn</button>
        <!--在組件內(nèi)部監(jiān)聽(tīng)事件-->
    </div>
</template>
<script>
    components:{
        tag:{
            template:"#temp",
                methods:{
                    btnClick(){
                        console.log(this.$parent.info)
                        //觸發(fā)事件時(shí)直接訪問(wèn)$parent,即直接訪問(wèn)上一層的組件。
                        console.log(this.$root)
                       //觸發(fā)事件時(shí)訪問(wèn)$root,即直接訪問(wèn)Vue實(shí)例。
                    }
                }
        }
    }
</script>

組件信息通訊EventBus

EventBus--事件總線--完全的發(fā)布訂閱模式。

原理:無(wú)論是父子組件還是兄弟組件或者不相關(guān)的組件,只要保證每個(gè)組件都可以獲取到這個(gè)==事件池==即可。

Slot插槽

組件的插槽讓組件具有更強(qiáng)的擴(kuò)展性,讓使用者決定組件內(nèi)部的展示。

基本使用<slot>

插槽定義在子組件,父組件使用子組件<son></son>時(shí),在中間使用標(biāo)簽就會(huì)代替掉子組件的插槽。中間不使用插槽則使用子組件的默認(rèn)標(biāo)簽。

具名插槽的使用

<div id="app">
    <tag>
        <span slot="title">這是標(biāo)題</span><!--通過(guò)slot名找到指定的spot-->
        <p slot="content">這是內(nèi)容</p><!--通過(guò)spot名找到指定的spot-->
    </tag>
</div>

<template id="temp">
    <div>
        <slot name="title"></slot>
        <p>子組件</p>
        <slot name="content"></slot>
    </div>
</template>

子組件定義插槽時(shí)給插槽加name,父組件使用插槽時(shí)給標(biāo)簽加上slot=name就會(huì)用上指定的插槽。

編譯作用域

<div id="app">
    <tag v-show="show"></tag><!--這個(gè)show使用的是Vue實(shí)例的show-->
</div>

<template id="temp">
    <div>
        <p v-show="show">子組件</p><!--這個(gè)show使用的是組件里面的show-->
    </div>
</template>

父組件模板的所有東西都會(huì)在父級(jí)作用域內(nèi)編譯;子組件模板的所有東西都會(huì)在子級(jí)作用域內(nèi)編譯。父子組件之間不能直接訪問(wèn)。

作用域插槽

當(dāng)我們需要對(duì)組件進(jìn)行數(shù)據(jù)自定義顯示的時(shí)候,可用到作用域插槽進(jìn)行自定義。

父組件替換插槽標(biāo)簽,但是內(nèi)容由子組件來(lái)提供。

<div id="app">
    <tag></tag><!--普通顯示-->
    <tag>
        <template slot-scope="slot"><!--利用template標(biāo)簽的slot-scope屬性獲取子組件的作用域?yàn)閟lot-->
        <span>{{slot.data.join(" - ")}}</span><!--slot.data即為子組件的data-->
    </template>
    </tag>
</div>

<template id="temp">
    <div>
        <slot :data="language"><!--自定義一個(gè)屬性并且存需要的數(shù)據(jù),以便于使用的時(shí)候獲取-->
            <ul>
                <li v-for="i in language">{{i}}</li>
            </ul>
        </slot>
    </div>
</template>

在子組件的插槽使用雙向綁定一個(gè)自定義屬性data="language"

父組件使用時(shí),要在外面包一層template標(biāo)簽,使用slot-scope="slot"屬性。

slot就代表著子組件的作用域。

作用域插槽不能使用具名插槽??

ES6-Modules

模塊化的兩個(gè)核心

導(dǎo)出和導(dǎo)入。

export

注意要使用import和export的script標(biāo)簽要加上type="module"

export let name="Hello";//導(dǎo)出一個(gè)變量

let width = 100;
let height =120;
export {
  width,height
}
//以對(duì)象形式導(dǎo)出一組變量

const Student = {
  name:"xiaoming",
  height:168,
  weight:90
}

export {Student}//導(dǎo)出一個(gè)對(duì)象
export {Student as stu}//還可以給對(duì)象起別名

export function run(){
  console.log("Run run run....");
}
//導(dǎo)出一個(gè)函數(shù)

export default function(){
  console.log(123)
}
//默認(rèn)導(dǎo)出,不需要給名字,讓接收者命名。且僅允許存在一個(gè)默認(rèn)導(dǎo)出。

import

import {name,Student,run} from './export.js';
/*導(dǎo)入變量。函數(shù),對(duì)象等(可一次導(dǎo)多個(gè)),都要用大括號(hào)把名字包裹住,名字要對(duì)應(yīng)上傳過(guò)來(lái)的變量名。*/

import fun from './export.js';
/*如果是default就不需要大括號(hào),這里的名字可隨便取。*/

import * as obj from './export.js';
/*把全部導(dǎo)出的東西存到obj對(duì)象里面。*/

webpack

何為webpack

從本質(zhì)上來(lái)講,webpack是一個(gè)js應(yīng)用靜態(tài)模塊打包工具。

webpack安裝

webpack依賴于node環(huán)境,node有各種各樣的依賴包,為了可以管理大量的依賴包,會(huì)一起安裝上npm管理工具,類似于Maven。(node packages manager)

下··

webpack起步

webpack配置

Vue CLI

CLI:command-Line Interface,翻譯為命令行界面,俗稱腳手架。

Vue CLI是一個(gè)官方發(fā)布的vue.js項(xiàng)目腳手架。

vue-cli可以快速創(chuàng)建Vue開發(fā)環(huán)境以及對(duì)應(yīng)的webpack配置。

Vue CLI使用前提:node.js

cli2創(chuàng)建方式:

vue init webpack projectname

運(yùn)行環(huán)境runtime-compiler和runtime-only

cli3創(chuàng)建方式:

vue create projectname 
//命令行進(jìn)行配置,選擇router和vuex,不用手動(dòng)配置
vue ui //或者通過(guò)圖形界面進(jìn)行配置,狹隘后還要手動(dòng)引入包和配置信息,煩

Vue-Router

認(rèn)識(shí)路由

vue-router基本使用

路由的初始化

(項(xiàng)目生成時(shí)已經(jīng)完成)

使用路由

1、創(chuàng)建路由組件

2、導(dǎo)入組件,配置路由映射

3、在Vue實(shí)例中掛載創(chuàng)建的路由實(shí)例

用代碼代替router-link

結(jié)果:

一些細(xì)節(jié)
{
  routes: [
    {
/*用于初始化時(shí)進(jìn)入的路徑,這里第一次進(jìn)入時(shí)默認(rèn)進(jìn)入\home*/
      path:'',
      redirect:'/home'
    }],
  mode:"history", /*改為history模式,去除哈希值‘#’*/
  linkActiveClass:'active' /*處于活躍狀態(tài)下的class*/
}

<router-link>的其他屬性:

router-link默認(rèn)渲染成a標(biāo)簽,使用tag="button"可以渲染成button。

讓router-link使用replaceState模式(不可返回),使用replace屬性。

標(biāo)簽活動(dòng)時(shí)(被點(diǎn)擊等等)會(huì)自動(dòng)生成兩個(gè)class,其中一個(gè)是router-link-active,可通過(guò)這個(gè)class給標(biāo)簽設(shè)置樣式,如果覺(jué)得此class過(guò)長(zhǎng)可以為此改名。active-class="active"

動(dòng)態(tài)路由的使用

路由的懶加載

一個(gè)項(xiàng)目最后被打包的時(shí)候最終是放在一個(gè)js文件中,全部頁(yè)面都放在一個(gè)js必然會(huì)很大,但我門第一次請(qǐng)求這個(gè)頁(yè)面時(shí)可能需要花費(fèi)一定的時(shí)間,甚至用戶界面還會(huì)出現(xiàn)短暫的空白。如要避免這種情況,使用懶加載把:不同的路由對(duì)應(yīng)的組件分割成不同的代碼塊,然后當(dāng)路由被將訪問(wèn)時(shí)才加載對(duì)應(yīng)組件,這樣就更加高效了。

<img src="C:\Users\admin\AppData\Roaming\Typora\typora-user-images\image-20200729095516035.png" alt="image-20200729095516035" style="zoom:67%;" />

使用懶加載:當(dāng)用戶使用組件時(shí)再import。

vue-router嵌套路由

實(shí)現(xiàn)路由嵌套有兩個(gè)步驟:

1、創(chuàng)建對(duì)應(yīng)子組件,并在路由映射中配置對(duì)應(yīng)的子路由。路徑不需要加 /

2、組件內(nèi)部使用router-view標(biāo)簽

vue-router參數(shù)傳遞

當(dāng)進(jìn)行路由跳轉(zhuǎn)時(shí),通常需要傳遞參數(shù),傳遞參數(shù)有兩種方式:

$route.params.value

傳遞一個(gè)參數(shù)時(shí)使用params

配置路由格式(動(dòng)態(tài)):/router/:id

傳遞方式:在path后面跟上對(duì)應(yīng)的值

傳遞后形成路徑:/router/123,/router/asd

$route.query.value

傳遞大量參數(shù)時(shí)使用query

配置路由格式:/router,普通配置

傳遞方式:雙向綁定路由to,綁定的值是個(gè)對(duì)象,包含url屬性和query屬性,query包含需要傳遞的參數(shù)。

傳遞后形成路徑:/router?id=123,/router?name=asd

通過(guò)$route.query.value獲取傳過(guò)來(lái)的屬性

用button實(shí)現(xiàn)query傳參
<button @click="toProfile">檔案</button>
<script>
toProfile(){
  this.$router.push(//使用query時(shí)push傳遞一個(gè)對(duì)象
    {
      path:'/profile',
      query:{       //query是一個(gè)對(duì)象
        name:"Goku",
        height:180,
        age:18
      }
  })
}
</script>

1、父組件主頁(yè)面設(shè)置事件

2、事件函數(shù)使用this.$route.push({}),對(duì)象有url和query屬性,query里面即為傳遞過(guò)去的參數(shù)。

3、子組件中的computed中使用this.$route.query.value獲取到值

4、頁(yè)面上使用計(jì)算屬性顯示值

route 和router

this.$router 是個(gè)路由導(dǎo)航對(duì)象,用它可以方便的使用JS代碼實(shí)現(xiàn)編程式路由導(dǎo)航,如頁(yè)面前進(jìn)、后退、跳轉(zhuǎn)等。

this.$route 是路由參數(shù)對(duì)象,路由中的所有參數(shù), params、query 都屬于它。

this.$router 用來(lái)發(fā)送。

this.$route用于接收信息。

vue-router導(dǎo)航守衛(wèi)

1、全局導(dǎo)航鉤子

分為前置守衛(wèi)(beforeEach)+ 后置鉤子(afterEach)

beforeEach:在在路由跳轉(zhuǎn)前觸發(fā),參數(shù)包括to,from,next(參數(shù)會(huì)單獨(dú)介紹)三個(gè),這個(gè)鉤子作用主要是用于登錄驗(yàn)證,也就是路由還沒(méi)跳轉(zhuǎn)提前告知,以免跳轉(zhuǎn)了再通知就為時(shí)已晚。

router.beforeEach((to,from,next)=>{
  document.title = to.matched[0].name;
  next();
})

afterEach和beforeEach相反,他是在路由跳轉(zhuǎn)完成后觸發(fā),參數(shù)包括to,from沒(méi)有了next。

單獨(dú)路由獨(dú)享鉤子
組件內(nèi)的鉤子

keep-alive

?????????

默認(rèn)情況下,一旦顯示了另一個(gè)組件,上一個(gè)被覆蓋的組件就會(huì)被銷毀,下次再顯示時(shí)再創(chuàng)建組件。使用keep-alive標(biāo)簽后組件不會(huì)頻繁地被創(chuàng)建和銷毀。

屬性:

exclude + name1,name2... 把此組件排除在外,它們會(huì)被創(chuàng)建和消除。

include + name1,name2... 包括這些組件,他們不會(huì)被創(chuàng)建和消除。

Vuex

Vuex簡(jiǎn)單介紹

Vuex是一個(gè)專為Vue.js應(yīng)用開發(fā)的狀態(tài)管理模式,Vuex是一個(gè)狀態(tài)管理工具。

它采用集中式儲(chǔ)存管理應(yīng)用的所有組件的狀態(tài),并以相應(yīng)規(guī)則保證狀態(tài)可預(yù)測(cè)的方式發(fā)生變化。簡(jiǎn)單來(lái)說(shuō)就是把多個(gè)組件共享的數(shù)據(jù)儲(chǔ)存在一個(gè)對(duì)象里面,然后把這個(gè)對(duì)象放在Vue實(shí)例中讓其他組件可以共同使用。Vuex還實(shí)現(xiàn)了響應(yīng)式,多個(gè)組件間公用一個(gè)狀態(tài)。

什么時(shí)候需要共享一個(gè)狀態(tài)?

  • 用戶登錄狀態(tài),用戶名稱,頭像等
  • 商品的收藏
  • 購(gòu)物車的商品

單頁(yè)面狀態(tài)管理

state改變引起actions改變,用戶事件(在view上)可以引起狀態(tài)改變。

多頁(yè)面狀態(tài)管理

使用VueX

vuex-devtools 和 mutations

vuex-devtools時(shí)一個(gè)瀏覽器插件,方便調(diào)試vue程序。

mutations是vuex中作為修改狀態(tài)的東西,下面會(huì)詳細(xì)介紹。

Vuex的核心概念

state

用于存放狀態(tài)信息。

單一狀態(tài)樹:也叫單一數(shù)據(jù)源。即只用一個(gè)state。

Vuex可實(shí)現(xiàn)響應(yīng)式數(shù)據(jù),但是要遵循一些條件:

  1. 提前在store中初始化所需的數(shù)據(jù)
  2. 給state對(duì)象添加新屬性是使用以下方式
    • Vue.set(obj,"proper","value")
    • 用新對(duì)象給舊對(duì)象賦值

任何頁(yè)面都可以使用$store訪問(wèn)store里面的屬性。

?

getters

相當(dāng)于計(jì)算屬性 ,當(dāng)需要使用經(jīng)過(guò)變化的state數(shù)據(jù)時(shí)使用。

區(qū)別:里面的函數(shù)有兩個(gè)默認(rèn)的形參,第一個(gè)是state,第二個(gè)是getters,不接受其他的參數(shù)。

不接受其他函數(shù),如果需要傳參數(shù),需要在里面return一個(gè)函數(shù)。

getters:{
    fun(state){
      return function (age) {
        return state.students.filter(s=>s.age > age)//返回年齡大于參數(shù)age的學(xué)生 對(duì)象
      }
    }//下圖使用
}

使用的時(shí)候是$store.getters.fun

mutations

mutations,突變,轉(zhuǎn)變,改變

state唯一的更新方式時(shí)通過(guò)mutations。

mutations必須是同步方法,因?yàn)閐evtools可幫我們捕捉mutation的快照,如果是異步方法devtools無(wú)法捕捉。

mutations可分成兩部分:

  • type事件類型
  • handler回調(diào)函數(shù),該回調(diào)函數(shù)的第一個(gè)參數(shù)是state
傳參:(參數(shù)也可以是對(duì)象)

1、綁定事件,在事件函數(shù)里面使用this.$store.commit('type',value);這種方法只能發(fā)一個(gè)參數(shù)。
2、type是store里面mutations里面的函數(shù)名

3、mutations對(duì)應(yīng)上的函數(shù)第一個(gè)參數(shù)是state(固定),第二個(gè)可以自定義形參用于接收數(shù)據(jù)

4、在mutations里面操作state數(shù)據(jù)。

另一種提交風(fēng)格
mutations的類型常量

action

在vuex中想要進(jìn)行異步操作,可以用action來(lái)取代mutations。action類似于mutation,只是它主要用于進(jìn)行異步請(qǐng)求(網(wǎng)絡(luò)請(qǐng)求)。

ps.初學(xué)階段好像在mutation上異步也沒(méi)啥影響。。。所以action...暫時(shí)沒(méi)啥作用....

module

當(dāng)項(xiàng)目越來(lái)越大的時(shí)候,state顯得越來(lái)越臃腫,但是又提倡使用單一狀態(tài)樹,所以使用module解決。

分模塊。

modules:{
  a:{
    state:{},
    mutations:{},
    actions:{},
    getters:{}
  },
  b:{
    state:{},
    mutations:{},
    actions:{},
    getters:{}
  }
}

???

?著作權(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)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

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

  • 一、什么是Vue.js 1. vue是一種數(shù)據(jù)驅(qū)動(dòng)的前端框架 this.msg="我愛(ài)你",通過(guò)改變數(shù)據(jù),然后自動(dòng)...
    在路上919閱讀 1,681評(píng)論 0 2
  • 一、了解Vue.js 1.1.1 Vue.js是什么? 簡(jiǎn)單小巧、漸進(jìn)式、功能強(qiáng)大的技術(shù)棧 1.1.2 為什么學(xué)習(xí)...
    蔡華鵬閱讀 3,495評(píng)論 0 3
  • 動(dòng)態(tài)綁定class : class:[ name?success:error,name?success:error...
    游_弋閱讀 304評(píng)論 0 2
  • Vue不支持IE8以及以下版本。 想要使用Vue的話可以通過(guò)直接下載vue.js,放置到項(xiàng)目中寫好路徑就可以,或者...
    酥楓閱讀 719評(píng)論 0 0
  • 漸變的面目拼圖要我怎么拼? 我是疲乏了還是投降了? 不是不允許自己墜落, 我沒(méi)有滴水不進(jìn)的保護(hù)膜。 就是害怕變得面...
    悶熱當(dāng)乘涼閱讀 4,469評(píng)論 0 13

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