Vue2.x學習二:資料渲染

WUJYAN發表於2018-05-31

之前,我們提到了vue可以解析雙大括號中的語法,資料繫結——{{msg}},以及,列表渲染——v-for。在這一章中,我們將詳細說明資料的幾種繫結/渲染方式。

單向資料繫結

之前一章中我們提到過,此處,我們通過程式碼,進行簡單回顧。

<body>
    <div class="container">
    <!-- data中的msg對映到此處 -->
        {{msg}}
    </div>

    <script type="text/javascript">
        //構建Vue物件例項
        new Vue({
            //當前Vue物件的作用範圍
            el:`.container`,
            //定義頁面中需要渲染的資料
            data:{
                msg:`hello world`
            }
        });
    </script>
</body>

補充
我們說過,在雙大括號中的語法變數能夠被Vue解析。事實上,雙大括號中還能夠放表示式,常規表示式都能夠被解析。

{{表示式}}

下面舉幾個例子來說明
①{{a+b}}

<body>
    <div class="container">
        {{a+b}}
    </div>

    <script type="text/javascript">
        new Vue({
            el:`.container`,
            data:{
                a:1,
                b:2
            }
        });
    </script>
    <!-- 列印結果:3 -->
</body>

②三目運算{{a ? `a存在` : `a不存在`}}
這句程式碼的意思是:是否存在a,如果a存在,那麼列印“a存在”,否則,列印“a不存在”。

<body>
    <div class="container">
        {{a?`a存在`:`a不存在`}}
    </div>

    <script type="text/javascript">
        new Vue({
            el:`.container`,
            data:{
                a:1,
                b:2
            }
        });
    </script>
    <!-- 列印結果:a存在 -->
</body>

如果a為null,undefined,0,NaN,“等這些值的時候,那麼列印出的結果為“a不存在”。
此處的原理是:資料型別的轉換。

雙向資料繫結

單向資料繫結中msg的資料只能顯示,但是不能改變,通過雙向資料繫結v-model,我們可以在頁面中,人為的改變其中的資料,並且這樣的改變是同步的。

v-model 指令可以在表單 <input> 及 <textarea> 元素上建立雙向資料繫結,它負責監聽使用者的輸入事件以更新資料。
在v-model中,寫入你要繫結的值的模型。
比如,我們要改變頁面中msg顯示的hello world,那麼我們就可以這樣寫,v-model=”msg”。

我們要記住,只有表單元素<input>及<textarea> 元素可以進行雙向資料繫結。

下面通過具體例子來說明:

<body>
    <div class="container">
        <p>{{msg}}</p>
        <!-- 
            雙向資料繫結
            這裡,我們通過input表單,來獲取使用者輸入的值
            用v-model繫結模型
        -->
        <input type="text" v-model="msg">
    </div>

    <script type="text/javascript">
        new Vue({
            el:`.container`,
            data:{
                msg:`hello world`
            }
        });
    </script>
</body>

這裡我們要理清思路:div中{{msg}}的值,是從我們構建的Vue物件中的data中尋找到的。也就是說:我們可以改變表單元素的值,這個值會去改變data中msg的值,然後data中msg的值改變之後,上面div中{{msg}}的值也會發生改變。所以這種形式,我們稱為雙向資料繫結。

列表渲染

v-for,列表渲染之前也提到過,它是根據一組陣列的選項列表進行渲染。
下面我們通過簡單的程式碼例子來回顧

<body>
    <div class="container">
        <ul>
            <!-- 
                在li中通過v-for指令,來遍歷data中,arrList中的資料
                自定義一個資料迭代的別名arr,並且arr能夠遍歷arrList中的資料
                通過雙大括號,將arr中的值輸入在內
             -->
            <li v-for="arr in arrList">{{arr}}</li>
        </ul>
    </div>

    <script type="text/javascript">
        new Vue({
            el:`.container`,
            data:{
                arrList:[`terry`,`larry`]
            }
        });
    </script>
<!-- 列印結果:以列表的形式列印出terry,larry -->
</body>

條件渲染

條件渲染的表示式的返回值是“布林型別”,並且與if-else迴圈語句相似。
下面來看一下幾種條件渲染的指令:

