2021-12-04 父子组件 & 第三方组件库 & 第三方组件库iview & 第三方组件库Vant & 父子组件配合开发

一、父子组件传值

(1) VUE项目中的父子组件之间的传值。
父子组件就是在一个vue文件中引入另一个vue文件,被引入vue文件就是子组件,引入vue文件的vue文件就是父组件。而在父组件中是不能直接调用子组件中的变量值的。

 Vue.config.productionTip = false

        // Child1组件
        Vue.component('Child1', {
            // 通过$parent返回的是父组件对象
            template:`
                <div class="child1">
                    <h3>房产信息</h3>
                    <p>{{$parent.house.address}}</p>
                    <p>{{$parent.house.size}}</p>
                    <Childson></Childson>
                </div>
            `,

组件中的数据,必须是一个函数,由函数返回一个对象

     data() {
                return {
                    name:'张杰',
                    age:25
                }
            },
            mounted() {
                console.log('子级1mounted');
            },
            created() {
                console.log('子级1created');
            },
        })


        // childSon组件
        Vue.component('Childson',{
            // $parent获取父组件对象
            // $root获取根组件对象
            template:`
                <div class="childSon">
                    <h3>房产信息</h3>
                    <p>{{$parent.$parent.house.address}}</p>
                    <p>{{$parent.$parent.house.size}}</p>
                    <hr>
                    <p>{{$root.house.address}}</p>
                    <p>{{$root.house.size}}</p>
                </div>
            `
        })

Child2 组件

Vue.component('Child2', {
            template:`
                <div class="child2">
                    <h3>汽车信息</h3>
                    <p>{{$parent.car.name}}</p>
                    <p>{{$parent.car.color}}</p>
                </div>
            `,
            data() {
                return {
                    name:'张飞',
                    age:23
                }
            },
            mounted() {
                console.log('子级2mounted');
            },
            created() {
                console.log('子级2created');
            },
        })
    Vue.component('Child3', {
            template:`
                <div class="child3">
                    <h3>存款信息</h3>
                    <p>{{$parent.money.value}}</p>
                    <p>{{$parent.money.bank}}</p>
                </div>
            `,
            data() {
                return {
                    name:'张强',
                    age:20
                }
            },
            mounted() {
                console.log('子级3mounted');
            },
            created() {
                console.log('子级3created');
            },
        })

暂且将#app对应的内容当成根组件

 new Vue({
            el:'#app',
            //数据
            data:{
                house:{
                    address:'名城世家3栋1单元1101室',
                    size:'150平米'
                },
                car:{
                    name:'奔驰S400',
                    color:'黑色'
                },
                money:{
                    value:'150W',
                    bank:'中国建设银行'
                },
                //接收子组件的数据的对象
                son1:{
                    name:'',
                    age:0
                },
                son2:{
                    name:'',
                    age:0
                },
                son3:{
                    name:'',
                    age:0
                }
            },
 mounted() {
                console.log('父级mounted');
                // 注意:在父子级的mounted生命周期函数内,才能获取到$children信息
                // $children返回的是所有子组件对象的数组
                // console.log(this.$children);
                /* this.son1.name = this.$children[0].name
                this.son1.age = this.$children[0].age
                this.son2.name = this.$children[1].name
                this.son2.age = this.$children[1].age
                this.son3.name = this.$children[2].name
                this.son3.age = this.$children[2].age */

                // $refs返回的是一个对象,对象中包含所有带有ref属性的组件
                // console.log(this.$refs);
                this.son1.name = this.$refs.son1.name
                this.son1.age = this.$refs.son1.age
                this.son2.name = this.$refs.son2.name
                this.son2.age = this.$refs.son2.age
                this.son3.name = this.$refs.son3.name
                this.son3.age = this.$refs.son3.age
            },
            created() {
                console.log('父级created');
            },
        })

子组件向父组件传值

那么我们延伸一下,子组件怎么向父组件传值?

  1. 基本概念
    在vue中,父子组件的关系可以总结为prop向下传递,事件向上传递。父组件通过prop给子组件下发数据,子组件通过事件给父组件发送信息。
父子组件图.png

每个Vue实例都实现了事件接口:使用on(evntName)监听事件;使用emit(eventName,optionalPayload)触发事件。另外,父组件可以在使用子组件的地方直接用v-on来监听子组件触发的事件。

  1. 举例说明
    父组件在组件上定义了一个自定义事件childFn,事件名为parentFn用于接受子组件传过来的message值。
<!-- 父组件 -->
<template>
    <div class="test">
      <test-com @childFn="parentFn"></test-com>
      <br/> 
      子组件传来的值 : {{message}}
    </div>
</template>

