Vue基础入门讲义(四)-组件化

news2025/1/19 14:16:21

在这里插入图片描述

文章目录

    • 1.引言
    • 2.定义全局组件
    • 3.组件的复用
    • 4.局部注册
    • 5.组件通信
      • 5.1.父向子传递props
      • 5.2.传递复杂数据
      • 5.3.子向父的通信

1.引言

在大型应用开发的时候,页面可以划分成很多部分。往往不同的页面,也会有相同的部分。例如可能会有相同的头部导航。

但是如果每个页面都独自开发,这无疑增加了开发的成本。所以会把页面的不同部分拆分成独立的组件,然后在不同页面就可以共享这些组件,避免重复开发。

2.定义全局组件

通过Vue的component方法来定义一个全局组件。

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>vuejs测试</title>
</head>
<body>

<div id="app">
    <!--使用定义好的全局组件-->
    <counter></counter>
</div>
<script src="node_modules/vue/dist/vue.js"></script>
<script type="text/javascript">
    //定义组件
    const counter = {
        template: "<button @click='num++'>你点击了{{num}}次;我记住了</button>",
        data() {
            return {num: 0}
        }
    };

    //全局注册组件;参数1:组件名称,参数2:组件
    Vue.component("counter", counter);

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

</script>
</body>
</html>
  • 组件其实也是一个Vue实例,因此它在定义时也会接收:data、methods、生命周期函数等
  • 不同的是组件不会与页面的元素绑定,否则就无法复用了,因此没有el属性。
  • 但是组件渲染需要html模板,所以增加了template属性,值就是HTML模板
  • 全局组件定义完毕,任何vue实例都可以直接在HTML中通过组件名称来使用组件了
  • data的定义方式比较特殊,必须是一个函数。

效果:
在这里插入图片描述

3.组件的复用

定义好的组件,可以任意复用多次:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>vuejs测试</title>
</head>
<body>

<div id="app">
    <!--使用定义好的全局组件-->
    <counter></counter>
    <counter></counter>
    <counter></counter>
</div>
<script src="node_modules/vue/dist/vue.js"></script>
<script type="text/javascript">
    //定义组件
    const counter = {
        template: "<button @click='num++'>你点击了{{num}}次;我记住了</button>",
        data() {
            return {num: 0}
        }
    };

    //全局注册组件;参数1:组件名称,参数2:组件
    Vue.component("counter", counter);

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

</script>
</body>
</html>

在这里插入图片描述
你会发现每个组件互不干扰,都有自己的num值。怎么实现的?

组件的data属性必须是函数!

当定义这个 <counter> 组件时,它的data 并不是像这样直接提供一个对象:

data: {
    num: 0
}

取而代之的是,一个组件的 data 选项必须是一个函数,因此每个实例可以维护一份被返回对象的独立的拷贝:

data: function () {
		return {
		num: 0
      }
}

如果 Vue 没有这条规则,点击一个按钮就会影响到其它所有实例!

4.局部注册

一旦全局注册,就意味着即便以后你不再使用这个组件,它依然会随着Vue的加载而加载。

因此,对于一些并不频繁使用的组件,会采用局部注册。

在外部定义一个对象,结构与创建组件时传递的第二个参数一致:

然后在Vue中使用它:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>vuejs测试</title>
</head>
<body>
<div id="app">
    <!--使用定义好的全局组件-->
    <counter></counter>
    <counter></counter>
    <counter></counter>
</div>
<script src="node_modules/vue/dist/vue.js"></script>
<script>
    //定义组件
    const counter = {
        template: "<button @click='num++'>你点击了{{num}}次;我记住了</button>",
        data() {
            return {num: 0}
        }
    };
    //全局注册组件;参数1:组件名称,参数2:组件
    //Vue.component("counter", counter);
    var app = new Vue({
        el: "#app",
        //局部注册组件
        components: {
            counter: counter
        }
    });