v-if

v-if指令中的值可以是我們自己定義在data中的值或者表示式。
表示式,如:”Math.random() > 0.5″,這種返回值為布林型別的就可以。
如果返回值為“true”,那麼v-if中的內容會被顯示;反之,它不會被顯示。

下面來測試一下:

<body>
    <div class="container">
    <!-- 如果data中的user存在,對應返回p標籤中的內容 -->
        <p v-if="user">歡迎您</p>
    </div>

    <script type="text/javascript">
        new Vue({
            el:`.container`,
            data:{
                user:`user`,//列印結果:歡迎您
                /*
                user:``,//列印結果:什麼都列印不出來
                當user為null,undefined,0,NaN,``等這些值的時候,都列印不出來
                */
            }
        });
    </script>
</body>

v-else

v-else必須與v-if或者v-else-if配合使用,否則它將不會被識別。
它的意思是,如果v-if的返回值為“false”,那麼它將顯示v-else中的內容。

下面我們來測試一下:

<body>
    <div class="container">
        <p v-if="user">歡迎您</p>
        <p v-else>您未登陸</p>
    </div>

    <script type="text/javascript">
        new Vue({
            el:`.container`,
            data:{
                user:``,
            }
        });
    </script>
    <!-- 列印結果:您未登陸 -->
</body>

v-else-if

v-else-if,充當v-if的“else-if”部分,可連續使用。
它也必須緊跟在v-if之後,無法單獨使用。

下面測試一下:

<body>
    <div class="container">
        <p v-if="type === `A`">A</p>
        <p v-else-if="type === `B`">B</p>
        <p v-else-if="type === `C`"> C</p>
        <p v-else>Not A/B/C</p>
    </div>

    <script type="text/javascript">
        new Vue({
            el:`.container`,
            data:{
                type:`B`
            }
        });
    </script>
    <!-- 列印結果:B -->
</body>

v-show

v-show的返回值也為布林型別,它用來控制程式碼所示的檢視是否顯示。
但與v-if不同的是:帶有 v-show 的元素始終會被渲染並保留在DOM中,只是改變css中的display屬性。

下面來測試一下:

<body>
    <div class="container">
        <p v-show="isShow">顯示</p>
        <!-- isShow是條件渲染的一個屬性,所以是一個變數,放在data中 -->
    </div>

    <script type="text/javascript">
        new Vue({
            el:`.container`,
            data:{
                isShow:false
                /*v-show意味著是否顯示,屬性為假,因此不會顯示
                如果 isShow:true,則會顯示*/
            }
        });
    </script>
    <!-- 無列印結果 -->
</body>

下面引用一段官方文件中的關於v-if與v-show區別的話。
v-if vs v-show
v-if 是“真正”的條件渲染,因為它會確保在切換過程中條件塊內的事件監聽器和子元件適當地被銷燬和重建。

v-if 也是惰性的:如果在初始渲染時條件為假,則什麼也不做——直到條件第一次變為真時,才會開始渲染條件塊。

相比之下,v-show 就簡單得多——不管初始條件是什麼,元素總是會被渲染,並且只是簡單地基於 CSS 進行切換。

一般來說,v-if 有更高的切換開銷,而 v-show 有更高的初始渲染開銷。因此,如果需要非常頻繁地切換,則使用 v-show 較好;如果在執行時條件很少改變,則使用 v-if 較好。

屬性渲染

我們先來看一下以下程式碼

<body>
    <div class="container">
        <!-- 怎麼顯示data中title的值 -->
        <button>按鈕</button>
    </div>

    <script type="text/javascript">
        new Vue({
            el:`.container`,
            data:{
                //隨便定義的值
                title:`this is title`
            },
        });
    </script>
</body>

此時,我們有一個問題:如何讓data中title的值顯示到button中?
原先我們是這麼寫的:
<button title=”button”>按鈕</button>
讓title的值在滑鼠懸停到button上時,作為提示顯示出來。
但這並不是我們所期望的,我們希望懸停時顯示的值不是寫死的。

