【Vue.js】组件化解析二

这是我参与更文挑战的第9天,活动详情查看: 更文挑战

一、组件间的通信

组件实例的作用域是孤立的;这意味着不能并且不应该在子组件的模板内直接引用父组件的数据。但是父子组件之间需要通信:父组件要给子组件传递数据,子组件需要将它内部发生的事情告知给父组件。

在 Vue.js 中,父子组件的关系可以总结为 props down, events up 。父组件通过 props 向下传递数据给子组件,子组件通过 events 给父组件发送消息。如下图所示:

微信截图_20210629130139.png

二、 Prop — 父组件传递数据给子组件

prop 是父组件用来传递数据的一个自定义属性。子组件需要显式地用 props 选项声明 “prop”:

Vue.component('child', {

	  // 声明 props

	  props: ['message'],

	  // 就像 data 一样,prop 可以用在模板内

	  // 同样也可以在 vm 实例中像 “this.message” 这样使用

	  template: '<span>{{ message }}</span>'

  })
复制代码

2.1 简单的传值

<!doctype html>
<html lang="en">
    <head>
        <meta charset="UTF-8">
        <title></title>
    </head>
    <body>
        <div id="app">
            <my-component message="你好"></my-component>
        </div>
        
        <script src="js/vue.js"></script>
        <script>
            
            Vue.component('my-component',{
                props:['message'],
                template:'<h1>{{message}}</h1>'
            });
            new Vue({
                el:'#app'
            })
           
        </script>
    </body>
</html>
复制代码

注意:HTML 特性不区分大小写。当使用非字符串模版时,prop的名字形式会从 camelCase 转为 kebab-case(短横线隔开)。

2.2 父组件传值给子组件,动态绑定

<!doctype html>
<html lang="en">
    <head>
        <meta charset="UTF-8">
        <title></title>
    </head>
    <body>
        <div id="app">
            <my-component message="message"></my-component>
               
               <template id="myComponent">
                   {{message}}
               </template>
        </div>
       
        <script src="js/vue.js"></script>
        <script>
            new Vue({
                el:'#app',
                data:{
                    message:'你好'
                },
                components:{
                    'my-component':{
                        template:'#myComponent',
                        props:['message']
                    }
                }
                
            })
        </script>
    </body>
</html>
复制代码

2.3 prop默认是单向绑定

当父组件的属性变化时,将传导给子组件,但是反过来不会。这是为了防止子组件无意修改了父组件的状态。

<!doctype html>
<html lang="en">
    <head>
        <meta charset="UTF-8">
        <title></title>
    </head>
    <body>
        <div id="app">
               <div>
                   <p>{{name}}</p>
                   <input type="text" v-model="name" />
               </div>
               
               <template id="myComponent">
                   {{name}}
               </template>
        </div>
       
        <script src="js/vue.js"></script>
        <script>
            new Vue({
                el:'#app',
                data:{
                    name:'你好'
                },
                components:{
                    'my-component':{
                        template:'#myComponent',
                        props:['name']
                    }
                }
                
            })
        </script>
    </body>
</html>
复制代码

结论:在vuejs2.0中,任何试图在组件内修改通过props传入的父组件数据都被认为是anti-pattern的。

三、自定义事件

我们知道,父组件是使用 props 传递数据给子组件,但如果子组件要把数据传递回去,应该怎样做?那就是自定义事件!

每个 Vue 实例都实现了事件接口(Events interface),即:

使用 $on(eventName) 监听事件

使用 $emit(eventName) 触发事件

另外,父组件可以在使用子组件的地方直接用 v-on 来监听子组件触发的事件。

一个简单的官方案例帮助我们来理解:

<!doctype html>
<html lang="en">
    <head>
        <meta charset="UTF-8">
        <title></title>
    </head>
    <body>
        <div id="app">
               <div>
                   <p>{{total}}</p>
                   <button-component @clicktotal="clicktotal"></buton-component>
               </div>
               
               <template id="myComponent">
                      <button @click="clicktotal"></button>
               </template>
        </div>
       
        <script src="js/vue.js"></script>
        <script>
            new Vue({
                el:'#app',
                data:{
                    total:0
                },
                methods:{
                    clicktotal(){
                        this.total += 1
                    },
                },
                components:{
                    'my-component':{
                        template:'#myComponent',
                        props:['name'],
                        methods:{
                            clicktotal(){
                                this.$emit('clicktotal')
                            }
                        }
                    }
                }
                
            })
        </script>
    </body>
</html>
复制代码

运行结果:子组件已经和它外部完全解耦了。它所做的只是触发一个父组件关心的内部事件。

© 版权声明
THE END
喜欢就支持一下吧
点赞0 分享