Vue入門--基礎語法

注:本教程所使用的vue版本爲 2.5.16
MVC與MVVM

MVC(Model-View-Controller):javascript

M指的是從後臺獲取到的數據, 
V指的是顯示動態數據的html頁面,
C是指響應用戶操做、通過業務邏輯處理後去更新視圖的過程,在此過程當中會致使對view層的引用。

這裏咱們發現咱們網站的大量代碼都被放在Controller,致使Controller代碼臃腫;並且不利於單元測試,由於業務邏輯處理和視圖更新操做會混雜在一塊兒。css

MVVM (Model-View-ViewModel):
MVVM是MVC的一個衍生模型,這裏的 ViewModel 把業務邏輯處理、用戶輸入驗證等跟視圖更新操做分離開了。MVVM是數據驅動的,咱們只須要關心數據的處理邏輯便可,它會經過模板渲染去單獨處理視圖的更新而不須要咱們親自去操做Dom元素。html

實例化Vue對象
<div id="app">
</div>

<script src="js/vue.min.js"></script>
<script>
    //調用Vue的構造函數建立實例對象
    var vm = new Vue({
        //根節點選擇器
        el: '#app',
        //數據對象
        data: {
            message: 'hello world',
        },
        //渲染模板
        template: '<div>message: {{ message }}</div>'
    })
</script>

Vue會將渲染模板結合數據對象生成的html結構替換掉根節點,只要數據對象上的message發生改變,插值處的內容就會跟着改變,上述例子的實際效果以下:vue

<body>
    <div>message: hello world</div>
</body>
模板語法

上面的雙大括號綁定是vue最經常使用的數據綁定方式,除了雙大括號還可使用v-text屬性進行綁定java

<div>message: <span v-text="message"></span></div>

若是要綁定html結構的話,須要使用到v-html指令,不然vue會把這段html代碼當作字符串直接綁定到對應位置數組

new Vue({
    el: '#app',
    data:{
        message: 'hello world',
        html: '<span>hello world</span>'
    },
    template: '<div>message: <span v-html="html"></span></div>'
})

須要綁定html元素特性的時候須要使用v-bind指令,v-bind能夠省略app

<div v-bind:id="id"></div>
<div :id="id"></div>

雙大括號的插值方法還可使用js表達式,這些表達式會在所屬 Vue 實例的數據做用域下被解析dom

{{ number + 1 }}

{{ boolean ? 'true' : 'false' }}

{{ message.split('').reverse().join('') }}

<div :id="'is' + id"></div>

注意,這裏的javascript語句只能是單個表達式,其餘的聲明變量、流程控制語法都不會生效函數

事件綁定

除了數據綁定外,vue還幫咱們優化了事件綁定流程,指令爲v-on,可縮寫爲@,後面是事件名稱單元測試

<a v-on:click="console.log(1)">打印1</a>

<a @click="console.log(1)">打印1</a>

僅僅一句js表達式是不夠支撐咱們的平常開發的,因此vue給咱們提供了自定義事件處理方法

new Vue({
    el: '#app',
    data: {
        message: 'hello world'
    },
    //log爲methods中定義的函數名,vue會默認把原生DOM事件對象當作參數傳處處理函數中
    template: '<a @click="log">Click Me</a>',
    methods: {
        log: function(event){
            console.log(this.message);
            event.stopPropagation();
        }
    }
});

除了直接綁定到一個方法,也能夠在內聯 JavaScript 語句中調用方法

<!-- 使用內聯語法後,原生DOM對象須要手動傳入(變量名變動爲 $event ) -->
<a @click="log(1, $event)">Click Me</a>
計算屬性 computed

模板內的表達式很是便利,可是設計它們的初衷是用於簡單運算的。在模板中放入太多的邏輯會讓模板太重且難以維護。例如這個字符串反轉:

<div>{{ message.split('').reverse().join('') }}</div>

這種狀況咱們能夠用 computed 解決

new Vue({
    el: '#app',
    data: {
        message: 'hello'
    },
    template: '<div>{{ reversedMessage }}</div>', //olleh
    computed: {
        reversedMessage: function(){
            return this.message.split('').reverse().join('');
        }
    }
});

這裏看渲染模板就直觀多了

