個人Vue學習筆記(一)

個人Vue學習筆記css

MVVM思想

MVVM是Model-View-ViewModel的簡寫,即:模型-視圖-視圖模型.
模型是指後端傳遞的數據
視圖是指咱們看到的頁面
視圖模型則是MVVM思想的核心部分,它連接了View和Model並做爲它們之間通訊的橋樑,它有兩個方向:一是將Model轉化爲View,即後端傳遞的數據轉化成看到的頁面,二則是將View轉化爲Model,也就是將用戶操做在頁面上的內容轉化爲後端的數據,這兩個功能是經過數據綁定以及DOM事件監聽來實現的,咱們稱之爲數據的雙向綁定。如圖所示:
html


總的來講:視圖層與模型層經過ViewModel進行通訊,當數據發生變化時,ViewModel可以監聽到數據的這種變化,而後經過通知對應的視圖層更新頁面;當用戶操做視圖層,ViewModel也可以監聽到視圖的變化,而後通知數據作改動,這就是MVVM思想,而Vue.js 則使用了MVVM的思想搭建出了既輕量級又開發高效快速且功能強大的框架。

建立實例,數據綁定,指令和事件

建立實例

vue 建立實例的方法以下:vue

<div id="app">
        {{myData}}
    </div>
    <script>
        var vueApp = new Vue({
            el:'#app',
            data:{
                myData:'Hello World'
                myData2:'Fuck World'
            }
        });
    </script>
複製代碼

代碼中 el 和 data 都是vue實例的屬性,el 用於指定頁面當中已存在的用來掛載Vue實例的DOM元素,data則是Vue須要雙向綁定的數據。後端

數據綁定

當掛載後,咱們可使用 vue實例.$vue實例的屬性這樣的語法來獲取vue實例的屬性,例如: vueApp.$el,訪問data中的屬性則不一樣,咱們能夠直接使用vue實例.data的屬性名這樣的語法來訪問,例如:vueApp.myData數組

生命週期鉤子

vue生命週期鉤子是在Vue對象生命週期的某一個階段執行的已定義的方法。從初始化vue實例對象,到它被銷燬,對象會遵循不一樣的生命階段,具體內容我截了一張很著名的生命週期鉤子圖:
瀏覽器


具體爲:

  1. beforeCreate : 建立vue實例前的鉤子函數
  2. created : 建立好了vue實例,可是還沒有掛載到頁面的DOM元素上
  3. beforeMount : 開始掛載
  4. mounted : 將編譯好的html掛載到頁面上 且 mounted在整個生命週期只執行一次
  5. beforeUpdate
  6. updated
  7. beforeDestroy : vue實例銷燬以前執行的鉤子函數
  8. 實例銷燬時執行的鉤子函數

vue生命週期有不少階段,可是咱們最經常使用到的是這三個階段:緩存

  1. created
  2. mounted
  3. beforeDestroy

舉例說明:bash

var vueApp = new Vue({
        el:'#app',
        data:{
            myData:'Hello World'
        },
        created:function () {
            alert('vue實例建立完畢了,可是尚未掛載到DOM元素上');
        },
        mounted:function () {
            alert('vue實例已經掛載到DOM上了');
        }
    });
複製代碼

對於上述示例頁面來講,打開瀏覽器,首先會彈出"vue實例建立完畢了,可是尚未掛載到DOM元素上"這樣的提示信息,對於created 這個階段來講,實際上已經完成了vue實例的建立,可是並無掛載至DOM元素上,而後會彈出「vue實例已經掛載到DOM上了」的提示框,mounted階段是vue建立的實例掛載到DOM後進行調用的,咱們的第一個業務邏輯也一般會在這裏開始,對於beforeDestory 階段,經過字眼意思也能夠知道 這是vue實例銷燬前的階段,經過會在這個階段進行解綁一些監聽事件。app

文本插值

對於本示例來說,咱們會在頁面上看到Hello World 的字樣,在html中,咱們書寫了這樣的語法:框架

<div id="app">
    {{myData}}
</div>
複製代碼

這種語法就是Vue的文本插值語法,它支持單個表達式,注意只是單個表達式:

