Vue3.0(二):Vue组件化基础 - 脚手架

Vue组件化基础 - 脚手架

Vue的组件化

  • 我们在处理一些任务量比较庞大的工作时候,会将工作内容进行拆分,分步骤完成

  • 而组件化的思想正式如此,对于一个庞大的项目,我们可以将其拆分成一个个的小功能,分步骤进行实现

  • 组件化是Vue的核心思想

    • 在前面的学习中,我们 在createApp中传入了一个App对象,这个对象的本质其实就是一个组件
    <div id="app"><div v-for="item in arr" :key="item">{{item}}</div>
    </div>
    <script>//使用Vueconst App = {data() {return {arr: [1, 2, 3],};},}const app = Vue.createApp(App);//挂载app.mount("#app");
    </script>
    
    • 任何应用都会被抽象成一颗组件树

image.png

注册组件的方式

分为全局组件注册:任何地方都可以用

局部组件注册:

注册全局组件

  • 全局组件需要使用 app进行注册
  • 通过 component方法传入组件名称,组件对象即可注册一个全局组件
<div id="app"><my-component></my-component>
</div>
<script>const App = {};//全局组件对象const myComponent = {template: `<h2>我是一个组件</h2>`,};//使用Vueconst app = Vue.createApp(App);//注册全局组件//传入全局组件的名称以及对象app.component("my-component", myComponent);//挂载app.mount("#app");
</script>
  • 组件的名称
    • 使用短横线分隔符:my-component进行命名,使用的时候 <my-component></my-component>
    • 使用大驼峰命名法:MyComponent进行命名,使用的时候 <my-component></my-component>或者 <MyComponent></MyComponent>

注册局部组件

全局组件往往是在程序一开始的时候,就会全局组件注册完成,但是有些组件我们并为使用过,在打包的时候,会增加打包文件的体积

因此局部组件是开发中常用的

  • 通过 components属性进行注册
  • 要明确要在哪里使用该组件