<script>
export default {
    // ...
    data() {
        return {
             message: ''
        }
    },
    methods: {
       parentFn(payload) {
        this.message = payload;
      }
    }
}
</script>

子组件是一个buttton按钮,并为其添加了一个click事件,当点击的时候使用$emit()触发事件,把message传给父组件。

<!-- 子组件 -->
<template> 
<div class="testCom">
    <input type="text" v-model="message" />
    <button @click="click">Send</button>
</div>
</template>
<script>
export default {
    // ...
    data() {
        return {
          // 默认
          message: '我是来自子组件的消息'
        }
    },
    methods: {
      click() {
            this.$emit('childFn', this.message);
        }
    }    
}
</script>

这样我们就基本实现了子组件向父组件发送值了

小结

通过"props down , events up"我们就简单的实现了父子组件之间的双向传值,这是很基本的知识点,其它还有$invoke等等方法,大家可以去官网好好看看。
关于通信和状态管理就必须了解vuex了,后面我们在项目中当涉及了再好好讲。

二、第三方组件库element-ui

网址:https://element.eleme.cn/#/zh-CN

(1)引入

<!-- 引入样式 -->
<link rel="stylesheet" href="https://unpkg.com/element-ui/lib/theme-chalk/index.css">
<!-- 引入组件库 -->
<script src="https://unpkg.com/element-ui/lib/index.js"></script>
<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>第三方组件库element-ui</title>
    <!-- 引入element-ui样式 -->
    <link rel="stylesheet" href="https://unpkg.com/element-ui/lib/theme-chalk/index.css">
</head>

在Elment网站中选择需要的组件复制过来

<body>
    <div id="app">
        <div>
            <el-button type="primary">主要按钮</el-button>
            <el-link type="success">成功链接</el-link>
            <el-date-picker
            v-model="date1"
            type="date"
            placeholder="选择日期">
            </el-date-picker>
            <hr>
            <el-breadcrumb separator-class="el-icon-arrow-right">
                <el-breadcrumb-item :to="{ path: '/' }">首页</el-breadcrumb-item>
                <el-breadcrumb-item>活动管理</el-breadcrumb-item>
                <el-breadcrumb-item>活动列表</el-breadcrumb-item>
                <el-breadcrumb-item>活动详情</el-breadcrumb-item>
              </el-breadcrumb>
            <el-table
                :data="tableData"
                style="width: 100%">
                <el-table-column
                    prop="date"
                    label="日期"
                    width="180">
                </el-table-column>
                <el-table-column
                    prop="name"
                    label="姓名"
                    width="180">
                </el-table-column>
                <el-table-column
                    prop="address"
                    label="地址">
                </el-table-column>
                </el-table>
                <el-pagination
                background
                layout="prev, pager, next"
                :total="1000">
                </el-pagination>
        </div>
        <el-tabs v-model="activeName" type="card">
            <el-tab-pane label="用户管理" name="first">
                用户管理用户管理用户管理用户管理用户管理
            </el-tab-pane>
            <el-tab-pane label="配置管理" name="second">
                <h2>配置管理配置管理</h2>
                <h2>配置管理</h2>
            </el-tab-pane>
            <el-tab-pane label="角色管理" name="third">
                <ul>
                    <li>配置管理</li>
                    <li>配置管理</li>
                    <li>配置管理</li>
                </ul>
            </el-tab-pane>
            <el-tab-pane label="定时任务补偿" name="fourth">
                <table>
                    <tr>
                        <td>定时任务补偿</td>
                        <td>定时任务补偿</td>
                    </tr>
                    <tr>
                        <td>定时任务补偿</td>
                        <td>定时任务补偿</td>
                    </tr>
                </table>
            </el-tab-pane>
          </el-tabs>
    </div>

接上

<!-- 引入Vue -->
    <script src="https://cdn.bootcdn.net/ajax/libs/vue/2.6.14/vue.js"></script>
    <!-- 第三方组件库,必须在Vue的下面引入 -->
    <!-- 引入element-ui组件库 -->
    <script src="https://unpkg.com/element-ui/lib/index.js"></script>
    <script>
        new Vue({
            el:'#app',
            data() {
                return {
                    //获取时间
                    date1:'',
                    tableData: [{
                        date: '2016-05-02',
                        name: '王小虎',
                        address: '上海市普陀区金沙江路 1518 弄'
                    }, {
                        date: '2016-05-04',
                        name: '王小虎',
                        address: '上海市普陀区金沙江路 1517 弄'
                    }, {
                        date: '2016-05-01',
                        name: '王小虎',
                        address: '上海市普陀区金沙江路 1519 弄'
                    }, {
                        date: '2016-05-03',
                        name: '王小虎',
                        address: '上海市普陀区金沙江路 1516 弄'
                    }],
                    activeName:'first'
                }
            },
        })
    </script>