</script>
</body>
</html>
  • components就是当前vue对象子组件集合。

    • 其key就是子组件名称
    • 其值就是组件对象的属性
  • 效果与刚才的全局注册是类似的,不同的是,这个counter组件只能在当前的Vue实例中使用

5.组件通信

通常一个单页应用会以一棵嵌套的组件树的形式来组织:
在这里插入图片描述

  • 页面首先分成了顶部导航、左侧内容区、右侧边栏三部分
  • 左侧内容区又分为上下两个组件
  • 右侧边栏中又包含了3个子组件

各个组件之间以嵌套的关系组合在一起,那么这个时候不可避免的会有组件间通信的需求。

5.1.父向子传递props

比如有一个子组件:

	Vue.component("introduce",{
	// 直接使用props接收到的属性来渲染页面
	template:'<h3>{{title}}</h3>',
	props:[title] // 通过props来接收一个父组件传递的属性
})
  • 这个子组件中要使用title属性渲染页面,但是自己并没有title属性
  • 通过props来接收父组件属性,名为title

父组件使用子组件,同时传递title属性:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>vuejs测试</title>
</head>
<body>
<div id="app">
    <!--使用定义好的全局组件-->
    <introduce :title="msg"></introduce>
</div>
<script src="node_modules/vue/dist/vue.js"></script>
<script>

    //定义组件
    const introduce = {
        //使用props属性title的值渲染模版
        template: "<h2>{{title}}</h2>",
        //定义接收来自父组件的属性
        props: ["title"]
    };

    //全局注册组件;参数1:组件名称,参数2:组件
    Vue.component("introduce", introduce);

    var app = new Vue({
        el: "#app",
        data: {
            msg: "父组件中的msg属性的内容"
        }
    });
</script>
</body>
</html>

效果:

在这里插入图片描述

5.2.传递复杂数据

定义一个子组件:

    const myList = {
        template: '\
            <ul>\
            <li v-for="item in items" :key="item.id">{{item.id}} : {{item.name}}</li>\
            </ul>\
            ',
        props: { // 通过props来接收父组件传递来的属性
            items: {// 这里定义items属性
                type: Array,// 要求必须是Array类型
                default: [] // 如果父组件没有传,那么给定默认值是[]
            }
        }
    };
  • 这个子组件可以对 items 进行迭代,并输出到页面。
  • 但是组件中并未定义items属性。
  • 通过props来定义需要从父组件中接收的属性
    • items:是要接收的属性名称
      • type:限定父组件传递来的必须是数组,否则报错;type的值可以是Array或者Object(传递对象的
        时候使用)
      • default:默认值,
default,如果是对象则需要写成方法的方式返回默认值。如:
default(){
     return {"xxx":"默认值"};
}

页面内容:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>vuejs测试</title>
</head>
<body>
<div id="app">
    <h2>学习的课程有:</h2>
    <!-- 接受来自父组件的属性值,使用v-bind指向父组件的属性lessons;注意使用my-list -->
    <my-list :items="lessons"></my-list>
</div>
<script src="node_modules/vue/dist/vue.js"></script>
<script>
    //定义组件
    const myList = {
        //可以使用双引号、单引号或者如下使用的 ` 飘号
        template: `
            <ul>
            <li v-for="item in items" :key="item.id">{{item.id}}--{{item.name}}</li>
            </ul>
        `,
        //定义接收来自父组件的属性
        props: {
        //定义模版中使用的属性
            items: {
        //必须为数组类型
                type: Array,
        //默认为空数组
                default: []
            }
        }
    };
    var app = new Vue({
        el: "#app",
        data: {
            msg: "父组件中的msg属性的内容",
            lessons: [{"id": 1, "name": "Java"},
                {"id": 2, "name": "PHP"},
                {"id": 3, "name": "前端"}
            ]
        },
        //注册组件
        components: {
        //如果组件key和value一致可以简写如下
            myList
        }
    });
</script>
</body>
</html>

效果:
在这里插入图片描述

5.3.子向父的通信