{{1<0 ? myData:myData2}}
這是三元運算符表達式,由於它屬於單個表達式
因此這是合法的,咱們會在頁面上看到Fuck World
{{var a = 6}}
注意:這是非法的
var a = 6 是一個聲明表達式 + 一個賦值表達式
咱們提到過 Vue 的文本插值語法只支持單個表達式
因此 這句話會報錯
複製代碼

過濾器

vue.js 支持在{{}}插值的尾部添加一小管道符" | "對數據進行過濾,常常用於格式化文本,好比字母所有大寫、貨幣千位使用逗號分隔等,同時也支持過濾器串聯寫法,傳參等等。咱們來看一個示例:
頁面實時顯示當前時間:

<div id="app">
        {{currentDate | format}}
    </div>
    <script>
        function formatTime(value) {
            return value <10 ? '0'+value : value;
        }
        var vueApp = new Vue({
            el:'#app',
            data:{
                currentDate: new Date()
            },
            filters:{
                format:function (currentDate) {
                    var date = new Date(currentDate);
                    var year = date.getFullYear(); // 獲取當前年
                    var month = formatTime(date.getMonth()+1); // 獲取當前月(須要+1)
                    var days = formatTime(date.getDate()); // 獲取當前天
                    var hours = formatTime(date.getHours()); // 獲取當前小時
                    var minutes = formatTime(date.getMinutes()); // 獲取當前分鐘
                    var seconds = formatTime(date.getSeconds()); // 獲取當前秒

                    return '當前時間爲:'+year+'年'+month+'月'+days+'日'+hours+'時'+minutes+'分'+seconds+'秒'
                }
            },
            mounted:function () {
                this.timer = setInterval(()=>{
                    this.currentDate = new Date();
                },1000)
            },
            beforeDestroy:function () {
                window.clearInterval(this.timer);
            }
        });
    </script>
複製代碼

咱們還能夠對過濾器進行傳參,咱們將代碼作一個小小的改動:

<div id="app">
        {{currentDate | format('當前時間爲',':')}}
    </div>
    <script>
        function formatTime(value) {
            return value <10 ? '0'+value : value;
        }
        var vueApp = new Vue({
            el:'#app',
            data:{
                currentDate: new Date()
            },
            filters:{
                format:function (currentDate,arg1,arg2) {
                    var date = new Date(currentDate);
                    var year = date.getFullYear(); // 獲取當前年
                    var month = formatTime(date.getMonth()+1); // 獲取當前月(須要+1)
                    var days = formatTime(date.getDate()); // 獲取當前天
                    var hours = formatTime(date.getHours()); // 獲取當前小時
                    var minutes = formatTime(date.getMinutes()); // 獲取當前分鐘
                    var seconds = formatTime(date.getSeconds()); // 獲取當前秒

                    return arg1+arg2+year+'年'+month+'月'+days+'日'+hours+'時'+minutes+'分'+seconds+'秒'
                }
            },
            mounted:function () {
                this.timer = setInterval(()=>{
                    this.currentDate = new Date();
                },1000)
            },
            beforeDestroy:function () {
                window.clearInterval(this.timer);
            }
        });
    </script>
複製代碼

咱們在過濾器中加入了參數,獲得了和以前同樣的結果。這裏面須要注意的是:過濾器對應的函數中第一個傳入的值是 「 | 」 前的data中的屬性值,在本例中即:currentDate ,而並不是是參數,傳入的參數是在函數的第二個傳遞值及之後的值。同時過濾器也可使用"串聯寫法" ,如:{{currentDate | filter1 | filter2 | filter3 }} ,過濾器的方法會依次執行,而且它們都被定義在 vue的屬性 filters 當中。

指令和事件

支持指令操做是vue框架的優勢之一,它是vue模板中最經常使用的一項功能,省去了複雜的DOM API,而且及其方便記憶和理解。接下來咱們先簡單瞭解一些指令操做:

  1. v-text

    v-text 的功能是解析文本 它的具體做用和文本插值{{}}是一毛同樣的

  2. v-html

    將內容解析成html

  3. v-bind

    動態更新HTML上的元素,例如id,class等等

  4. v-on

    用來綁定事件監聽