</body>

效果图如下:


效果图.jpg

三、第三方组件库iview

网址:http://v1.iviewui.com/

(1)引入iview的样式,在页面上引入 js 和 css 文件即可开始使用:

<link rel="stylesheet" type="text/css" href="http://unpkg.com/view-design/dist/styles/iview.css">

(2)引入Vue

<script type="text/javascript" src="http://vuejs.org/js/vue.min.js"></script>

(3)引入iview

<script type="text/javascript" src="http://unpkg.com/view-design/dist/iview.min.js"></script>

(4)快速使用 View UI 写出一个示例:

<script>
        new Vue({
            el: '#app',
            data() {
                return {
                    columns1: [
                        {
                            title: '姓名',
                            key: 'name'
                        },
                        {
                            title: '年龄',
                            key: 'age'
                        },
                        {
                            title: '地址',
                            key: 'address'
                        },
                        {
                            title:'日期',
                            key:'date'
                        }
                    ],
                    data1: [
                        {
                            name: 'John Brown',
                            age: 18,
                            address: 'New York No. 1 Lake Park',
                            date: '2016-10-03'
                        },
                        {
                            name: 'Jim Green',
                            age: 24,
                            address: 'London No. 1 Lake Park',
                            date: '2016-10-01'
                        },
                        {
                            name: 'Joe Black',
                            age: 30,
                            address: 'Sydney No. 1 Lake Park',
                            date: '2016-10-02'
                        },
                        {
                            name: 'Jon Snow',
                            age: 26,
                            address: 'Ottawa No. 2 Lake Park',
                            date: '2016-10-04'
                        }
                    ]
                }
            },
        })
    </script>
SUCCESS.jpg

四、第三方组件库Vant

网址:http://vant-contrib.gitee.io/vant/#/zh-CN/

使用 Vant 最简单的方法是直接在 html 文件中引入 CDN 链接,之后你可以通过全局变量 vant 访问到所有组件。

引入样式文件

<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/vant@2.12/lib/index.css" />

    <div id="app">
        <van-button type="primary">主要按钮</van-button>
        <van-cell-group>
            <van-cell title="单元格" value="内容" />
            <van-cell title="单元格" value="内容" label="描述信息" />
        </van-cell-group>
        <van-cell-group>
            <van-field v-model="value" label="文本" placeholder="请输入用户名" />
        </van-cell-group>
    </div>
    <script src="https://cdn.jsdelivr.net/npm/vue@2.6/dist/vue.min.js"></script>
    <script src="https://cdn.jsdelivr.net/npm/vant@2.12/lib/vant.min.js"></script>
    <script>
        new Vue({
            el: '#app',
            data() {
                return {
                    value:'123'
                }
            },
        })
    </script>

五、父子组件配合开发

示例:

   <style>
        *{
            list-style: none;
            margin: 0;
            padding: 0;
        }
        .tabs{
            width: 400px;
            border: 1px solid #eee;
            padding: 10px;
            margin: 10px;
        }
        .title{
            list-style: none;
            display: flex;
        }
        .title li{
            border: 1px solid #eee;
            padding: 2px 10px;
            margin-right: 4px;
            cursor: pointer;
        }
        .title li.active{
            background-color: orangered;
            color: white;
        }
        .content{
            border: 1px solid #eee;
            padding: 10px;
            margin-top: 10px;
        }
    </style>
    <div id="app">
        <b-tabs>
            <b-tabs-item title="南京">
                <img src="https://img1.baidu.com/it/u=1959505243,1682424610&fm=26&fmt=auto" style="width: 100%;" />
            </b-tabs-item>
            <b-tabs-item title="北京">
                <ul>
                    <li>北京的烤鸭真好吃</li>
                    <li>北京的烤鸭真好吃</li>
                    <li>北京的烤鸭真好吃</li>
                </ul>
            </b-tabs-item>
            <b-tabs-item title="常州">
                <button>常州的鸭脖子真好吃</button>
                <button>常州的鸭脖子真好吃</button>
                <button>常州的鸭脖子真好吃</button>
            </b-tabs-item>
            <b-tabs-item title="无锡">
                <a href="#">无锡的小笼包真好吃</a>
                <a href="#">无锡的小笼包真好吃</a>
                <a href="#">无锡的小笼包真好吃</a>
            </b-tabs-item>
        </b-tabs>
    </div>
  <script>
        /* 设置为 false 以阻止 vue 在启动时生成生产提示 */
        Vue.config.productionTip = false
        // tab选项组件
        Vue.component('b-tabs-item', {
            // 定义组件的属性
            props:['title'],
            // 定义组件的模板
            template:`
                <li v-show="isShow">
                    <slot></slot>
                </li>
            `,
            data() {
                return {
                    //是否显示
                    isShow:false
                }
            },
            created() {
                // 在子组件的created生命周期函数中,可以获取到父组件的数据
                this.$parent.titles.push(this.title)
            },
        })
        // tab组件
        Vue.component('b-tabs', {
            template:`
                <div class="tabs">
                    <ul class="title">
                        <li @click="activeIndex=index" :class="{active:activeIndex===index}" v-for="(item,index) in titles" :key="index">{{item}}</li>
                    </ul>
                    <ul class="content">
                        <slot></slot>
                    </ul>
                </div>
            `,
            data() {
                return {
                    //高亮索引
                    activeIndex:0,
                    //定义titles数组
                    titles:[]
                }
            },
            watch:{
                //监听高亮索引
                activeIndex(val){
                    //先隐藏所有的子组件
                    this.$children.forEach(c=>c.isShow=false)
                    //再显示当前高度的子组件
                    this.$children[val].isShow = true
                }
            },
            // 父组件挂载完成时,所有的子组件一定全部都挂载完成了
            mounted() {
                this.$children[this.activeIndex].isShow = true
            },
        })
        new Vue({
            el:'#app',
        })
    </script>