来看这样的一个案例:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>vuejs测试</title>
</head>
<body>
<div id="app">
    <h2>num = {{num}}</h2>
    <!--使用定义好的全局组件-->
    <counter :snum="num"></counter>
</div>
<script src="node_modules/vue/dist/vue.js"></script>
<script>

    //定义组件
    const counter = {
        //组件只能是一个元素里面包裹其他元素;如下面,一个div包含两个按钮
        template: `
        <div>
        <button @click="snum++">+</button>
        <button @click="snum--">-</button>
        </div>
        `,
        props: ["snum"]
    };

    //全局注册组件;参数1:组件名称,参数2:组件
    Vue.component("counter", counter);

    var app = new Vue({
        el: "#app",
        data: {
            num: 0
        }
    });
</script>
</body>
</html>
  • 子组件接收父组件的num属性
  • 子组件定义点击按钮,点击后对num进行加或减操作

尝试运行,好像没问题,点击按钮试试:
在这里插入图片描述
子组件接收到父组件属性后,默认是不允许修改的。怎么办?
既然只有父组件能修改,那么加和减的操作一定是放在父组件:

var app = new Vue({
        el: "#app",
        data: {
            num: 0
        },
        methods: {
            //父组件中定义操作num的方法
            numPlus() {
                this.num++;
            },
            numReduce() {
                this.num--;
            }
        }
    });

但是,点击按钮是在子组件中,那就是说需要子组件来调用父组件的函数,怎么做?
可以通过v-on指令将父组件的函数绑定到子组件上

<div id="app">
    <h2>num = {{num}}</h2>
    <!--使用定义好的全局组件-->
    <counter @plus="numPlus" @reduce="numReduce" :snum="num"></counter>
</div>

然后,当子组件中按钮被点击时,调用绑定的函数:

//定义组件
    const counter = {
        //组件只能是一个元素里面包裹其他元素;如下面,一个div包含两个按钮
        template: `
        <div>
        <button @click="incrNum">+</button>
        <button @click="decrNum">-</button>
        </div>
        `,
        props: ["snum"],
        methods: {
            //点击模板中使用的方法
            incrNum() {
                return this.$emit("plus");
            },
            decrNum() {
                return this.$emit("reduce");
            }
        }
    };

完成页面如下:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>vuejs测试</title>
</head>
<body>
<div id="app">
    <h2>num = {{num}}</h2>
    <!--使用定义好的全局组件-->
    <counter @plus="numPlus" @reduce="numReduce" :snum="num"></counter>
</div>
<script src="node_modules/vue/dist/vue.js"></script>
<script>
    //定义组件
    const counter = {
//组件只能是一个元素里面包裹其他元素;如下面,一个div包含两个按钮
        template: `
<div>
<button @click="incrNum">+</button>
<button @click="decrNum">-</button>
</div>
`,
        props: ["snum"],
        methods: {
//点击模板中使用的方法
            incrNum() {
                return this.$emit("plus");
            },
            decrNum() {
                return this.$emit("reduce");
            }
        }
    };
    
    //全局注册组件;参数1:组件名称,参数2:组件
    Vue.component("counter", counter);
    var app = new Vue({
        el: "#app",
        data: {
            num: 0
        },
        methods: {
//父组件中定义操作num的方法
            numPlus() {
                this.num++;
            },
            numReduce() {
                this.num--;
            }
        }
    });
</script>
</body>
</html>
  • vue提供了一个内置的this.$emit函数,用来调用父组件绑定的函数

效果:
在这里插入图片描述
子组件不能直接修改父组件传递参数的引用或者基本类型参数值。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/386875.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

第二章SpringBoot基础学习

文章目录SpringBoot依赖管理特性依赖管理开发导入starter场景启动器SpringBoot自动配置特性自动配好Tomcat自动配好SpringMVC默认的包结构各种配置拥有默认值按需加载所有自动配置项SpringBoot注解底层注解ConfigurationImport导入组件Conditional条件装配ImportResource导入Sp…

Python入门自学进阶-Web框架——33、瀑布流布局与组合查询

