1. 程式人生 > >vue學習十一(prop傳不同值、 v-bind 動態賦值、單向資料流、prop校驗)

vue學習十一(prop傳不同值、 v-bind 動態賦值、單向資料流、prop校驗)

區域性註冊

在這些情況下,你可以通過一個普通的 JavaScript 物件來定義元件:

var ComponentA = { /* ... */ }

然後在 components 選項中定義你想要使用的元件:

new Vue({
  el: '#app',
  components: {
    'component-a': ComponentA,
    'component-b': ComponentB
  }
})

對於 components 物件中的每個屬性來說,其屬性名就是自定義元素的名字,其屬性值就是這個元件的選項物件

我們看下面的例子:


    <div id="div2">
        <my-component>
        </my-component>

    </div>
    <script type="text/javascript">
        var Child = {
            template: '<div>A custom component!</div>'
        }
        new Vue({
            el: "#div2",
            components: {
                'my-component': Child
            }
        })
    </script>

dom模板解析注意事項

有些 HTML 元素,諸如 <ul>、<ol>、<table> 和 <select>,對於哪些元素可以出現在其內部是有嚴格限制的。而有些元素,諸如 <li>、<tr> 和 <option>,只能出現在其它某些特定的元素內部。 這會導致我們使用這些有約束條件的元素時遇到一些問題。例如:

<table>
  <blog-post-row></blog-post-row>
</table>

這個自定義元件 會被作為無效的內容提升到外部,並導致最終渲染結果出錯。幸好這個特殊的 is 特性給了我們一個變通的辦法:

<table>
  <tr is="blog-post-row"></tr>
</table>

我們看一個例子如下:

<ul id="ul1">
        <li is="my-li"></li>
    </ul>

    <script type="text/javascript">
        var Child = {
            template: '<li>xx!</li>'
        }
        new Vue({
            el: "#ul1",
            components: {
                'my-li': Child
            }
        })
    </script>

用 Prop 傳遞不同值型別

以前只看到了以字串陣列形式列出的 prop 但是,通常你希望每個 prop 都有指定的值型別。這時,你可以以物件形式列出 prop,這些屬性的名稱和值分別是 prop 各自的名稱和型別

props: {
  title: String,
  likes: Number,
  isPublished: Boolean,
  commentIds: Array,
  author: Object
}

我們看下面這個例子:

    <child id="div1" message="hello!"></child>

    <script type="text/javascript">
        Vue.component('child', {
            props: {'message':String},
            template: '<span>{{ message }}</span>'
        })
        new Vue({
            el: "#div1",
        })
    </script>

效果輸出如下:

hello!

用 Prop通過 v-bind 動態賦值

  <div id="div2">
        <input type="text" v-model="parentMsg">
        <component1 v-bind:msg="parentMsg"></component1>
    </div>

    <script type="text/javascript">
        Vue.component("component1", {
            props: ["msg"],
            template: "<span>{{msg}}</span>"
        })
        new Vue({
            el: "#div2",
            data: {
                parentMsg: "父元件初始化資料"
            }
        })
    </script>

效果圖如下:

父元件初始化資料  父元件初始化資料

用 Prop傳遞物件的所有屬性

方式一我們可以使用v-bind:prop-name進行物件屬性的傳遞

<div id="div3">
        <todo-item v-bind:text="todo.text" v-bind:complete="todo.isComplete"></todo-item>

    </div>

    <script type="text/javascript">
        Vue.component("todo-item", {
            props: ["text", "complete"],
            template: "<span>{{text}}{{complete}}</span>"
        })
        new Vue({
            el: "#div3",
            data: {
                todo: {
                    text: 'Learn',
                    isComplete: "Vue"
                }
            }
        })
    </script>

方式二我們可以使用不帶引數的 v-bind

 <div id="div4">
        <todo-item v-for="item in todo" v-bind:todo="item"></todo-item>
    </div>

    <script type="text/javascript">
        Vue.component("todo-item", {
            props: ["todo"],
            template: "<span>{{todo}}</span>"
        })
        new Vue({
            el: "#div4",
            data: {
                todo: {
                    text: 'Learn',
                    isComplete: "Vue"
                }
            }
        })
    </script>

輸出效果如下:

LearnVue

用 Prop傳遞物件陣列