接下來咱們依舊經過示例,來簡單認識這幾個指令事件。

<style>
        .active{
            background: red;
            height: 1em;
        }
    </style>
---------------------------------------------------------------
    <div id="app">
        v-text: <br>
        {{apple}} <br>
        <!--v-text 的做用和文本插值 是同樣的-->
        <span v-text="apple"></span>
        v-html: <br>
        <span v-html="banana"></span> <br>
        v-bind: <br>
        <div v-bind:class="className"></div>
        v-bind的簡寫格式: <br>
        <div :class="className"></div>
        v-on: <br>
        <button v-on:click="plusOne">{{originalNum}}</button>
        <br>
        v-on的簡寫格式: <br>
        <button @click="plusOne">{{originalNum}}</button>
    </div>
    <script>
        var app = new Vue({
            el:'#app',
            data:{
                apple:'蘋果',
                banana:'<span style="color: yellow;">香蕉</span>',
                className:'active',
                originalNum:0
            },
            methods:{
                plusOne:function () {
                    this.originalNum = this.originalNum + 1;
                }
            }
        });
    </script>
複製代碼

部分html內容如上,對於 v-bind 和 v-on 兩個指令 都有響應的簡寫格式,如示例中:

<div v-bind:class="className"></div>
能夠簡寫爲:
<div :class="className"></div>


<button v-on:click="plusOne">{{originalNum}}</button>
能夠簡寫爲:
<button @click="plusOne">{{originalNum}}</button>

複製代碼

計算屬性

先看一個示例:咱們要實現一個功能 反轉字符串,對於字符串 '123,456,789' 咱們要將字符串變爲: '321,654,987' ,示例程序以下:

<div id="app">
    {{text.split(',').map((e)=>{return e.split('').reverse().join('')}).join(',')}}
</div>
<script>
    var app = new Vue({
        el:'#app',
        data:{
            text:'123,456,789'
        }
    });
</script>
複製代碼

咱們看到這個程序內心必定一句媽賣批,程序雖然沒有什麼問題,也符合文本插值的語法,可是看起來就是以爲很頭疼,而且這樣寫的代碼也很差進行維護。咱們能夠將內容作一個優化,建立一個函數並將函數放在methods屬性當中:

<div id="app">
    <!--將'123,456,789' 這串字符串 變爲 '321,654,987'-->
    使人頭痛的代碼: <br>
    {{text.split(',').map((e)=>{return e.split('').reverse().join('')}).join(',')}} <br>
    methods屬性內的方法: <br>
    {{reverseMethod()}} <br>
</div>
<script>
    var app = new Vue({
        el:'#app',
        data:{
            text:'123,456,789'
        },
        methods:{
          reverseMethod:function () {
              // ['123',456,'789']
              return this.text.split(',').map((e)=>{
                  return e.split('').reverse().join('');
              }).join(',');
          }
        }
    });
</script>
複製代碼

除了將方法定義在methods中並調用,咱們還可使用計算屬性:

<div id="app">
    <!--將'123,456,789' 這串字符串 變爲 '321,654,987'-->
    使人頭痛的代碼: <br>
    {{text.split(',').map((e)=>{return e.split('').reverse().join('')}).join(',')}} <br>
    methods屬性內的方法: <br>
    {{reverseMethod()}} <br>
    計算屬性: <br>
    {{reverseText}}
</div>
<script>
    var app = new Vue({
        el:'#app',
        data:{
            text:'123,456,789'
        },
        methods:{
          reverseMethod:function () {
              // ['123',456,'789']
              return this.text.split(',').map((e)=>{
                  return e.split('').reverse().join('');
              }).join(',');
          }
        },
        computed:{
            reverseText:function () {
                return this.text.split(',').map((e)=>{
                    return e.split('').reverse().join('')
                }).join(',');
            }
        }
    });
</script>
複製代碼

咱們將方法定義在了 vue示例的computed 屬性當中,乍一看 和 methods並無什麼區別,實際上 計算屬性能夠實現的東西 在methods方法中 均可以實現 ,可是兩者也是有差異的。具體的差異,咱們在看完另外一個示例後,再來介紹:
本示例的功能是對購物車的價格總和進行計算,具體代碼以下:

<div id="app">
    {{prices}}
</div>
<script>
    var app2 = new Vue({
        el:'#app2',
        data:{
            msg:'兩個購物車的價格總和爲:'
        }
    });
    var app = new Vue({
       el:'#app',
       data:{
           // 購物車1
           package1:[
               {
                   name:'iphone',
                   price:6999,
                   count:2
               },
               {
                 name:'ipad',
                 price:3299,
                 count:2
               }
           ],
           // 購物車 2
            package2:[
                {
                    name:'XiaoMi',
                    price:999,
                    count:6
                },
                {
                    name:'ipod',
                    price:1099,
                    count:2
                }
            ]
       },
       computed:{
           prices:{
               get:function () {
                   var prices = 0;
                   //  第一個購物車的價格總和
                   for(var i = 0;i<this.package1.length;i++){
                       prices += this.package1[i].price * this.package1[i].count;
                   }

                   // 第一個購物車與第二個購物車的價格總和
                   for(var j = 0; j<this.package2.length;j++){
                       prices += this.package2[j].price * this.package2[j].count;
                   }

                   return app2.msg+prices;
               },
               set:function (options) {
                   if(options.package === 'package1'){
                       for(var i = 0;i<this.package1.length;i++){
                           if(this.package1[i].name === options.name){
                               this.package1[i].price = options.price;
                               this.package1[i].count = options.count;
                               break;
                           }
                       }
                   }else if(options.package === 'package2'){
                       for(var i = 0;i<this.package2.length;i++){
                           if(this.package2[i].name === options.name){
                               this.package2[i].price = options.price;
                               this.package2[i].count = options.count;
                               break;
                           }
                       }
                   }
               }
           }
       }
    });
</script>
複製代碼

每個計算屬性都有一個getter和 setter方法,當咱們僅僅是調用了計算屬性的方法名時,實際上調用的是 該屬性的get 方法,當有必要設置一些參數時,咱們也能夠提供一個 set方法手動修改計算屬性。另外在本示例中,咱們能夠看到 計算屬性 prices不只依賴了當前vue對象 並且也依賴了其餘的實例,儘管 app2 並無掛載到DOM上,可是執行的結果代表 計算屬性能夠依賴於其餘的實例。 代碼執行的結果以下:


咱們能夠經過set方法設置須要改動的參數:


當修改完畢後,頁面會實時更新數據:


咱們回過頭談論下methods 裏的方法 和 計算屬性有什麼不一樣之處:

計算屬性與methods方法

咱們首先來看一個示例:

<div id="app">
    {{text}} <br>
    {{getNow()}} <br>
    {{now}} <br>

</div>
<script>
    var app = new Vue({
        el:'#app',
        data:{
            text:666
        },
        methods:{
            getNow:function () {
                return Date.now();
            }
        },
        computed:{
            now:{
                get:function () {
                    return Date.now(); // 獲取 1970年 至如今的時間戳
                }
            }
        }
    });
</script>
複製代碼

咱們在 methods 方法以及 計算屬性中都定義了獲取 1970年到如今爲止的時間戳的函數 ,代碼運行的結果以下:


如今,我對text的內容作一個小小的更改:


咱們在更改了text的數據後,頁面天然會發生改動,可是咱們發現:
不只僅是text的內容發生了變更,methods 的 getNow方法在頁面上渲染出的html也發生了變更:


爲何會這樣呢?這裏面就涉及到了計算屬性的緩存。對於調用方法而言,只要是頁面從新渲染,那麼方法就會執行,注意我提到的是隻要頁面從新渲染,若是沒有渲染的話,方法是不會自動執行的,而計算屬性則不一樣,不管頁面是否發生渲染,只要計算屬性依賴的數據沒有發生變化,那麼就永遠不會變。計算屬性和methods方法的區別就是二者依賴的東西是不一樣的,計算屬性是基於它依賴的數據進行緩存的,當它依賴的數據產生變化時,它纔會變,而methods不存在緩存,當頁面發生了從新的渲染,方法就會執行。在上文中,提到過計算屬性能實現的東西methods方法均可以實現,那麼對於兩者該如何取捨使用呢? 其實仔細想一想也能想出結果,當咱們須要進行大量計算時,由於數據的計算耗費內存,咱們須要對數據進行緩存,那麼就應該使用計算屬性。