監聽屬性 watch

Vue 提供了 watch 這種通用的方式來觀察和響應 Vue 實例上的數據變更

<div id="app">
    <p>問題: <input v-model="question"></p>
    <p>{{ answer }}</p>
</div>

<script src="js/vue.min.js"></script>
<script>
    var vm = new Vue({
        el: '#app',
        data: {
            question: '',
            answer: '請先輸入問題',
            timer: undefined,
        },
        watch: {
            question: function(newVal, oldVal){
                if(this.timer){ clearTimeout(this.timer); }
                var _this = this;
                this.answer = '等待中止輸入...';
                setTimeout(function(){ _this.answer = 'Yes!!!'; }, 1000);
            }
        }
    });
</script>
表單綁定,指令爲 v-model

v-model 指令在表單 <input> 及 <textarea> 元素上建立雙向數據綁定。它會根據控件類型自動選取正確的方法來更新元素。v-model 會忽略全部表單元素的 value、checked、selected 特性的初始值而老是將 Vue 實例的數據做爲數據來源。

<div id="app">
    <input v-model="message" placeholder="寫點什麼。。">
    <!-- 經過v-model綁定message後,
        在input輸入的文字會實時更新到數據對象上,
        從而自動渲染在下面的p標籤上
    -->
    <p>Message: {{ message }}</p>
</div>

<script src="js/vue.min.js"></script>
<script>
    var vm = new Vue({
        el: '#app',
        data: {
            message: ''
        }
    })
</script>

單個複選框

<input type="checkbox" id="checkbox" v-model="checked">
<label for="checkbox">{{ checked }}</label>

data: { checked: true }

多個複選框的狀況下,把v-model綁定到同一個數組便可:

<input type="checkbox" value="blue" id="blue" v-model="checkedColor"/>
<label for="blue">blue</label>
<input type="checkbox" value="red" id="red" v-model="checkedColor"/>
<label for="red">red</label>

data: { checkedColor: [] }

單選按鈕

<input type="checkbox" value="true" id="true" v-model="checkedRadio"/>
<label for="true">true</label>
<input type="checkbox" value="false" id="false" v-model="checkedRadio"/>
<label for="false">false</label>

data: { checkedRadio: '' }
條件渲染

在javascript語法中有if-else等流程語句讓程序執行不一樣的代碼塊,在vue中一樣有 v-ifv-else-ifv-else 這些指令控制某些節點的顯示與否

<div id="app">
    <div v-if="isShow">
        <label>用戶名</label>
        <input type="text" placeholder="請輸入用戶名" />
    </div>
    <!-- v-else 元素必須緊跟在帶 v-if 或者 v-else-if 的元素的後面,不然它將不會被識別。 -->
    <div v-else>
        <label>郵箱</label>
        <input type="text" placeholder="請輸入郵箱" />
    </div>
    <button @click="switchDom">切換輸入框類型</button>
</div>

<script src="js/vue.min.js"></script>
<script>
    var vm = new Vue({
        el: '#app',
        data: { isShow: true },
        methods: {
            switchDom: function(){ this.isShow = !this.isShow; }
        }
    })
</script>

在上述例子中,咱們點擊 button 會顯示不一樣的dom,可是若是咱們在input裏面輸入文字再進行切換的時候會發現,輸入的文字並不會被清除,這是由於vue的 就地複用 策略致使的。vue爲了儘量高效地渲染dom元素,一般會複用已有元素而不是從頭開始渲染,若是不想vue複用這些元素,咱們能夠添加一個具備惟一值的 key 屬性

<input type="text" placeholder="請輸入用戶" key="username"/>

<input type="text" placeholder="請輸入郵箱" key="email"/>

另外一個用於根據條件展現元素的選項是 v-show 指令。用法大體同樣:

<p v-show="show">Hello!</p>

v-ifv-show 區別:
v-if 是惰性渲染,在初始渲染時條件爲假,什麼也不作——直到條件第一次變爲真時,纔會開始渲染條件塊;在切換過程當中條件塊內的事件監聽器和子組件會被銷燬和重建。
v-show 無論初始條件是什麼,元素總會被渲染,切換的只是css的display屬性

列表渲染