<div id="app"><my-component></my-component><my-item></my-item>
</div>
<script>const App = {components: {//key就是组件的名称,后面跟着组件对象"my-component": {template: `<h2>我是一个组件</h2>`,},//第二个局部组件MyItem: {template: `<h2>我是一个组件Item</h2>`,},},};//使用Vueconst app = Vue.createApp(App);//挂载app.mount("#app");
</script>
  • 局部组件与全局组件的区别就是
    • 全局组件可以在任意组件内使用
    • 而局部组件只能在定义的组件的内部使用:比如 MyItem组件不能再 my-component组件中使用

Vue的开发模式

  • 在真正开发Vue项目的时候,我们是通过创建一个 Vue文件进行开发的
  • 而浏览器是不认识 Vue文件的,此时我们可以借助打包工具 webpack/vite等,进行打包
  • Vue文件转换成JS对象,这样浏览器就可以识别

image.png

单文件的特点

上面说的Vue文件实际上就是一个单文件

  • 以下就是一个简单的 Vue文件

image.png

Vue CLI脚手架

为了让浏览器能够正常渲染Vue文件,可以使用Vue CLI搭建相关环境

  • 在真实的开发中,我们通常会使用 脚手架来创建一个项目,Vue项目我们使用的就是Vue的脚手架
  • Vue的脚手架就是 Vue CLI
    • 我们可以通过 CLI选择项目的配置和创建出我们的项目
    • Vue脚手架已经 内置了webpack的相关配置,不需要从零开始配置

安装和脚手架

  • 通过 npm install @vue/cli -g全局安装 Vue脚手架

image.png

  • 接下来我们就可以使用 Vue脚手架创建项目了
  • 使用 vue create 项目名称创建一个项目
    • 注意 项目名称中不能含有大写字母
  • 接下来选择项目的配置项
    • 我们选择自定义配置项

image.png

  • 根据个人需求选择下面的选项即可

image.png

  • 选择创建Vue项目的版本
    • 此处我们选择 Vue3版本

image.png

  • 针对于 Babel等工具配置项的选项
    • 我们选择将配置项单独生成一个文件

image.png

  • 以下还有一些内容的配置

image.png

  • 而后等待项目自动生成即可
  • 进入到项目目录中,使用 npm run serve命令即可运行项目

Vue项目的目录分析

  • 整体的项目目录如下

image.png

  • node_modules:项目的依赖包
  • public:里面的两个文件是项目的图标,以及html模板(用于打包时候自动生成的html)
  • src:用于编写源代码
  • .browserslistrc:进行浏览器适配的,比如写了ES6+以上的代码,根据适配的浏览器,决定是否转化,会在caniuse中去查找相应的内容
  • .gitignore:git的忽略文件
  • babel.config.js:babel工具的配置项
  • jsconfig.json:给vscode使用,可以拥有更好的友好提示
  • package-lock.js package.json:安装依赖的版本,执行脚本等
  • vue.config.js:可以在这里对webpcak的打包工具进行设置等操作

src文件夹中的main入口文件,以及App.vue文件

  • main.js是项目的入口文件
    • 这和之前写的代码时一样的
    • 之前我们通过 Vue.createApp(App)创建一个Vue实例,而这是通过 import引入Vue
    • 该文件中,还引入了 App.vue文件,并进行挂载
    • 在此处我们可以注册全局组件
import { createApp } from "vue";
import App from "./App.vue";
import HelloWorld from "./components/HelloWorld";const app = createApp(App);
//注册全局组件
//直接在任意vue文件中使用即可
app.component("hello-world", HelloWorld);//挂载
app.mount("#app");
  • App.vue文件就是根组件
    • 可以在里面注册局部组件
<template><h2>{{ title }}</h2><HelloWorld></HelloWorld>
</template><script>
import HelloWorld from "./components/HelloWorld.vue";
export default {//注册局部组件components: {//这是对象的增强写法,等同于HelloWorld:HelloWorldHelloWorld,},data() {return {title: "zhangcheng",};},
};
</script><style></style>
  • 因此对于今后的开发就变成了以下的情况

image.png

其他创建vue项目的方法

使用npm init vue@latest

  • 运行 npm init vue@latest命令创建项目

    • 首先会安装一个本地工具 : create-vue
    • 使用 create-vue创建一个vue项目
  • 且是使用 vite进行打包的,不是使用webpack进行打包

  • 输入完命令,会询问是否安装 vue-create工具

    • 输入 y

image.png

  • 而后根据需要进行如下配置

image.png

  • 最后根据提示,安装相应的依赖包,即可运行项目

image.png

组件化 - 组件间通信

认识组件的嵌套

  • 在根组件中,我们可以引入各种小组件,完成组件嵌套
<template><div><!-- 头部 --><header-com></header-com><!-- 内容 --><content-com></content-com><!-- 底部 --><footer-com></footer-com></div>
</template><script>
import HeaderCom from "./components/HeaderCom.vue";
import ContentCom from "./components/ContentCom.vue";
import FooterCom from "./components/FooterCom.vue";
export default {//注册局部组件components: {HeaderCom,ContentCom,FooterCom,},data() {return {title: "zhangcheng",};},
};
</script><style></style>

父子组件之间的通信

  • 父组件传递给子组件 : 通过props属性
  • 组组件传递给父组件:通过$emit触发事件

image.png

组件间通信-父传子

在以上案例中,相当于是App.vue中的数据,要传递给HeaderCom.vue/ContentCom.vue/FooterCom.vue

  • 在子组件中通过 props接收父组件传递过来的参数

  • 什么是Props

    • Props是可以在组件上注册一些自定义的attribute
    • 父组件给 这些attribute赋值子组件通过attribute的名称获取对应的值
  • Props有两种常见的用法

    • 方式一:字符串数组
      • 弊端:不能对传入的数据进行类型验证
      • 没有默认值
    • 方式二:对象类型

image.png

type的类型都是哪些
  • 常见的类型
String
Number
Boolean
Array
Object
Date
Function
Symbol
对象类型的其他写法
  • 接收的是一个对象/数组
props: {//若是对象类型,则需要用函数返回obj:{type:Object,//因为对象类型,多个组件共享该对象的话,其中一个组件进行了更改,所有的都会更改default:()=>{return {name:"zhangcheng"}} },arr:{type:Array,default(){return [1,2,3]}}},
  • 声明多个类型
props: {//可以接收多个类型age: [Number,String],},

组件间通信-子传父

在以上案例中,相当于是HeaderCom.vue/ContentCom.vue/FooterCom.vue中的数据,要传递给App.vue

  • 用到子传父的时候
    • 子组件中有一些事件发生的时候,比如子组件中发生了点击,父组件需要切换内容
    • 子组件中有一些内容想要传递给父组件
  • 用法
    • 首先在子组件中 通过 $emit发射一个事件
    • 在父组件引用子组件的地方 使用发射的事件
    • 在父组件中定义一个事件 用于接收子组件传入的数据

image.png

  • Vue3中,增加了emits属性,父组件在使用子组件发射参数的时候能够得到友好的提示,同时可以对其进行验证(很少用)

image.png

非Prop的attribute

  • 当子组件中设置了 prop进行接收父组件传进来的数据,则该attribute就是prop的attribute
  • 但是 当父组件传入了一个attribute,是子组件中没有声明的,那就是非prop的attribute
    • class没有在子组件的prop中声明,此时class就是 非prop的attribute
<childCom class="active"></childCom>
  • 非prop的attribute会自动给子组件的根节点
//父组件引用了子组件
<childCom class="active"></childCom>-----------------------
//子组件
<template><div>其他元素</div>
</template>
//相当于在子组件中的div中添加了class="active"
  • 如果我们不想,默认添加给根节点,同时还想将其给子组件中的其他元素
    • 首先通过 inheritAttrs属性禁止非prop的attribute添加到根节点中
    • 之后通过 $attrs.属性名进行获取
<template><div><div :class="$attrs.class">{{ name }}</div><div v-bind="$attrs">{{ age }}</div></div>
</template><script>
export default {//阻止非prop的attribute添加到根节点中inheritAttrs: false,props: ["name", "age"],data() {return {};},methods: {},
};
</script>

插槽 - Slot

子组件中的数据可以根据传入的数据进行变化

而子组件中的元素是否可以?

  • 比如,现在有一个子组件,我们想让其根据不同的要求,显示 文本/按钮/图片等内容
  • 此时我们就需要用到 slot插槽这个功能

基本使用

  • 用法
    • 在子组件中,写入插槽
    • 父组件引用子组件的内部写入想要显示的元素即可

image.png

默认内容

当我们没有给子组件传入内容,但是又想让子组件默认显示一些内容,可以在slot中写入默认的元素

image.png

多个插槽-具名插槽

  • 如果子组件中,有多个插槽,应当使用 具名插槽
  • 在 子组件的插槽中 使用 name属性,给插槽起名字
  • 父组件中传入元素的时候 使用 v-slot:插槽名字
  • 不带name属性的slot,实际上有一个默认不显示的名字,为 default
-----子组件
<template><div><div class="left"><slot name="left"></slot></div><div class="right"><slot name="right"></slot></div></div>
</template>-------父组件
<template><childCom><!--需要使用template进行包裹--><template v-slot="left"><button>按钮</button></template><template v-slot="right"><span>文本</span></template></childCom>
</template>
  • 具名插槽的简写 可以用 #代替v-slot
-------父组件
<template><childCom><!--需要使用template进行包裹--><template #"left"><button>按钮</button></template><template #"right"><span>文本</span></template></childCom>
</template>

动态插槽名

当我们在父组件中使用 v-slot的时候,可以指定元素插入到哪个插槽中

但是我们不希望冒号后面的内容写死,即 v-slot:“right”,right是动态的

<AddComponts @add="countAdd"><!--将冒号后面,写上 [],里面写入变量即可--><template v-slot:[posion]>
<button>123</button></template>
</AddComponts>

作用域插槽

  • 首先看一下需求
    • 父组件给子组件传递了data数据
    • 子组件中有一个插槽
    • 父组件引用了子组件的插槽,且填入元素
    • 想让填入的元素中的数据,使用父组件传给子组件的数据
  • 此时我们就可以使用作用域插槽

image.png

image.png

非父子组件通信

  • 在实际开发中,我们有时候会遇到,非父子组件之间的传值
  • 比如 App.vue向SearchCom.vue传值,或者MainCom.vue向FootCom.vue传值

image.png

  • 通常我们在非父子组件通信的时候,使用的是 Provide/Inject(不常用)和事件总线

Provide和Inject

仅能用作有关联的组件,没有关联的组件不能使用

  • Provide和Inject用于非父子组件之间共享数据
  • 父组件有一个 provide选项来提供数据
  • 子组件有一个 Inject选项来使用这些数据
  • 同时父组件不知道要把数据传给谁,而子组件不知道数据的来源是哪里

image.png

  • 通常提供数据的一方 provide写成函数的形式
    • 若提供的数据为响应式的话,需要用到 computed函数

事件总线

以上方法的弊端就是,无法实现兄弟组件之间的通信,因此选用事件总线

  • 在Vue2版本中,Vue是有事件总线的功能 o n , on, on,emit等
  • 但是在Vue3版本中,取消了事件总线的功能,因此官方推荐使用了三方库 mitt
  • 同时我们自己也可以自己封装一个事件总线的工具函数
    • 在JS高级的文章中,有过封装
  • 首先封装一个自己的事件总线工具
class zcEventBus {constructor() {this.obj = {};}//on事件需要接收两个参数,事件名称,回调函数on(eventName, callBackFn) {//采用对象的结构,一个事件名称,后面跟着数组,可以包含多个事件//{eventName:[fn1,fn2]}//但是第一次执行的时候,this.obj[eventName]不是一个数组,需要进行判断let eventArr = this.obj[eventName];//第一次肯定是undefined,当!eventArr的时候,为trueif (!eventArr) {//将this.obj[eventName]初始化数组eventArr = [];this.obj[eventName] = eventArr;}//相当于在this.obj[eventName]中push了事件eventArr.push(callBackFn);}//emit事件需要接收两个参数,事件名称,以及参数emit(eventName, ...arg) {console.log(eventName);//需要遍历eventName对用的事件数组,并依次执行//首先判断是否存在,不存在直接返回let eventArr = this.obj[eventName];if (!eventArr) return;//若存在,则直接遍历执行for (const fn of eventArr) {fn(...arg);}}
}export default new zcEventBus();
  • 在组件中引用
import EventBus from "./components/EventBus.vue";
  • 在提供数据的一方使用 emit方法
emitData() {//传入事件的名称,以及参数zcEventBus.emit("zcEventBus", "zhangcheng");
},
  • 在接收数据的一方使用 on方法
created() {zcEventBus.on("zcEventBus", (data) => {console.log("父组件收到了数据", data);});
},

image.png

  • 规范的写法,应当在 unmounted生命周期中取消相应的事件总线

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Intellij IDEA各种调试+开发中常见bug

Intellij IDEA中使用好Debug&#xff0c;主要包括如下内容&#xff1a; 一、Debug开篇 ①、以Debug模式启动服务&#xff0c;左边的一个按钮则是以Run模式启动。在开发中&#xff0c;我一般会直接启动Debug模式&#xff0c;方便随时调试代码。 ②、断点&#xff1a;在左边行…

docker重建镜像

DockerFile如下&#xff1a; FROM k8s-registry.qhtx.local/base/centos7-jdk8-haitong0704RUN yum -y update && yum install -y python3-devel && yum install -y python36 RUN mv /usr/bin/python /usr/bin/python_old RUN ln -s /usr/bin/python3 /usr/bi…

windows安装Visual Studio Code,配置C/C++运行环境(亲测可行)

一.下载 Visual Studio Code https://code.visualstudio.com/ 二.安装 选择想要安装的位置: 后面的点击下一步即可。 三.下载编译器MinGW vscode只是写代码的工具&#xff0c;使用编译器才能编译写的C/C程序&#xff0c;将它转为可执行文件。 MinGW下载链接&#xff1a;…

Linux(一)

介绍 常见的操作系统(windows、IOS、Android、MacOS, Linux, Unix)&#xff1b; Linux是一个开源、免费的操作系统&#xff0c;其稳定性、安全性、处理多并发已经得到业界的认可&#xff1b;【免费只是说linux的内核免费】 目前很多企业级的项目(c/c/php/python/java/go)都会…

免费的hyper-v虚机添加U盘的二种方法

windows集成了hyper-v&#xff0c;hyper-v可以安装linux&#xff0c;windows等虚机&#xff0c;基本可以满足工作&#xff0c;实验之需。但是不少人反映hyper-v不方便连接U盘&#xff0c;这样子文件传输不是很方便。 网上有方法说在虚机设置中添加磁盘&#xff0c;首先到物理机…

图数据库(neo4j)在工业控制中的应用

最近看到国外发表的一篇文章&#xff0c;提到将OPC UA 模型映射到neo4j图模型数据库中&#xff0c;通过GraphQL 访问效率很高&#xff0c;顿时感觉自己眼睛一亮&#xff0c;这是一个好主意。 图模型 事物的模型中&#xff0c;除了它自身的某些特征之外&#xff0c;还包括它与其…

kubectl命令

kubenetes部署服务的流程 以部署一个nginx服务来说明kubernetes系统各个组件调用关系&#xff1a; 1. 首先要明确&#xff0c;一旦kubernetes环境启动之后&#xff0c;master和node都会将自身的信息存储到etcd数据库中 2. 一个nginx服务的安装请求会首先被发送到master节点的ap…

世界各国都在追求“主权人工智能能力”,国家级人工智能硬件需求将剧增

NVIDIA的CEO黄仁勋最近在接受媒体采访时指出&#xff0c;世界各国都打算在本国内建立和运行自主的人工智能基础设施&#xff0c;这将全面带动NVIDIA硬件产品需求的飙升。黄仁勋表示&#xff0c;包括印度、日本、法国和加拿大在内的国家政府都在讨论投资“国家主权人工智能能力”…

利用jmeter完成简单的压力测试

Jmeter是一个非常好用的压力测试工具。Jmeter用来做轻量级的压力测试&#xff0c;非常合适&#xff0c;只需要十几分钟&#xff0c;就能把压力测试需要的脚本写好。 1、什么是压力测试 顾名思义&#xff1a;压力测试&#xff0c;就是 被测试的系统&#xff0c;在一定的访问压…

从小白到入门webrtc音视频通话

0. 写在前面 先会骑车&#xff0c;再研究为什么这么骑&#xff0c;才是我认为学习技术的思路&#xff0c;底部付了demo例子&#xff0c;根据例子上面的介绍即可运行。 1. 音视频通话要用到的技术简介 websocket 介绍&#xff1a;1. 服务器可以向浏览器推送信息&#xff1b;2…

Java SWT Composite 绘画

Java SWT Composite 绘画 1 Java SWT2 Java 图形框架 AWT、Swing、SWT、JavaFX2.1 Java AWT (Abstract Window Toolkit)2.2 Java Swing2.3 Java SWT (Standard Widget Toolkit)2.4 Java JavaFX 3 比较和总结 1 Java SWT Java SWT&#xff08;Standard Widget Toolkit&#xff…

Yarn常见问题处理

任务出现container OOM异常导致作业失败 原因 Container内存不足或者作业数据倾斜 解决方案 检查Container相关参数,判断是否设置过小(低于4GB)。如果Container小于4GB,优先考虑调大当前作业container大小,如果是Tez任务,还需要同步调整以下参数 # tez container size…

STM32--SPI通信协议(1)SPI基础知识总结

前言 I2C (Inter-Integrated Circuit)和SPI (Serial Peripheral Interface)是两种常见的串行通信协议&#xff0c;用于连接集成电路芯片之间的通信&#xff0c;选择I2C或SPI取决于具体的应用需求。如果需要较高的传输速度和简单的接口&#xff0c;可以选择SPI。如果需要连接多…

探索设计模式的魅力:从单一继承到组合模式-软件设计的演变与未来

设计模式专栏&#xff1a;http://t.csdnimg.cn/nolNS 在面对层次结构和树状数据结构的软件设计任务时&#xff0c;我们如何优雅地处理单个对象与组合对象的一致性问题&#xff1f;组合模式&#xff08;Composite Pattern&#xff09;为此提供了一种简洁高效的解决方案。通过本…

记录下ibus-libpinyin输入法的重新安装

目前的版本为: 首先把现在的ibus-libpinyin卸了 sudo apt-get --purge remove ibus-libpinyin sudo apt-get autoremove 安装教程请参考 Installation libpinyin/ibus-libpinyin Wiki GitHub yilai sudo apt install pkg-config sudo apt-get install libglib2.0-de…

CSS要点总结

一、CSS 快速入门 <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><title>css 快速入门</title><!-- 解读1. 在 head 标签内&#xff0c;出现了 <style type"text/css"></style…

初探unity中的ECS

ECS是一种软件架构模式&#xff0c;就像MVC一样。ECS最早在游戏《守望先锋》中提及到的相关链接。ECS具体是指实体&#xff08;entity&#xff09;、 组件&#xff08;component&#xff09;和系统&#xff08;system&#xff09;&#xff1a; 实体&#xff1a;实体是一个ID&a…

从源代码看Chrome 版本号

一直以来都是用Chrome 浏览器&#xff0c;但是看到Chrome 点分4 组数据的表达方式&#xff0c;总是感觉怪怪的&#xff0c;遂深入源代码了解她的版本号具体表示的内容 chrome 浏览器中显示的版本号 源代码中的版本号标识 版本号文件位于 chrome/VERSION &#xff0c; 看到源代…

SpringBoot实战(二十六)集成SFTP

目录 一、SFTP简介二、SpringBoot 集成2.1 Maven 依赖2.2 application.yml 配置2.3 DemoController.java 接口2.4 SftpService.java2.5 DemoServiceImpl.java 实现类2.6 SftpUtils.java 工具类2.7 执行结果1&#xff09;上传文件2&#xff09;下载文件3&#xff09;重命名文件&…

全链游戏的未来趋势与Bridge Champ的创新之路

为了充分探索全链游戏的特点和趋势&#xff0c;以及Bridge Champ如何作为一个创新案例融入这一发展脉络&#xff0c;我们需要深入了解这两者之间的互动和相互影响。全链游戏&#xff0c;或完全基于区块链的游戏&#xff0c;代表了游戏行业的一个重要转型&#xff0c;它们利用区…