一、瀑布流&#xff0c;是指页面布局中&#xff0c;在显示很多图片时&#xff0c;图片及文字大小不相同&#xff0c;导致页面排版不美观如上图&#xff0c;右边的布局&#xff0c;因为第一行第一张图片过长&#xff0c;第二行的第一张被挤到第二列了。示例&#xff1a;def flow…

大数据框架之Hadoop:MapReduce(八)常见错误及解决方案

1、导包容易出错。尤其Text和CombineTextInputFormat。 2、Mapper中第一个输入的参数必须是LongWritable或者NullWritable&#xff0c;不可以是IntWritable. 报的错误是类型转换异常。 3、java.lang.Exception: java.io.IOException: Illegal partition for 13926435656 (4)&…

51单片机LCD1602的使用

文章目录前言一、LCD1602简单介绍二、LCD1602中各个引脚的作用四、LCD1602命令解析1.写命令2.写数据3.清屏指令4.光标归位指令5.进入模式设置指令6.显示开关控制指令7.设定显示屏或光标移动方向指令三、LCD1602代码编写四、代码测试总结前言 本篇文章将为大家讲解LCD1602的使用…

CPU扫盲-CPU如何执行指令以及流水线技术

在CPU扫盲-CPU与指令集中阐述了CPU与指令集之间的关系&#xff0c;并在CPU扫盲-自研指令集中以创造者的身份深入讲解了指令集&#xff0c;这篇文章则是针对CPU的专场&#xff0c;以x86架构下的CPU为例具体分析一下CPU如何执行指令。 计算机基本硬件由控制器、储存器、运算器、输…

基于java的五子棋游戏设计

技术&#xff1a;Java、JSP等摘要&#xff1a;随着互联网迅速的发展&#xff0c;网络游戏已经成为人们普遍生活中不可或缺的一部分&#xff0c;它不仅能使人娱乐&#xff0c;也能够开发人的智力&#xff0c;就像本文所主要讲的五子棋游戏一样能挖掘人们聪明的才干与脑袋的机灵程…

【大数据 AI 人工智能】数据科学家必学的 9 个核心机器学习算法

如今,机器学习正改变着我们的世界。借助机器学习(ML),谷歌在为我们推荐搜索结果,奈飞在为我们推荐观看影片,脸书在为我们推荐可能认识的朋友。 机器学习从未像在今天这样重要。但与此同时,机器学习这一领域也充斥着各种术语,晦涩难懂,各种机器学习的算法每年层出不穷…

思科2.7.6 Packet Tracer - Implement Basic Connectivity(作业)

Packet Tracer - 实施基本连接地址分配表目标第 1 部分&#xff1a;对 S1 和 S2 执行基本配置第 2 部分&#xff1a;配置 PC第 3 部分&#xff1a;配置交换机管理界面背景信息在这个练习中&#xff0c;您会首先执行基本的交换机 配置。然后您会通过在交换机和 PC 上配置 IP 编址…

【C++】string

【C修炼秘籍】string 目录 【C修炼秘籍】string 文章目录 前言 一、标准库里的string 二、string常用接口功能简介&#xff08;具体使用和底层转到模拟实现&#xff09; 1、string类的常见构造函数 2、string类对象的容量操作 3、string类对象的访问及遍历操作 4、 string类对象…

数影周报:LastPass数据泄露事件最新细节

本周看点&#xff1a;LastPass&#xff1a;关键运维员工遭定向攻击&#xff1b;Waymo今年第二轮裁掉137名员工&#xff1b;国家网信办发布《个人信息出境标准合同办法》&#xff1b;京麦商家“取消订单页面”升级&#xff1b;“智研汇”获千万级天使轮投资......数据安全那些事…

ubuntu-8-安装nfs服务共享目录

Ubuntu最新版本(Ubuntu22.04LTS)安装nfs服务器及使用教程 ubuntu16.04挂载_如何在Ubuntu 20.04上设置NFS挂载 Ubuntu 20.04 设置时区、配置NTP同步 timesyncd 代替 ntpd 服务器 10.0.2.11 客户端 10.0.2.121 NFS简介 (1)什么是NFS NFS就是Network File System的缩写&#xf…