咱們用 v-for 指令根據一組數據表進行列表渲染。v-for 指令須要使用 item in list 的語法,list指的是原數據數組,item指的是迭代的數組元素。v-for 指令還支持一個可選的表示當前迭代元素索引的第二個參數 (item, index) in list

<div id="app">
    <ul>
        <li v-for="item in list">
        <!-- 效果同樣 -->
        <!-- <li v-for="item of list"> -->
            {{ item.text }}
        </li>
    </ul>
</div>

<script src="js/vue.min.js"></script>
<script>
    var vm = new Vue({
        el: '#app',
        data: {
            list: [
                {text: 'blue'},
                {text: 'red'},
                {text: 'yellow'},
            ]
        }
    })
</script>

除了數組,v-for指令還能夠經過一個對象的屬性來迭代,v-for 指令最多能夠支持3個參數,第二第三個可選。

<li v-for="(value, key, index) in object">
    {{ index }}. {{ key }}: {{ value }}
</li>

data:{
    object: {
        firstName: 'John',
        lastName: 'Doe',
        age: 26
    }
}

//結果
0. firstName: John
1. lastName: Doe
2. age: 26
Vue的生命週期

圖片描述

根據上圖作了一個測試例子,列出了每一個生命週期對應的不一樣屬性的狀態

<div id="app">
    {{message}}
</div>

<script src="js/vue.min.js"></script>
<script>
    var vm = new Vue({
        el: '#app',
        data: {
            message : "hello"
        },
        beforeCreate: function () {
            console.group('beforeCreate 建立前狀態===============》');
            console.log("%c%s", "color:red" , "el     : " + this.$el); //undefined
            console.log("%c%s", "color:red","data   : " + this.$data); //undefined
            console.log("%c%s", "color:red","message: " + this.message)
        },
        created: function () {
            console.group('created 建立完畢狀態===============》');
            console.log("%c%s", "color:red","el     : " + this.$el); //undefined
            console.log("%c%s", "color:red","data   : " + this.$data); //已被初始化
            console.log("%c%s", "color:red","message: " + this.message); //已被初始化
        },
        beforeMount: function () {
            console.group('beforeMount 掛載前狀態===============》');
            console.log("%c%s", "color:red","el     : " + (this.$el)); //已被初始化
            console.log(this.$el);
            console.log("%c%s", "color:red","data   : " + this.$data); //已被初始化
            console.log("%c%s", "color:red","message: " + this.message); //已被初始化
        },
        mounted: function () {
            console.group('mounted 掛載結束狀態===============》');
            console.log("%c%s", "color:red","el     : " + this.$el); //已被初始化
            console.log(this.$el);
            console.log("%c%s", "color:red","data   : " + this.$data); //已被初始化
            console.log("%c%s", "color:red","message: " + this.message); //已被初始化

            var _this = this;
            setTimeout(function(){
                _this.message = 'hello world!!';
            }, 3000);
        },
        beforeUpdate: function () {
            console.group('beforeUpdate 更新前狀態===============》');
            console.log("%c%s", "color:red","el     : " + this.$el);
            console.log(this.$el);
            console.log("%c%s", "color:red","data   : " + this.$data);
            console.log("%c%s", "color:red","message: " + this.message);
        },
        updated: function () {
            console.group('updated 更新完成狀態===============》');
            console.log("%c%s", "color:red","el     : " + this.$el);
            console.log(this.$el);
            console.log("%c%s", "color:red","data   : " + this.$data);
            console.log("%c%s", "color:red","message: " + this.message);
        },
        beforeDestroy: function () {
            console.group('beforeDestroy 銷燬前狀態===============》');
            console.log("%c%s", "color:red","el     : " + this.$el);
            console.log(this.$el);
            console.log("%c%s", "color:red","data   : " + this.$data);
            console.log("%c%s", "color:red","message: " + this.message);
        },
        destroyed: function () {
            console.group('destroyed 銷燬完成狀態===============》');
            console.log("%c%s", "color:red","el     : " + this.$el);
            console.log(this.$el);
            console.log("%c%s", "color:red","data   : " + this.$data);
            console.log("%c%s", "color:red","message: " + this.message)
        }
    })
</script>
相關文章
相關標籤/搜索