我们在处理一些任务量比较庞大的工作时候,会将工作内容进行拆分,分步骤完成
而组件化的思想正式如此,对于一个庞大的项目,我们可以将其拆分成一个个的小功能,分步骤进行实现
组件化是Vue的核心思想
<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>
分为全局组件注册:任何地方都可以用
局部组件注册:
<div id="app">
<my-component>my-component>
div>
<script>
const App = {};
//全局组件对象
const myComponent = {
template: `
我是一个组件
`,
};
//使用Vue
const app = Vue.createApp(App);
//注册全局组件
//传入全局组件的名称以及对象
app.component("my-component", myComponent);
//挂载
app.mount("#app");
script>
或者
全局组件往往是在程序一开始的时候,就会全局组件注册完成,但是有些组件我们并为使用过,在打包的时候,会增加打包文件的体积
因此局部组件是开发中常用的
<div id="app">
<my-component>my-component>
<my-item>my-item>
div>
<script>
const App = {
components: {
//key就是组件的名称,后面跟着组件对象
"my-component": {
template: `
我是一个组件
`,
},
//第二个局部组件
MyItem: {
template: `
我是一个组件Item
`,
},
},
};
//使用Vue
const app = Vue.createApp(App);
//挂载
app.mount("#app");
script>
上面说的Vue文件实际上就是一个单文件
为了让浏览器能够正常渲染Vue文件,可以使用Vue CLI搭建相关环境
npm install @vue/cli -g
全局安装 Vue脚手架vue create 项目名称
创建一个项目
npm run serve
命令即可运行项目Vue.createApp(App)
创建一个Vue实例,而这是通过 import
引入Vueimport { 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");
{{ title }}
使用npm init vue@latest
运行 npm init vue@latest
命令创建项目
且是使用 vite进行打包的,不是使用webpack进行打包
输入完命令,会询问是否安装 vue-create工具
在以上案例中,相当于是App.vue中的数据,要传递给HeaderCom.vue/ContentCom.vue/FooterCom.vue
在子组件中通过 props接收父组件传递过来的参数
什么是Props
Props有两种常见的用法
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
<childCom class="active">childCom>
//父组件引用了子组件
-----------------------
//子组件
其他元素
//相当于在子组件中的div中添加了class="active"
{{ name }}
{{ age }}
子组件中的数据可以根据传入的数据进行变化
而子组件中的元素是否可以?
当我们没有给子组件传入内容,但是又想让子组件默认显示一些内容,可以在slot中写入默认的元素
-----子组件
-------父组件
文本
-------父组件
文本
当我们在父组件中使用 v-slot的时候,可以指定元素插入到哪个插槽中
但是我们不希望冒号后面的内容写死,即 v-slot:“right”,right是动态的
仅能用作有关联的组件,没有关联的组件不能使用
以上方法的弊端就是,无法实现兄弟组件之间的通信,因此选用事件总线
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";
emitData() {
//传入事件的名称,以及参数
zcEventBus.emit("zcEventBus", "zhangcheng");
},
created() {
zcEventBus.on("zcEventBus", (data) => {
console.log("父组件收到了数据", data);
});
},