W800系列||STM32最小版|CKLINK|待完善|学习(3-2):自制cklink调试工具测试(win11系统识别错误待解决)

续前文&#xff1a; W800系列|ST-LINK|STM32最小版|HEX文件|CKLINK|DebugServer|学习&#xff08;3-1&#xff09;&#xff1a;自制cklink调试工具_打酱油的工程师的博客-CSDN博客 硬件接线 CK-LINK W806 3V3 3V3 RST RST&#xff08;复位脚&#xff09; TCK CLK&…

MySQL日志管理

日志管理在数据库保存数据时&#xff0c;有时候不可避免会出现数据丢失或者被破坏&#xff0c;这种时候&#xff0c;我们必须保证数据的安全性和完整性&#xff0c;就需要使用日志来查看或者恢复数据了数据库中数据丢失或被破坏可能原因&#xff1a;误删除数据库数据库工作时&a…

openpnp - error - 回位精度差的问题

文章目录openpnp - error - 回位精度差的问题概述齿隙矫正方法不能用openpnp默认的, 要自己选合适的方法ENDopenpnp - error - 回位精度差的问题 概述 用openpnp向导进行完x/y齿隙校正后, 进行回位精度测试. 在设备上挑选2个点: 主基准点次基准点 都是固定位置(将带mark点的…

Go中sync 包的 Once 使用

文章目录背景One 简介示例注意源码解读背景 在系统初始化的时候&#xff0c;某些代码只想被执行一次&#xff0c;这时应该怎么做呢&#xff0c;没有学习 Once 前&#xff0c;大家可能想到 声明一个标识&#xff0c;表示是否初始化过&#xff0c;然后初始化这个标识加锁&#x…

Lazada(来赞达)箱包什么产品好卖?东南亚热销国家选品分析

东南亚市场&#xff1a;存在巨大的跨境电商出口机遇 和2021年前对比&#xff0c;2022年越南、马来西亚等东南亚国家普遍实现了贸易正增长&#xff0c;欧美国家则多仍处于负增长状态。 同时2022年欧美等发达经济体通胀压力迅速抬升&#xff0c;这直接影响到国家间货币汇率&…

微信小程序如何配置并使用less?

微信小程序如何配置并使用less&#xff1f;1、在VScode中下载Less插件2、在微信小程序中依次点击如下按钮3、选中刚在vscode中下载安装的插件文件4、在设置中选中编辑器设置5、找到less进行json配置6、在json文件中的less.compile添加如下配置7、如何使用1、在VScode中下载Less…

深圳大学计软《面向对象的程序设计》实验7 拷贝构造函数与复合类

A. Point&Circle(复合类与构造) 题目描述 类Point是我们写过的一个类&#xff0c;类Circle是一个新的类&#xff0c;Point作为其成员对象&#xff0c;请完成类Circle的成员函数的实现。 在主函数中生成一个圆和若干个点&#xff0c;判断这些点与圆的位置关系&#xff0c;…

最佳iOS设备管理器imazing 2.16.9官网Mac/Windows下载电脑版怎么下载安装

imazing 2.16.9官网Mac/Windows下载电脑版是款针对苹果设备所打造的管理工具。iMazing为用户提供多种设备管理功能&#xff0c;每一位用户都能以自己的形式管理苹果设备。iMazing与苹果设备连接后&#xff0c;用户就可以轻松传输文件&#xff0c;浏览保存信息等。 应用介绍 iM…

员工入职流程自动化的原因

人和人之间的第一印象非常重要&#xff0c;一段缘分能不能开始&#xff0c;就看第一印象够不够给力了。其实&#xff0c;公司和新员工之间也存在着这样的关系&#xff0c;但也有些许差别。公司对新员工的第一印象&#xff0c;更多是从第一次见面的时候就产生了&#xff0c;而新…