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

Vue组件化基础 - 脚手架

Vue的组件化

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

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

  • 组件化是Vue的核心思想

    • 在前面的学习中,我们 在createApp中传入了一个App对象,这个对象的本质其实就是一个组件
    <div id="app">
        <div v-for="item in arr" :key="item">{{item}}</div>
    </div>
    <script>
        //使用Vue
        const 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>
        `,
    };
    //使用Vue
    const 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>
                `,
            },
        },
    };
    //使用Vue
    const 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:HelloWorld
    HelloWorld,
  },
  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的时候,为true
    if (!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生命周期中取消相应的事件总线

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

迅为RK3588开发板ubuntu和window互传图形界面直接拖拽进行文件传输

确保以及安装了 VMware Tools。如下图所示表示已安装过了。 和 windows 端文件夹间传输一样直接拖拽进去即可&#xff0c;如下图所示&#xff1a; 也可拖拽到终端&#xff0c;如下图所示&#xff1a; 更多内容可以B站搜索迅为RK3588开发板

【Java报错】显示错误“Error:java: 程序包org.springframework.boot不存在“

使用idea运行项目&#xff0c;显示错误信息如下&#xff1a; 原因是&#xff1a;idea配置的maven加载不到autoconfigure。 解决方案一&#xff1a; 第6步绕过证书语句如下&#xff1a; -Dmaven.wagon.http.ssl.insecuretrue -Dmaven.wagon.http.ssl.allowalltrue 打开终端&am…

算法学习——华为机考题库10(HJ64 - HJ69)

算法学习——华为机考题库10&#xff08;HJ64 - HJ69&#xff09; HJ64 MP3光标位置 描述 MP3 Player因为屏幕较小&#xff0c;显示歌曲列表的时候每屏只能显示几首歌曲&#xff0c;用户要通过上下键才能浏览所有的歌曲。为了简化处理&#xff0c;假设每屏只能显示4首歌曲&a…

2024最新版鸿蒙HarmonyOS开发工具安装使用指南

2024最新版鸿蒙HarmonyOS开发工具安装使用指南 By JacksonML 0. 什么是鸿蒙Harmony OS&#xff1f; 华为鸿蒙系统&#xff08;HUAWEI Harmony OS&#xff09;&#xff0c;是华为公司在2019年8月9日于东莞举行的华为开发者大会&#xff08;HDC.2019&#xff09;上正式发布的分…

JavaWeb:调出Maven面板

问题描述 情况说明&#xff1a;IDEA中找不到Maven面板&#xff0c;Maven面板如下图所示&#xff1a; 解决方案 选择 View > Appearance > Tool Window Bars&#xff1a; 然后就会出现Maven面板了。

SSO单点登录系统?or 统一身份中台?

单点登录&#xff08;Single Sign-On&#xff0c;简称 SSO&#xff09;是解决多个应用系统多次认证登录的一种方式&#xff0c;从应用侧切入&#xff0c;提高员工使用便利性&#xff0c;但未解决身份&#xff08;账号&#xff09;真正统一。传统路径通过属性映射方式完成各个账…

Hack The Box-Challenges-Misc-M0rsarchive

解压压缩包&#xff0c;里面是一张图片和一个新的zip文件 图片放大后的图案是----. 考虑到为莫斯密码&#xff0c;将其解密 密码为9&#xff0c;继续解压缩包 又是一张莫斯密码图加压缩包&#xff0c;写一段脚本去解密图片中的莫斯密码&#xff0c;并自动解压缩包 import re i…

MQ面试题整理(持续更新)

1. MQ的优缺点 优点&#xff1a;解耦&#xff0c;异步&#xff0c;削峰 缺点&#xff1a; 系统可用性降低 系统引入的外部依赖越多&#xff0c;越容易挂掉。万一 MQ 挂了&#xff0c;MQ 一挂&#xff0c;整套系统崩 溃&#xff0c;你不就完了&#xff1f;系统复杂度提高 硬生…

HiveSQL题——array_contains函数

目录 一、原创文章被引用次数 0 问题描述 1 数据准备 2 数据分析 ​编辑 3 小结 二、学生退费人数 0 问题描述 1 数据准备 2 数据分析 3 小结 一、原创文章被引用次数 0 问题描述 求原创文章被引用的次数&#xff0c;注意本题不能用关联的形式求解。 1 数据准备 i…

本次安装Visual Studio 所用的安装程序不完整。请重新运行VisualStudio安装程序以解决此问题

今天点开VS的时候遇到了这个问题 因为昨天升级到一半电脑关机了&#xff0c;今天打开软件遇到如下错误&#xff0c; 解决办法很简单&#xff0c;找到安装目录进入Installer文件夹 我的目录在C:\Program Files (x86)\Microsoft Visual Studio\Installer 找到vs_installer.exe…

idea修改项目git地址

大家好&#xff0c;今天给大家分享的知识是如何在idea中修改项目的git地址。 一、修改地址 首先我们先找到菜单栏中Git选项&#xff0c;然后点击管理远程&#xff08;Manage Remote&#xff09; 之后双击origin之后就可以定义名称或者URL了。

oracle主库增加redo组数

redo log&#xff08;重做日志&#xff09;&#xff1a; 重做日志&#xff1a;简单来说就是&#xff0c;将oracle数据库的DML、DDL&#xff08;数据库操作语言&#xff0c;数据库定义i语言&#xff09;操作记录在日志中&#xff0c;方便恢复及备库使用&#xff0c;以组的方式管…

《Lua程序设计》-- 学习11

反射&#xff08;Re fl ection&#xff09; 反射是程序用来检查和修改其自身某些部分的能力 调试库由两类函数组成&#xff1a;自省函数&#xff08;introspective function&#xff09;和钩子&#xff08;hook&#xff09;。自省函数允许我们检查一个正在运行中的程序的几个…

【实训】网络系统集成课程实训(vlan、vrrp、nat)

目录 一 实训概述 1.1 实训目的 1.2 实训内容 二 实训原理 2.1 VLAN间划分及VLAN间通信 2.2 BGP&#xff0c;边界网关协议 BGP是运行于 TCP 上的一种自治系统的路由协议&#xff0c;用于在AS之间实现路由信息的交互。 2.2.1 VRRP原理 2.2.2 OSPF配置 三&#xff0e;实训…

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…

我用JVS低代码平台,搭建了一套固定资产管理系统

随着企业规模的不断扩大和业务的快速发展&#xff0c;资产管理成为了企业运营中的重要环节。然而&#xff0c;传统的手工管理模式已经无法满足现代企业的需求&#xff0c;管理效率低下、信息不准确、流程不规范等问题逐渐凸显。为了解决这些问题&#xff0c;越来越多的企业开始…

将xyz格式的GRACE数据转成geotiff格式

我们需要将xyz格式的文件转成geotiff便于成图&#xff0c;或者geotiff转成xyz用于数据运算&#xff0c;下面介绍如何实现这一操作&#xff0c;采用GMT和matlab两种方法。 1.GMT转换 我们先准备一个xyz文件&#xff0c;这里是一个降水文件。在gmt中采用以下的语句实现xyz转grd…

Java栈和队列

&#x1f435;本文章将对栈相关知识进行讲解 一、什么是栈 栈是一种特殊的线性表&#xff0c;向栈中放入元素的次序是由栈底到栈顶依次放入&#xff0c;被称为入栈或压栈&#xff0c;从栈中出元素时只能从栈顶出&#xff0c;被称为出栈。即栈要求元素“先进后出” 下面给一道经…

Vivado-IP核

Vivado-IP核 主程序 timescale 1ns / 1ps ////module ip_clk_wiz(input sys_clk,input sys_rst_n,output clk_out1,output clk_out2,output clk_out3,output clk_out4,output locked);clk_wiz_0 instance_name(// Clock out ports.clk_out1(clk_out1), // output clk_out…

ywtool login guard命令

一.登录防护功能介绍 登录防护功能主要检查系统日志/var/log/secure&#xff0c;查看系统有没有被暴力登录。登录防护默认是检测3分钟内登录系统失败15次(次数可修改)后,视其为有攻击性,拉黑此IP(centos7通过系统文件阻止IP,centos8/9通过防火墙阻止IP)。此脚本只针对SSH访问,…