全局注册

我们只用过 Vue.component 来创建组件
这些组件是全局注册的。也就是说它们在注册之后可以用在任何新创建的 Vue 根实例 (new Vue) 的模板中。比如

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

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

局部注册

在这些情况下,你可以通过一个普通的 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
Logo

前往低代码交流专区

更多推荐