這時,我們可以用v-bind來給它繫結屬性。
v-bind可以動態地繫結一個或多個特性,或一個元件prop到表示式(prop之後會在元件中講到)。
它的語法形式是這樣的:v-bind:屬性名=”(定義在data中的)變數”

所以上面的程式碼可以這樣變一下:

<!-- v-bind動態的繫結(vue中的)屬性title -->
<button v-bind:title="title">按鈕</button>
<!-- 
 簡寫
<button :title="title">按鈕</button>
-->

當然,它還可以其他特性:
1)樣式屬性的繫結(通過style)
(事件的繫結內容在下一章節會有)
以下面程式碼為例:

<body>
    <div class="container">
        <!-- 目標:當我們點選p標籤,字型變色 -->
        <!-- 屬性的繫結用v-bind
            為樣式繫結屬性,我們可以用v-bind:style="",
            簡寫 :style=""
         -->
         <!-- 直接寫物件,物件中由鍵值對組成,{樣式的屬性名:樣式的屬性值}
               樣式的屬性值,必須在vue物件中的data中獲取
               事件的繫結用v-on: 簡寫@ ,方法定義在methods中
         -->
        <p :style="{color:fontColor}" @click="scale">{{msg}}</p>
    </div>

    <script type="text/javascript">
        new Vue({
            el:`.container`,
            data:{
                msg:`click me`,
                fontColor:`#666`
            },
            methods:{
                // 當我們點選p標籤,字型變色
                scale(){
                    this.fontColor=`orange`;
                }
            }
        });
    </script>
</body>

2)樣式屬性的繫結(通過class)

<body>
    <style type="text/css">
        .block {
            background-color: orange;
            color: #fff;
            border-radius: 3px;
        }
        .aaa {
              padding: .5em 1em;
        }
        .bbb {
              border:2px solid pink;
        }
        .ccc {
            font-weight: bold;
            font-size: 24px;
        }
    </style>
    
    <div class="container">
        <!-- 第一種: 只有一個class-->
        <!-- 在class中的取值就為一個變數
            isBlock為布林型別的值
            如果,isBlock為true,那麼class的取值為block
            如果,isBlock為false,那麼class的取值就不為block
            這種寫法一定要在style標籤中定義block樣式
         -->
        <p v-bind:class="{block:isBlock}">{{msg}}</p>
        <!-- 第二種: 有多個class-->
        <!-- 用中括號將多個class包裹,每個class之間用逗號分隔,相當於陣列 -->
        <!-- {block:isBlock}:如果isBlock為true,返回值為block 
             `aaa`:用引號引起來,相當於字串,不會被解析,原樣輸出
              className:沒有單引號,是一個變數,訪問data中的className
              class="ccc":常規css樣式
        -->
        <p v-bind:class="[{block:isBlock},`aaa`,className]" class="ccc">{{msg}}</p>
    </div>

    <script type="text/javascript">
        new Vue({
            el:`.container`,
            data:{
                msg:`click me`,
                isBlock:true,
                // 定義一個樣式為bbb
                className:`bbb`,
            }
        });
    </script>
</body>

3)style樣式屬性中傳入物件

<body>
    <div class="container">
        <!-- 直接給style屬性樣式傳入物件,並在data中定義 -->
        <!-- 只有一個物件 -->
        <p v-bind:style="styleObj">{{msg}}</p>
        <!-- 有多個物件 -->
        <p v-bind:style="[styleObj,styleObj2]">{{msg}}</p>
    </div>

    <script type="text/javascript">
        new Vue({
            el:`.container`,
            data:{
                msg:`click me`,
                // 給style屬性傳入的物件
                // 相當於將css的樣式規則寫在js中
                styleObj:{
                    /*由於是一個物件,
                      當屬性名為普通字串的時候不需要加引號,
                      當屬性名為特殊寫法時,如background-color,要加引號
                    */
                    `background-color`:`pink`,
                      `color`:`#fff`,
                      `padding`:`.5em 1em`
                },
                styleObj2:{
                      `border-radius`:`10px`
                }
            }
        });
    </script>
</body>

此處講解的只是基礎內容,如果想要詳細瞭解,可以檢視Vue.js官方教程文件:https://cn.vuejs.org/v2/guide/

相關文章