vue.js原生组件化开发(二)——父子组件

前言

在了解父子组件之前应先掌握组件开发基础。在实际开发过程中,组件之间可以嵌套,也因此生成父子组件。

父子组件创建流程

1.构建父子组件

1.1 全局注册

(1)构建注册子组件

//构建子组件child
var child = Vue.extend({
    template: '<div>这是子组件</div>'
});
//注册名为'child'的组件
Vue.component('child',child);

(2)构建注册父组件

//构建父组件parent,在其中嵌套child组件
var parent = Vue.extend({
    template: '<div>这是父组件<child></child></div>'
});

Vue.component('parent',parent);

(3)定义vue实例

var app = new Vue({
    el: '#app'
})

(4)使用父组件

<div id="app">
    <parent></parent>
</div>

打开浏览器查看

1.2 局部注册

(1)构建子组件

var child = Vue.extend({
    template: '<div>这是子组件</div>'
});

(2)构建父组件
在父组件中局部注册子组件

var parent = Vue.extend({
    template: '<div>这是父组件<child></child></div>',
    components:{
        'child':child
    }
});

(3)定义vue实例
在vue实例中局部注册父组件

var app = new Vue({
    el: '#app',
    components:{
        'parent':parent
    }
})

(4)使用父组件

<div id="app">
    <parent></parent>
</div>

2.父子组件间通信

2.1 父传子

父组件传消息到子组件使用<code>props</code>,并且这传递是单向的,只能由父组件传到子组件。我们将上面例子中的父组件增加一个数据传递到子组件中渲染显示。如果父组件需要传多个数据给子组件,依次在后面加即可。
(1)在父组件中增加data,并绑定到子组件上

var parent = Vue.extend({
    template: '<div>这是父组件<child :pdata=data></child></div>',
    data(){
        return{
            data:'这是父组件传来的数据'
        }
    },
    components:{
        'child':child
    }
});

其中<code><child :pdata=data></child></code>,<code>:pdata</code>是<code>v-bind:pdata</code>的缩写,<code>pdata</code>是自定义传递数据的命名,子组件中也是用该名字获取数据,<code>data</code>是父组件中数据的命名。
(2)在子组件中通过props获取数据,并渲染出来

var child = Vue.extend({
    template: '<div>这是子组件 {{pdata}}</div>',
    props:['pdata']
});

查看浏览器

父组件中数据发生变化,子组件中自动更新
子组件不可直接修改通过<code>props</code>获取到的父组件中的数据

下面我们通过一个例子更好的理解上面两句话
(1)使用<code><template></code>标签创建子组件
为方便书写,我们使用<code><template></code>标签创建组件

<template id="child">
    <div>
        <p>这是子组件</p>
        <table>
            <tr>
                <td>name</td>
                <td>{{name}}</td>
                <td><input type="text" v-model="name"></td>
            </tr>
            <tr>
                <td>age</td>
                <td>{{age}}</td>
                <td><input type="text" v-model="age"></td>
            </tr>
        </table>
    </div>
</template>

这里使用<code>v-model</code>指令来双向绑定从父组件中获取到的数据
(2)使用<code><template></code>标签创建父组件

<template id="parent">
    <div>
        <p>这是父组件</p>
        <table>
            <tr>
                <td>name</td>
                <td>{{name}}</td>
                <td><input type="text" v-model="name"></td>
            </tr>
            <tr>
                <td>age</td>
                <td>{{age}}</td>
                <td><input type="text" v-model="age"></td>
            </tr>
        </table>
        //给子组件传递2个数据
        <child :name="name" :age="age"></child>
    </div>
</template>

(3)构建子组件

var child = Vue.extend({
    template: '#child',
    props:['name','age']
});

(4)构建父组件

var parent = Vue.extend({
    template: '#parent',
    data(){
        return{
            age:16,
            name:'乔巴'
        }
    },
    components:{
        'child':child
    }
});

查看浏览器


接着,我们在父组件中修改输入框的值,这会引起<code>v-model</code>绑定的值变化,同时也会改变子组件中的值



然后我们试着修改子组件中输入框的值,vue会警告不能直接修改父组件传过来的值。