组件化的核心思想:

如果我们将一个应用程序所有的逻辑都放在一个组件中,那么这个组件就会变成非常的臃肿和难以维护;
并且在真实开发中,我们会有很多的内容和代码逻辑,项目扩展性和可维护性是非常差的;
所以,在真实的开发中,我们会对组件进行拆分,拆分成一个个功能的小组件。

所以组件化的核心思想应该是对组件进行拆分,拆分成一个个小的组件;再将这些组件组合嵌套在一起,最终形成我们的应用程序

我们可以按照如下的方式进行拆分:


12121212121212121.png

按照如上的拆分方式后,我们开发对应的逻辑只需要去对应的组件编写就可

组件的通信

在开发过程中,我们会经常遇到需要组件之间相互进行通信,根据组件之间的关系可以分为父子组件通信非父子组件通信。
在一个Vue项目中,组件之间的通信是非常重要的环节,所以接下来我们就具体学习一下组件之间是如何相互之间传递数据的

父子组件之间通信的方式

父子组件之间如何进行通信呢?
父组件传递给子组件:通过props属性;
子组件传递给父组件:通过$emit触发事件;

22222222222.png

父组件传递给子组件

在开发中很常见的就是父子组件之间通信,比如父组件有一些数据,需要子组件来进行展示:
这个时候我们可以通过props来完成组件之间的通信;

什么是Props呢?

Props是你可以在组件上注册一些自定义的attribute;
父组件给这些attribute赋值,子组件通过attribute的名称获取到对应的值;

Props有两种常见的用法:

1.字符串数组,数组中的字符串就是attribute的名称;
2.对象类型,对象类型我们可以在指定attribute名称的同时,指定它需要传递的类型是否是必须的默认值等等;

具名插槽

<div id="app">
    <b-box>
        <!-- template标签指定它里面的内容在哪一个具体的插槽中呈现 -->
        <template v-slot:header>
            <h4>好好学习</h4>
            <h4>天天向上</h4>
        </template>
        <template v-slot:default>
            <img src="https://img0.baidu.com/it/u=2293835918,4228668324&fm=253&fmt=auto&app=120&f=JPEG?w=556&h=500">
            <img src="https://ss0.baidu.com/-Po3dSag_xI4khGko9WTAnF6hhy/image/h%3D300/sign=e25abb7779061d95624631384bf50a5d/5ab5c9ea15ce36d39e62417f2df33a87e950b11f.jpg">
        </template>
        <!-- v-slot:的简写是# -->
        <template #footer>
            <a href="http://www.baidu.com">百度</a>
            <a href="http://www.taobao.com">淘宝</a>
        </template>
    </b-box>
</div>
// 在组件内部通过slot标签定义插槽,在通过name属性给插槽定义名字,这样的插槽称之为:具名插槽。
// 插槽的默认名称是:default。如果有多个插槽,允许其中一个插槽不定义名称。
Vue.component('b-box', {
    template:`
    <div class="box">
    <h2>我是组件</h2>
    <div class="header">
    <slot name="header"></slot>
    </div>
    <div class="main">
    <slot></slot>
    </div>
    <div class="footer">
    <slot name="footer"></slot>    
    </div>
    </div>
    `
})
new Vue({
    el:'#app',
})

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

推荐阅读更多精彩内容