v-bind 的class與style綁定

v-bind 的做用只用一句話就能夠描述,那就是綁定活的屬性,咱們經過一個簡單的示例來回顧一下:

<div id="app">
    <a v-bind:href="url">連接</a>
</div>
<script>
    var app = new Vue({
        el:'#app',
        data:{
            url:'http://www.baidu.com'
        }
    });
</script>
複製代碼

頁面點擊鏈接後則會跳轉到baidu。

v-bind 的 class綁定

v-bind綁定 class 對象語法

見示例:

<style>
        .red{
            background: red;
        }
        .blue{
            background: blue;
        }
    </style>
--------------------------------------------------
<div id="app">
    v-bind綁定對象: 對象的key是類名,對象的value是布爾值<br>
    <button v-bind:class="{red:isRed,blue:isBlue}" v-on:click="transColor">clickMe</button>
</div>
<script>
    var app = new Vue({
        el:'#app',
        data:{
            isRed:true,
            isBlue:false,
        },
        methods:{
            transColor:function () {
                this.isRed = !this.isRed;
                this.isBlue = !this.isBlue;
            }
        }
    });
</script>
複製代碼

本示例實現的功能是一個按下去能轉換顏色的按鈕,同時v-bind:class使用的是對象語法,對象的key爲 類名 對象的value則是布爾值,若是值爲true則綁定這個類名,若是值爲false則和此類名無關聯。

v-bind綁定計算屬性語法

見示例:

<style>
        .red{
            width: 100px;
            height: 100px;
            background: red;
        }
    </style>
-----------------------------------------------
<div id="app">
    v-bind綁定計算屬性: 計算屬性返回的也是對象 key爲類名 ; value爲 布爾值 <br>
    <div v-bind:class="computedClass"></div>
</div>
<script>
    var app = new Vue({
        el:'#app',
        data:{
            isRed:true,
        },
        computed:{
            computedClass:function () {
                return {
                    red:'isRed'
                }
            }
        }
    });
</script>
複製代碼

示例中 v-bind:class綁定了計算屬性,可是即使爲計算屬性,返回的結果也是對象,對象中key爲類名,value爲布爾值,同上 當value值爲真時,元素攜帶這個類,當value值爲false時,元素則不攜帶這個類

v-bind綁定class數組語法

見示例:

<style>
        .first{
            font-size: 32px;
            color: red;
        }
        .second{
            background: #000;
        }
    </style>
---------------------------------------
<div id="app">
    綁定class數組語法:數組中的成員爲data中的屬性,這些屬性直接對應類名 <br>
    <div v-bind:class="[classOne,classTwo]">VUE is cool!</div>
</div>
<script>
    var app = new Vue({
        el:'#app',
        data:{
            classOne:'first',
            classTwo:'second'
        }
    });
</script>
複製代碼

v-bind綁定class數組的語法相比於前面而言更加簡單,數組中的成員爲data中的屬性,這些屬性直接對應類名,經過示例應該不難看懂~

v-bind綁定內聯樣式

除了綁定class較爲經常使用,v-bind也能夠綁定內聯樣式

<div id="app">
    綁定內聯樣式:對象語法,key 表明style的屬性,value表明屬性對應的值 br>
    <div v-bind:style="{'color':color,'fontSize':fontSize}">VUE is cool!</div>
</div>
<script>
    var app = new Vue({
        el:'#app',
        data:{
            color:'red',
            fontSize:'32px'
        }
    });
</script>
複製代碼

除了這種對象語法以外,綁定內聯樣式也支持"數組"語法,可是聽說這種語法比較蠢,由於誰也不會把樣式分開寫,因此我就不在這裏列出來了。須要注意的是 css屬性名稱 使用駝峯命名,或者是短橫線分隔命名,可是這裏面仍是推薦駝峯式寫法~~~~

相關文章
相關標籤/搜索