<div id="div5">
        <todo-item v-for="item in todo" v-bind:todo="item"></todo-item>
    </div>

    <script type="text/javascript">
        Vue.component("todo-item", {
            props: ["todo"],
            template: "<span>{{todo.text}},{{todo.isComplete}}</span>"
        })
        new Vue({
            el: "#div5",
            data: {
                todo: [{
                    text: 'Learn',
                    isComplete: "Vue"
                }, {
                    text: 'yes',
                    isComplete: "no"
                }]
            }
        })
    </script>

輸出效果如下:

Learn,Vueyes,no

用 Prop傳入一個數字

   <div id="div6">
        <comp todo="1+23"></comp>
        <!-- 這裡用了動態語法,傳遞的值會通過js的表示式計算,傳遞的是數字 -->
        <comp v-bind:todo="1+23"></comp>
    </div>

    <script type="text/javascript">
        Vue.component("comp", {
            props: ["todo"],
            template: "<span>{{todo}}</span>"
        })
        new Vue({
            el: "#div6",
        })
    </script>

輸出如下:

1+23 24

單向資料流

所有的 prop 都使得其父子 prop 之間形成了一個單向下行繫結:父級 prop 的更新會向下流動到子元件中,但是反過來則不行。這樣會防止從子元件意外改變父級元件的狀態,從而導致你的應用的資料流向難以理解。

額外的,每次父級元件發生更新時,子元件中所有的 prop 都將會重新整理為最新的值。這意味著你不應該在一個子元件內部改變 prop。如果你這樣做了,Vue 會在瀏覽器的控制檯中發出警告。

這裡有兩種常見的試圖改變一個 prop 的情形:

1、這個 prop 用來傳遞一個初始值;這個子元件接下來希望將其作為一個本地的 prop 資料來使用。在這種情況下,最好定義一個本地的 data 屬性並將這個 prop 用作其初始值

 <div id="div7">
        <input type='text' v-model="msg">
        <child v-bind:message='msg'></child>
    </div>

    <script type="text/javascript">
        var tmp = 0;
        Vue.component('child', {
            props: ['message'],
            template: '<p>message:{{ message}} --tmp:{{tmp}}</p>',
            data: function () {
                return { tmp: this.message }
            },
        })
        new Vue({
            el: '#div7',
            data: {
                msg: '我是msg'
            }
        })
    </script>

效果圖如下: 在這裡插入圖片描述

2、這個 prop 以一種原始的值傳入且需要進行轉換。在這種情況下,最好使用這個 prop 的值來定義一個計算屬性

<div id="div8">
        <input type='text' v-model="msg">
        <child v-bind:message='msg'></child>
    </div>

    <script type="text/javascript">
        Vue.component('child', {
            props: ['message'],
            template: '<p>message:{{ normalizedSize}} </p>',
            computed: {
                normalizedSize: function () {
                    return this.message += "_str"
                }
            }
        })
        new Vue({
            el: '#div8',
            data: {
                msg: '我是msg'
            }
        })
    </script>

在這裡插入圖片描述

Prop 驗證

我們可以為元件的 prop 指定驗證要求,例如你知道的這些型別。如果有一個需求沒有被滿足,則 Vue 會在瀏覽器控制檯中警告你

為了定製 prop 的驗證方式,你可以為 props 中的值提供一個帶有驗證需求的物件,而不是一個字串陣列。例如:

 <div id="app">
        <my-child :num="100" :msg="'sdf'" :object="{a:'a'}" :cust="100">
            </child>
    </div>

    <script type="text/javascript">
        Vue.component('my-child', {
            props: {
                // 基礎型別檢測 (`null` 意思是任何型別都可以)
                num: Number,
                // 多種型別
                propB: [String, Number],
                // 必傳且是字串
                msg: {
                    type: String,
                    required: true
                },
                // 數字,有預設值
                num1: {
                    type: Number,
                    default: 1000
                },
                // 陣列/物件的預設值應當由一個工廠函式返回
                object: {
                    type: Object,
                    default: function () {
                        return { message: 'hello' }
                    }
                },
                // 自定義驗證函式
                cust: {
                    validator: function (value) {
                        return value > 10
                    }
                }
            },
            template: `<div>
               <p>{{ num }}</p>
               <p>{{ msg }}</p>
               <p>{{ num1 }}</p>
               <p>{{ object }}</p>
               <p>{{ cust }}</p>
              </div>`
        })
        new Vue({
            el: "#app"
        });
    </script>

效果輸出如下:

100

sdf

1000

{ "a": "a" }

100