如果我们需要修改从父组件中props传过来的值,最好一开始把这个值赋给另外一个data。
var child = Vue.extend({
    template: '#child',
    props:['name','age'],
    data(){
        return{
            name1: '',
            age1: ''
        }
    },
    //页面挂载时将props的值赋给子组件中的data
    mounted:function(){
        this.name1 = this.name
        this.age1 = this.age
    },
    //同时增加监听,当props的值发生变化时,也立即赋值给子组件的data
    watch:{
        name:function(val){
            this.name1 = this.name
        },
        age:function(val){
            this.age1 = this.name
        }
    }
});

同时修改<code>v-model</code>绑定的<code>name</code>值为<code>name1</code>,<code>age</code>为<code>age1</code>
现在修改子组件中的值,就不会报错了,这是因为子组件中修改的是<code>name1</code>,并不是props传递过来的<code>name</code>值


2.1 子传父

子组件给父组件传值通过<code>emit</code>。父组件需在子组件标签上绑定<code>emit</code>事件。
例子:
(1)构建子组件

var child = Vue.extend({
    template: '<div><button @click="change">点击给父组件传值</button></div>',
    methods:{
        change: function(){
            this.$emit('posttoparent',10)
        }
    }
});

子组件按钮绑定了一个<code>click</code>事件,当点击按钮执行<code>change</code>方法,该方法触发<code>emit</code>事件,事件名为<code>posttoparent</code>,并且带了一个参数10。
(2)构建父组件

var parent = Vue.extend({
    template: '<div>来自子组件的值为:{{datafromchild}} <child v-on:posttoparent="getfromchild"></child></div>',
    data(){
        return{
            datafromchild:''
        }
    },
    components:{
        'child':child
    },
    methods: {
        getfromchild: function(val){
            this.datafromchild = val
        }
    }
});

父组件接收emit事件通过v-on指令,格式为:

v-on:emit方法名="父组件方法"

父组件将接收到的参数赋值给<code>datafromchild </code>
查看浏览器


3.兄弟组件间通信

兄弟组件间通信也是用的<code>emit</code>。但原生vue.js需要新建一个空的vue实例来当桥梁。
下面直接贴代码

//新建一个空的vue实例bus
var bus = new Vue();

var myCom1 = Vue.extend({
    template: '<div><button @click="change">点击给兄弟组件传值</button></div>',
    methods:{
        change: function(){
            //通过空实例去触发emit
            bus.$emit('posttobro',10)
        }
    }
});

var myCom2 = Vue.extend({
    template: '<div>来自兄弟组件的值为:{{datafrombro}}</div>',
    data(){
        return{
            datafrombro:''
        }
    },
    mounted:function(){
      //接收emit事件
        bus.$on('posttobro',function(val){
            this.datafrombro = val
        }.bind(this))
    }
});

Vue.component('my-com1',myCom1);
Vue.component('my-com2',myCom2);

var app = new Vue({
    el: '#app'
});

使用组件

<div id="app">
    <my-com1></my-com1>
    <my-com2></my-com2>
</div>

查看浏览器


最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 202,009评论 5 474
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 84,808评论 2 378
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 148,891评论 0 335
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,283评论 1 272
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,285评论 5 363
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,409评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,809评论 3 393
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,487评论 0 256
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,680评论 1 295
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,499评论 2 318
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,548评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,268评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,815评论 3 304
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,872评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,102评论 1 258
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,683评论 2 348
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,253评论 2 341

推荐阅读更多精彩内容

  • 这篇笔记主要包含 Vue 2 不同于 Vue 1 或者特有的内容,还有我对于 Vue 1.0 印象不深的内容。关于...
    云之外阅读 5,044评论 0 29
  • Vue 实例 属性和方法 每个 Vue 实例都会代理其 data 对象里所有的属性:var data = { a:...
    云之外阅读 2,198评论 0 6
  • 此文基于官方文档,里面部分例子有改动,加上了一些自己的理解 什么是组件? 组件(Component)是 Vue.j...
    陆志均阅读 3,798评论 5 14
  • 1.安装 可以简单地在页面引入Vue.js作为独立版本,Vue即被注册为全局变量,可以在页面使用了。 如果希望搭建...
    Awey阅读 10,978评论 4 129
  • 我小心 怀揣一纸希望 疯狂地跑 两地渡口 你不言 ...
    1木子业阅读 239评论 0 0