《Vue 组件化开发:构建可复用的模块》
一、Vue 组件化开发概述
组件化是 Vue.js 的核心概念之一,它允许将界面拆分成独立、可复用的组件,使得开发大型应用变得更加简单和高效。
组件的定义是实现应用中局部功能代码和资源的集合。Vue.js 的组件化用于将 UI 页面分割为若干组件进行组合和嵌套。它是一种高效的处理复杂应用系统的方式,能够更好地明确功能模块的作用。目的是为了解耦,把复杂系统拆分成多个组件,分离组件边界和责任,便于独立升级和维护。
Vue 的组件化将 UI 页面分割为若干组件进行组合和嵌套。组件化是一种强大的开发模式,具有诸多好处。比如,它能提高开发效率,方便重复使用,简化调试步骤,提升项目可维护性,便于多人协同开发。组件是 Vue.js 最强大的功能之一,让我们用独立可复用的小组件来构建大型应用,开发效率更快更敏捷。
在 Vue 中,组件可以分为页面组件、业务组件和通用组件。Vue 的组件是基于配置的,我们通常编写的组件是组件配置而非组件,框架后续会生成其构造函数,它们基于 VueComponent,扩展于 Vue。Vue 中常见组件化技术有属性 prop,自定义事件,插槽等,它们主要用于组件通信、扩展等。合理的划分组件,有助于提高应用性能。组件应该是高内聚、低耦合的,遵循单向数据流的原则。
二、组件复用的方法
(一)引入组件并注册
- 可以全局注册组件,如 Vue.component('my-component', {...})。全局注册组件有多种方式,一种是在 main.js 中直接注册,例如:
// 引入
import PageTools from '@/components/PageTools';
// 注册为全局组件
Vue.component('PageTools', PageTools);
这种方式的缺点是如果需要注册的全局组件非常多,我们需要一个一个引入,然后分别调用 Vue.component 方法,main.js 文件会变的很大,不好维护。另一种是使用插件的形式注册,在统一注册的入口文件中:
// 引入
import PageTools from './PageTools';
export default {
install(Vue) {
// 注册全局组件
Vue.component('PageTools', PageTools);
}
};
入口文件注册插件(main.js):
import Components from './components';
Vue.use(Components);
此外,还可以在 main.js 中引入组件,然后通过 Vue.component 方法全局注册组件,例如:
// 全局注册组件
import MyCounter from "./components/MyCounter.vue";
Vue.component('MyCounter', MyCounter);
全局注册后,在项目的任意位置均可使用组件。
- 也可在特定实例中局部注册组件,如 new Vue({components: {'my-component': {...}}})。局部注册插件,是指在某个 Vue 页面中局部使用。代码如下:
import MyCounter from '@/components/MyCounter.vue';
export default {
name: 'Home',
components: {
MyCounter
}
};
此处需要注意,首先得在 components 属性中注册组件,然后才能在页面代码部分引用组件。
- 单文件组件(.vue 文件)的使用。模块化就是把一个很大的东西,拆分成一些小的东西,vue 组件就是把一个大的 html 文件,拆成了一些小的 vue 文件,这个 vue 文件里面,包括了 html,js,css。当要去使用组件的时候,就需要暴露这些组件【export】,然后引入【import】。
vue-cil 脚手架使用全局安装(仅第一次执行):npm install -g @vue/cli。此后命令行就有了 vue 这个命令。切换到要创建的目录,然后使用命令创建项目vue create xxx。启动项目npm run serve。
由于浏览器不认识.vue 文件,就需要我们搭建 vue 脚手架,vue 脚手架给我们配置好了基本上所有东西,我们直接在里面写项目就可以了。单文件组件格式由三部分组成:\u003ctemplate\u003e、\u003cstyle\u003e、\u003cscript\u003e。\u003ctemplate\u003e 里面写 html,必须有一个根标签;\u003cstyle\u003e 里面写 css,scoped 样式作用是让样式局部生效,防止和其他组件样式冲突被覆盖;\u003cscript\u003e 里面写 js,export default 暴露组件。组件使用时,首先要在我们使用的地方去引入组件,然后配置一项 components: {组件名,组件名},最后直接当做标签中使用\u003c组件名\u003e\u003c/组件名\u003e。
(二)在模板中使用组件
- 直接在 template 里面使用引入的 component 的文件,如。在普通的标签模板中,必须使用短横线的方式使用组件。如果使用驼峰式命名组件,那么在使用组件的时候,只能在模板字符串中使用驼峰命名法。注意事项:组件参数的 data 值必须是函数;组件模板必须是单个跟元素。全局组件和局部组件都可以通过这种方式在模板中使用。例如:
<div id="app">
<hello-world>
</hello-world>
<peng-ke>
</peng-ke>
</div>
Vue.component('HelloWorld', {
data: function() {
return {
msg: 'helloworld'
};
},
template: `<p>{{msg}}</p>`
});
var pengke = {
data: function() {
return {
msg: '你好,pengke'
};
},
template: `<h3>{{msg}}</h3>`
};
var vm = new Vue({
el: '#app',
data: {},
components: {
'peng-ke': pengke
}
});
三、组件的注册方式
(一)在实例中注册
在 Vue 中,可以在特定的实例中局部注册组件。局部注册插件是指在某个 Vue 页面中局部使用。首先需要引入组件,然后在组件的配置对象中通过components属性进行注册。例如:
import MyCounter from '@/components/MyCounter.vue';
export default {
name: 'Home',
components: {
MyCounter
}
};
此处需要注意,首先得在components属性中注册组件,然后才能在页面代码部分引用组件。
(二)在 Vue 中注册
全局注册后可以在任何实例中使用,如在main.js中引入组件,然后通过Vue.component方法全局注册组件:
// 全局注册组件
import MyCounter from "./components/MyCounter.vue";
Vue.component('MyCounter', MyCounter);
全局注册后,在项目的任意位置均可使用组件。这种方式适用于一些通用的组件,方便在整个项目中复用。但如果需要注册的全局组件非常多,一个个引入并注册会使main.js文件变得很大,不好维护。此时可以使用插件的形式注册,在统一注册的入口文件中:
// 引入
import PageTools from './PageTools';
export default {
install(Vue) {
// 注册全局组件
Vue.component('PageTools', PageTools);
}
};
入口文件注册插件(main.js):
import Components from './components';
Vue.use(Components);
四、组件的 props
(一)定义 props
在 Vue.js 中,组件的 props 是子组件声明的属性,它们允许子组件从父组件接收数据。子组件通过声明 props 来定义它期望从父组件接收哪些数据。例如,子组件可以这样定义 props:
import { defineProps } from 'vue';
const props = defineProps({
name: String,
age: Number
});
export default {
props
};
(二)传递 props
在父组件中,可以通过普通的 HTML 属性的方式将数据传递给子组件。例如:
<template>
<div>
<ChildComponent :name="userName" :age="userAge" />
</div>
</template>
<script setup>
import { ref } from 'vue';
import ChildComponent from './ChildComponent.vue';
const userName = ref('张三');
const userAge = ref(30);
</script>
五、组件事件
(一)自定义事件的创建和触发
在 Vue 中,自定义事件可以让子组件向父组件传递特定的信息或触发特定的操作。自定义事件有三个关键要素:事件源(通常是子组件)、事件类型和监听器(通常是父组件中的方法)。
例如,我们可以创建一个名为myComponent的子组件,并在其中定义一个自定义事件。当特定条件满足时,触发这个自定义事件:
export default {
data() {
return {
someCondition: false
};
},
methods: {
triggerEvent() {
if (this.someCondition) {
this.$emit('myCustomEvent', 'some data');
}
}
}
};
(二)父组件监听子组件事件
父组件可以通过v-on指令监听子组件触发的自定义事件。例如:
<template>
<div>
<my-component @myCustomEvent="parentMethod"></my-component>
</div>
</template>
<script>
import myComponent from './myComponent.vue';
export default {
components: {
myComponent
},
methods: {
parentMethod(data) {
console.log('子组件触发了自定义事件,传递的数据是:', data);
}
}
};
</script>
(三)父组件处理事件
当父组件监听到子组件触发的事件后,可以在对应的处理方法中进行各种操作。比如,可以更新父组件的数据、调用其他方法或者执行一些特定的逻辑。
例如,在接收到子组件传递的数据后,父组件可以根据这个数据进行一些计算或状态更新:
parentMethod(data) {
this.someParentData = data * 2;
// 或者调用其他方法进行进一步处理
this.someOtherMethod(data);
}
六、Vue 实现逻辑复用的方式
(一)插件(Plugins)
插件可以全局或局部地添加功能,例如可以通过创建一个插件对象,在其中定义一些方法或属性,然后使用Vue.use()方法全局注册插件,或者在特定的 Vue 实例中局部使用插件。这样可以在多个组件中共享一些通用的功能,提高代码的复用性。
(二)混入(Mixins)
混入包含可复用的组件逻辑,如定义一个混入对象,可以包含数据、方法、生命周期钩子等组件选项。例如:
const myMixin = {
data() {
return {
sharedData: 'This is shared data'
};
},
methods: {
sharedMethod() {
console.log('This is a shared method.');
}
},
created() {
console.log('Mixing in created hook.');
}
};
然后在组件中使用混入,可以通过在组件的选项中添加mixins属性,并将混入对象作为数组元素传入。例如:
import { defineComponent } from 'vue';
const MyComponent = defineComponent({
mixins: [myMixin],
data() {
return {
componentData: 'Component specific data'
};
},
template: `<div>{{sharedData}} - {{componentData}}</div>`
});
这样,组件就可以继承混入对象中的逻辑,实现代码的复用。混入在 Vue 中提供了一种灵活的方式来共享通用的功能,减少重复代码,提高开发效率。
七、内容分发——插槽(Slots)
(一)默认插槽
默认插槽也叫匿名插槽,可以在子组件中使用一个<slot>标签来作为占位符,父组件可以通过这个标签向子组件中传递内容。在父组件中使用子组件时,可以在标签中直接写入要插入的内容,也可以使用v-bind指令绑定父组件中的数据。子组件的模板中可以使用this.$slots.default来渲染插入的内容。
例如,子组件MyComponent的代码如下:
<template>
<div>
<slot>默认内容...</slot>
</div>
</template>
<script>
export default {
name: 'MyComponent'
};
</script>
父组件中使用MyComponent:
<template>
<div>
<MyComponent>
<p>这是插入的内容</p>
</MyComponent>
</div>
</template>
<script>
import MyComponent from './MyComponent.vue';
export default {
components: {
MyComponent
}
};
</script>
(二)具名插槽
具名插槽就是给每一个插槽增加了一个name属性让每一个插槽都有自己的名字,这样方便,父组件中的配置按照相应的地方插入。
父组件中:
<Category title="美食">
<img slot="center" src="D:\\gr信息\\图集\\2.jpg" alt="1"/>
<a slot="footer" href="http://www.baidu.com/">牛肉饭</a>
</Category>
<Category title="游戏":listData="games">
<ul slot="center">
<!-- 这时候因为变量直接在app.vue中所以可以直接去遍历game遍历完了再利用插槽的功能传递给Category.vue -->
<li v-for="(g, index) in games" :key="index">{{ g }}</li>
<div class="foot" slot="footer">
<a href="http://www.baidu.com/">网络游戏</a>
<a href="http://www.baidu.com/">单机游戏</a>
</div>
</ul>
</Category>
<Category title="电影":listData="films">
<!-- controls 可以让video可以播放 -->
<videoslot="center" controlssrc="http://clips.vorwaerts-gmbh.de/big_buck_bunny.mp4"/>
<template v-slot:footer>
<div class="dianyin" slot="footer">
<a href="http://www.baidu.com/">经典</a>
<a href="http://www.baidu.com/">热门</a>
<a href="http://www.baidu.com/">推荐</a>
</div>
<h4>欢迎观影</h4>
</template>
</Category>
子组件中:
<template>
<div class="category">
<h3>{{ title }}分类</h3>
<!-- 定义一个默认插槽,那么App.vue中相应的组件标签里标签体的内容会往这个插槽中放置 -->
<slot name="center"></slot>
<slot name="footer"></slot>
</div>
</template>
<script>
export default {
name: 'Category',
props: ['title']
};
</script>
<style>
.category {
background-color: skyblue;
width: 200px;
height: 300px;
}
h3 {
text-align: center;
background-color: orange;
}
</style>
要点:具名插槽:即具有名字的插槽,在默认插槽基础上指定插槽的名字(name = " ")。父组件指明放入子组件的哪个插槽slot = "footer",如果是template可以写成v-slot : footer。
父组件中:
<Category>
<template slot="center">
<div>html结构1</div>
</template>
<template v-slot:footer>
<div>html结构2</div>
</template>
</Category>
子组件中:
<template>
<div>
<!-- 定义插槽 -->
<slot name="center">插槽默认内容...</slot>
<slot name="footer">插槽默认内容...</slot>
</div>
</template>
<script>
export default {
name: 'Category'
};
</script>
(三)作用域插槽
作用域插槽是一种特殊的插槽,它能够接收来自父组件的数据,并在子组件中使用。在 Vue2 中,作用域插槽是通过slot-scope实现的,而在 Vue3 中,作用域插槽是通过v-slot实现的。
例如,子组件代码如下:
<template>
<div>
<!-- 这是一个具名插槽,name=sun是这个插槽的名字 -->
<slot name="sun":data="data"></slot>
</div>
</template>
<script>
// import Vue from 'vue';
export default {
data() {
return {
data: '我是子组件的数据'
};
}
};
</script>
如果想要用到子组件的数据并展示的话,就可以使用作用域插槽了。首先得在子组件的slot中如同使用prop传值一样,绑定需要传递的数据,然后在父组件中使用v-slot去获取传过来的数据并结构。
父组件代码如下:
<template>
<!-- sun就是插槽的名字 -->
<!-- {data}是用结构的方式来获取的 -->
<Sun v-slot:sun="{data}">{{data}}</Sun>
</template>
<script>
import Sun from './Sun.vue';
export default {
name: 'Father',
components: {
Sun
}
};
</script>
(四)使用插槽
插槽是 Vue 中一个非常有用的工具,可以帮助我们创建可重用的组件,实现动态内容展示,以及提高代码的可维护性和可扩展性。
在使用插槽时,可以根据实际需求选择默认插槽、具名插槽或作用域插槽。
默认插槽适用于只有一个插槽位置的情况,父组件可以直接在子组件标签中插入内容或使用v-bind指令绑定数据。
具名插槽可以定义多个插槽,每个插槽都有一个名字,父组件可以通过slot属性或v-slot指令将内容插入到特定的插槽位置。
作用域插槽允许子组件将数据传递给父组件,父组件可以在插槽中使用这些数据来渲染内容。
(五)作用域插槽的使用
作用域插槽可以用于父组件向子组件传递数据,同时子组件可以自定义显示方式。比如,我们可以在父组件中传递一组数据给子组件,然后在子组件中使用作用域插槽来自定义显示方式,这样就能够实现复杂的 UI 效果。
实际应用如下:
父组件代码如下:
<template>
<div>
<child-component:list="list">
<template v-slot:item="{ item }">
<div class="item":class="{ active: item.active }">{{ item.name }}</div>
</template>
</child-component>
</div>
</template>
<script setup>
import ChildComponent from './ChildComponent.vue';
const list = ref([
{ name: 'item1', active: true },
{ name: 'item2', active: false },
{ name: 'item3', active: true }
]);
</script>
子组件代码如下:
<template>
<div>
<ul>
<li v-for="item in list":key="item.name">
<slot name="item":item="item"></slot>
</li>
</ul>
</div>
</template>
<script setup lang="ts">
import { withDefaults, defineProps } from 'vue';
interface props {
list: Array;
}
const props = withDefaults(defineProps<props>(), {
list: () => []
});
</script>
在父组件中,我们通过v-slot来定义作用域插槽,然后在子组件中使用slot来引用这个插槽。在子组件中,我们可以使用item来访问从父组件传递过来的数据,并自定义显示方式。
八、组件通信方式
(一)父子组件通信
- Props 和 Events:父组件通过 props 向子组件传递数据,子组件通过$emit向父组件发送事件。这种方式简单直接,在 Vue 开发中被广泛应用。例如,子组件可以定义为<button @click=\"increment\">Increment</button>,父组件则使用<child-component :initial-count=\"count\" @increment=\"count++\"></child-component>的方式进行通信。在子组件中,通过 props 接收父组件传递的initial-count属性,然后在按钮被点击时,触发increment方法,通过$emit向父组件发送事件,父组件接收到事件后执行count++操作,实现数据的双向传递。
(二)Event Bus(非官方,但常用)
通过一个事件总线(通常是一个 Vue 实例)来通信。在 Vue 中,当需要在非父子组件之间进行通信时,Event Bus 是一种常用的方法。例如,可以创建一个全局的事件总线对象:
const eventBus = new Vue();
在组件中,可以使用$emit和$on方法来触发和监听事件。例如,在发送事件的组件中:
eventBus.$emit('customEvent', 'some data');
在接收事件的组件中:
eventBus.$on('customEvent', (data) => {
console.log(data);
});
(三) listeners
listeners 包含了父作用域中的(不含.native 修饰器的)v-on 事件监听器。在 Vue 中, listeners 可以帮助我们更好地处理组件之间的通信和属性传递。例如,子组件可以通过$attrs获得父组件在子组件上添加的属性(除了子组件 prop 声明的以外的属性),并且可以通过v-bind="$attrs"的方式,将属性自动绑定到子组件的某标签上。同时,子组件可以通过$listeners获取父组件绑定在子组件上的所有事件监听器,并通过类似this.$listeners.click的方式将事件传递给父组件处理。
(四)provide/inject
provide:祖父组件可以使用 provide 来提供数据。inject:后代组件可以使用 inject 来注入数据。在 Vue 中,provide/inject 是一种处理层级嵌套的数据通信方式。父组件通过 provide 来提供变量,然后在子组件中通过 inject 来注入变量。无论组件嵌套多深,provide 是个函数,返回值一个对象;inject 是一个数组,用来接收 provide 传递过来的对象。例如:
const App = {
data() {
return {
title: "老爹"
};
},
// provide 提供变量
provide() {
return {
msg: "老爹的数据"
};
},
template: `<div><A></A></div>`,
};
Vue.component('B', {
data() {
return {
count: 0
};
},
// 通过 inject 去接收
inject: ['msg'],
created() {
console.log(this.msg);
},
template: `<div>{{msg}}</div>`,
});
Vue.component('A', {
data() {
return {};
},
created() {
// 通过 this.$parent 获取父组件的数据,支持连续链式操作
console.log(this.$parent.$parent);
console.log(this.$children);
console.log(this);
},
template: `<div><B></B></div>`,
});
new Vue({
el: '#app',
data: {},
components: {
// 2.挂载子组件 App
App
}
});
(五)状态管理库(Vuex)
对于复杂应用,可以使用 Vuex 来集中管理状态。Vuex 是 Vue.js 的状态管理模式和库。它采用集中式存储管理应用的所有组件的状态,并以相应的规则保证状态以一种可预测的方式发生变化。例如,在一个计数器应用中,可以使用 Vuex 来管理计数器的状态:
// store.js
import Vue from 'vue';
import Vuex from 'vuex';
Vue.use(Vuex);
export default new Vuex.Store({
state: {
count: 0
},
mutations: {
increment(state) {
state.count++;
},
decrement(state) {
state.count--;
}
},
actions: {
incrementAction({ commit }) {
commit('increment');
},
decrementAction({ commit }) {
commit('decrement');
}
},
getters: {
countGetter(state) {
return state.count;
}
}
});
在组件中,可以使用mapState、mapMutations和mapActions辅助函数来自动将 Vuex store 的状态和 actions 映射为组件的属性和方法:
<!-- Counter.vue -->
<template>
<div>
<h1>{{ count }}</h1>
<button @click="increment">+</button>
<button @click="decrement">-</button>
</div>
</template>
<script>
import { mapState, mapActions } from 'vuex';
export default {
computed: {
...mapState(['count'])
},
methods: {
...mapActions(['incrementAction', 'decrementAction'])
}
};
</script>
(六)ref
...
(七) children
使用 children 可能会导致组件之间的耦合度增加,这可能会使组件更难以重用和测试。在 Vue 中,子组件可以通过$parent访问父实例,父组件可以通过$children访问子组件实例。但是这种方式只是作为访问组件的应急方法,更推荐用 props 和 events 实现父子组件通信。例如:
Vue.component('A', {
data() {
return {};
},
created() {
// 通过 this.$parent 获取父组件的数据,支持连续链式操作
console.log(this.$parent.$parent);
console.log(this.$children);
console.log(this);
},
template: `<div></div>`,
});
九、构建可复用模块的技巧
(一)函数封装
在 Vue 组件化开发中,函数封装是构建可复用模块的重要技巧之一。例如,可以将截取输入框中第二个字符开始到最后的值并把它们转化成大写字母的功能封装成函数。这样,在多个组件中需要进行类似操作时,只需调用这个封装好的函数即可,无需重复编写相同的代码逻辑。
(二)组件封装
- 整体封装,用户通过改变数据源来呈现不同的页面状态,代码结构不可定制化。整体封装的组件在使用时相对简单,只需提供相应的数据源即可实现特定的功能。然而,由于其代码结构不可定制化,可能在某些复杂的应用场景下灵活性不足。
- 自定义封装(插槽),开放一部分槽位给父组件,使其能够进行一定程度的定制化。具名插槽可以定义多个插槽,每个插槽都有一个名字,父组件可以通过slot属性或v-slot指令将内容插入到特定的插槽位置。作用域插槽是一种特殊的插槽,它能够接收来自父组件的数据,并在子组件中使用。在 Vue2 中,作用域插槽是通过slot-scope实现的,而在 Vue3 中,作用域插槽是通过v-slot实现的。
(三)插件封装
在某些情况下,将公用部分逻辑封装成插件,为项目添加全局功能,如常见的 loading 功能、弹框功能等。vue 中的组件可以以插件的方式封装,例如封装一个 toast 插件:创建 toast 组件,在 main.js 中导入并安装,在组件中通过this.$toast访问 toast 组件中的方法。插件的核心是 install 函数,第一个参数是 Vue 对象,第二个参数是 options 配置参数。当通过vue.use()调用插件时,即执行 install 方法。通过 mixins 创建全局插件,以下封装了一个数据验证的插件 rules。通过在 vue 实例的$options中添加 rules,实现对实例中 data 的监听。封装控件先与创建其他 vue 实例相同,构建控件需要实现的效果,再在 js 文件中,实现 install 方法,并暴露为全局对象。以下为封装消息弹框控件 toast 的示例,假定 toast.vue 实现了效果。在 toast.js 文件中:引入 toast 组件,定义 toastObj 对象,实现 install 方法,将 toast 组件对象挂载到 Vue 实例上,最后导出 toastObj 对象。在 main.js 文件中,通过vue.use(toast)全局使用 toast 控件;也可以在任何 vue 实例中进行局部使用。
十、Vue 组件化开发的优势
(一)模块化开发
Vue 的组件化开发实现了模块化开发,具有多方面的优势。首先,它具有独立性,每个组件可以独立开发、测试和部署,减少了开发中的耦合度。就像管理书籍时,根据类别将书放在不同的格子里,随着业务的发展,Vue 组件化将应用程序按照业务拆分成不同的模块,每个模块对应 Vue 项目下 component 下的文件目录,模块中的组件组成了完整的模块页面。这种独立性使得不同的开发人员可以专注于特定的组件,提高开发效率。
其次,模块化开发有利于团队协作。不同的开发人员可以同时开发不同的组件,提升团队协作效率。例如在开发电商网站时,可以将产品展示、购物车、用户评论等功能分别开发成独立的组件,开发人员可以并行工作,互不干扰。
最后,模块化的结构使得调试更加简单。问题可以被隔离在特定的组件中,更容易定位和修复。当出现问题时,可以快速确定是哪个组件出现了问题,针对性地进行调试。
(二)代码复用性高
Vue 组件化开发极大地提高了代码的复用性。一方面,它减少了重复代码。相同的功能只需开发一次,然后在不同的地方复用。比如在开发多页面应用时,可以创建一个导航栏组件,在所有页面中复用该组件,避免了在每个页面中重复编写导航栏的代码。
另一方面,通过复用组件可以确保应用中相同功能的一致性,减少了不一致的问题。同时,只需在一个地方进行修改,就可以更新所有使用该组件的地方,维护起来非常方便。
(三)易于维护
Vue 组件化开发使得应用程序的维护变得更加容易。首先,组件化的代码结构清晰,便于理解和管理。每个组件都有明确的功能和职责,就像一个个独立的模块,使得整个应用程序的结构一目了然。
其次,组件可以单独更新,不会影响其他部分的功能。例如,如果需要修改某个组件的功能,只需要对该组件进行修改,而不会对其他组件产生影响。
此外,不同的组件可以由不同的开发人员负责,职责分明,降低了维护成本。根据业界调查,使用组件化开发的项目,其维护成本比传统开发方式降低了 30%以上。
(四)提高开发效率
Vue 组件化开发能够快速提高开发效率。其一,通过复用现有的组件,可以快速搭建应用的基础结构。在新项目启动时,可以直接复用之前项目中的通用组件,如按钮、输入框、表单等,从而大大缩短开发时间。
其二,组件化结构便于隔离和定位问题,缩短调试时间。当出现问题时,可以快速确定问题所在的组件,针对性地进行调试,提高了调试效率。
最后,高效协作也是提高开发效率的重要因素。团队成员可以并行开发不同的组件,避免资源冲突,提高团队的协作效率。
相关文章:
《Vue 组件化开发:构建可复用的模块》
一、Vue 组件化开发概述 组件化是 Vue.js 的核心概念之一,它允许将界面拆分成独立、可复用的组件,使得开发大型应用变得更加简单和高效。 组件的定义是实现应用中局部功能代码和资源的集合。Vue.js 的组件化用于将 UI 页面分割为若干组件进行组合和嵌套…...
贪心算法理论
系列博客目录 文章目录 系列博客目录贪心算法 (Greedy Algorithm)贪心算法的特点贪心算法的适用条件常见的贪心算法问题贪心算法的步骤贪心算法示例:活动选择问题贪心算法的优缺点 贪心算法 (Greedy Algorithm) 贪心算法是一种在每一步选择中都采取当前状态下最优的…...
JVM之Synthetic
Synthetic是人造,合成的意思,在虚拟机很多地方使用ACC_SYNTHETIC表示编译器自动生成的,区别于我们自己写的程序代码。这样说可能比较模糊,我们举个例子:我们创建一个内部类,如下 public class TestInnerCl…...
HCIE IGP双栈综合实验
实验拓扑 实验需求及解法 本实验模拟ISP网络结构,R1/2组成国家骨干网,R3/4组成省级网络,R5/6/7组成数据中 心网络。 配置所有ipv4地址,请自行测试直连。 R1 sysname R1 interface GigabitEthernet0/0/0ip address 12.1.1.1 255.…...
【k8s】监控metrics-server
metrics-server介绍 Metrics Server是一个集群范围的资源使用情况的数据聚合器。作为一个应用部署在集群中。Metric server从每个节点上KubeletAPI收集指标,通过Kubernetes聚合器注册在Master APIServer中。为集群提供Node、Pods资源利用率指标。 就像Linux 系统一样…...
第六届国际科技创新学术交流会暨管理科学信息化与经济创新发展(MSIEID 2024)
重要信息 大会官网:msieid2024.iaecst.org (点击了解大会,参会等内容) 大会时间:2024年12月6-8日 大会地点:中国-广州 大会简介 随着全球化和信息化的不断深入,管理科学、信息化和经济发展…...
将面具贴到人脸上的过程
使用OpenCV进行人脸面具贴合和变形以适应人脸的3D透视角度,通常需要以下步骤: 人脸检测:首先需要检测图像中的人脸位置。特征点检测:在检测到的人脸区域中,找到关键特征点,如眼睛、鼻子、嘴巴等。透视变换…...
【Maven】Nexus私服
6. Maven的私服 6.1 什么是私服 Maven 私服是一种特殊的远程仓库,它是架设在局域网内的仓库服务,用来代理位于外部的远程仓库(中央仓库、其他远程公共仓库)。一些无法从外部仓库下载到的构件,如项目组其他人员开发的…...
AI高中数学教学视频生成技术:利用通义千问、MathGPT、视频多模态大模型,语音大模型,将4个模型融合 ,生成高中数学教学视频,并给出实施方案。
大家好,我是微学AI,今天给大家介绍一下AI高中数学教学视频生成技术:利用通义千问、MathGPT、视频多模态大模型,语音大模型,将4个模型融合 ,生成高中数学教学视频,并给出实施方案。本文利用专家模…...
探索温度计的数字化设计:一个可视化温度数据的Web图表案例
随着科技的发展,数据可视化在各个领域中的应用越来越广泛。在温度监控和展示方面,传统的温度计已逐渐被数字化温度计所取代。本文将介绍一个使用Echarts库创建的温度计Web图表,该图表通过动态数据可视化展示了温度值,并通过渐变色…...
windows电脑上安装树莓派操作系统
在Windows电脑上安装树莓派通常涉及以下几个步骤:准备安装工具、下载树莓派系统镜像、烧录系统到SD卡、配置树莓派以及远程连接(如果需要无显示器操作)。以下是详细的步骤说明: 一、准备安装工具 安装树莓派官方烧录工具: 下载并安装Raspberry Pi Imager。这是一个官方的…...
交换机四大镜像(端口镜像、流镜像、VLAN镜像、MAC镜像)应用场景、配置实例及区别对比
在网络管理中,端口镜像、流镜像、VLAN镜像和MAC镜像都是用于监控和分析网络流量的重要技术。 端口镜像(Port Mirroring) 定义:端口镜像是将一个或多个源端口的流量复制到一个目标端口,以便于网络管理员能够监控和分析…...
我不是挂王-用python实现燕双鹰小游戏
一.准备工作 1.前言提要 作为程序员在浩瀚的数字宇宙中,常常感觉现实世界是一台精密运作的虚拟机,其底层的物理逻辑如同铁律般难以撼动。然而我们拥有在虚拟世界中自由驰骋、创造无限可能的独特力量。突发奇我想用Python写出燕双鹰的小游戏,这样想想就很…...
Java:反射、注解
文章目录 1. 反射1-1. 获取Class对象的三种方式1-2. 获取类的构造器、实例化对象1-3. 获取类的成员变量1-4. 获取类的成员方法 2. 注解2-1. 元注解2-2. 解析注解 1. 反射 反射:加载类,并允许以编程的方式解剖类中的各种成员变量、方法、构造器。 1-1. …...
Java 通过枚举类减少if else
目录 一. 案例1二. 案例2三. 案例3四. 案例4 枚举类聚合封装消息 一. 案例1 涉及到EnumMap的实际使用 ⏹定义一个枚举类,用来表示日本的各种支付方法对应的code import com.fasterxml.jackson.annotation.JsonFormat;// 让jackson将前台的数据封装数据到枚举类中 J…...
单链表---移除链表元素
对于无头单向不循环链表,给出头结点head与数值val,删除链表中数据值val的所有结点 #define ListNodeDataType val struct ListNode { struct ListNode* psll;ListNodeDataType val; } 方法一---遍历删除 移除所有数值为val的链表结点,…...
认识redis 及 Ubuntu安装redis
文章目录 一. redis概念二. redis应用场景二. redis的特性四. 使用Ubuntu安装redis 一. redis概念 redis 是在内存中存储数据的中间件, 用在分布式系统 redis是客户端服务器结构的程序, 客户端服务器之间通过网络来通信 二. redis应用场景 redis可用作数据库 类似MySQL, 但…...
Java开发网络安全常见问题
1、敏感信息明文传输 用户敏感信息如手机号、银行卡号、验证码等涉及个人隐私的敏感信息不通过任何加密直接明文传输。 如下图中小红书APP 的手机短信验证码登录接口,此处没有对用户手机号和验证码等信息进行加密传输,可以很简单的截取并开展一些合法的…...
C#基础之委托,事件
文章目录 1 委托1.1 简介1.2 操作使用1.2.1 声明委托(Delegate)1.2.2 实例化委托(Delegate)1.2.3 直接调用和invoke1.2.4 Invoke 和 BeginInvoke 1.3 委托的多播1.4 委托的匿名和lambda1.4.1 匿名方法1.4.2 lambda 表达式 1.5 内置…...
nginx配置静态资源的访问
比如静态资源图片位于/mnt/software/nginx/html/static/images目录下,那么nginx.conf中的配置则为: # 静态文件目录 location /static/images/ { root /mnt/software/nginx/html; try_files $uri $uri/ 404; #找不到时提示404 …...
JS的魔法三角:constructor、prototype与__proto__
在JavaScript中,constructor、prototype和__proto__是与对象创建和继承机制紧密相关的三个概念。理解它们之间的关系对于掌握JavaScript的面向对象编程至关重要。下面将详细介绍这个魔法三角: 1. constructor 定义:constructor是一个函数&am…...
CA系统(file.h---申请认证的处理)
#pragma once #ifndef FILEMANAGER_H #define FILEMANAGER_H #include <string> namespace F_ile {// 读取文件,返回文件内容bool readFilename(const std::string& filePath);bool readFilePubilcpath(const std::string& filePath);bool getNameFro…...
matlab显示sin二维图
1,新建脚本 2、保存脚本 3、脚本命令:clc 清除 脚本命令的信息 clrear all 清除全部 4工作区内容:变量啥的 x0:0.001:2*pi%% 开始 精度 中值 ysin(x) y1cos(x) figure%%产生一个屏幕 plot(x,y)%%打印坐标 title(ysin(x))%%标题 xlabel(…...
验证 kubelet 服务已经停止并且不再生成错误日志
要验证 kubelet 服务已经停止并且不再生成错误日志,可以按照以下步骤进行操作: 1. 检查 kubelet 服务状态 首先,确认 kubelet 服务已经停止。 Bash 深色版本 sudo systemctl status kubelet 你应该看到类似以下的输出,表示服…...
【Linux】进程控制-----进程替换
目录 一、为什么要进行进程替换: 二、进程替换的原理: 三、exec家族: 1、execl: 2、execlp: 3、execv: 4、execvp: 5、execle和execve 编辑 putenv: 一、为什么要进行进程…...
安装SQL Server 2022提示需要Microsoft .NET Framework 4.7.2 或更高版本
安装SQL Server 2022提示需要Microsoft .NET Framework 4.7.2 或更高版本。 原因是:当前操作系统版本为Windows Server 2016 Standard版本,其自带的Microsoft .NET Framework 版本为4.6太低,不满足要求。 根据报错的提示,点击链接…...
使用ECharts创建带百分比标注的环形图
在数据可视化领域,环形图是一种非常有效的图表类型,它能够清晰地展示各部分与整体的关系。今天,我们将通过ECharts来创建一个带百分比标注的环形图,并详细解释如何实现这一效果。 1. 数据准备 首先,我们定义了一些基础…...
学习threejs,设置envMap环境贴图创建反光效果
👨⚕️ 主页: gis分享者 👨⚕️ 感谢各位大佬 点赞👍 收藏⭐ 留言📝 加关注✅! 👨⚕️ 收录于专栏:threejs gis工程师 文章目录 一、🍀前言1.1 ☘️THREE.CubeTextureLoader 立…...
go语言里的mkdir mkdirall有什么区别?
在Go语言中,os.Mkdir 和 os.MkdirAll 都是用来创建目录的函数,但它们之间存在一些关键的区别。 ### os.Mkdir - **功能**:os.Mkdir 用于创建一个单一的目录。如果该目录已经存在,则会返回一个错误。 - **参数**: - na…...
使用Python OpenCV实现图像形状检测
目录 一、环境准备 二、读取和预处理图像 读取图像 灰度化 滤波去噪 三、边缘检测 四、查找轮廓 五、绘制轮廓 六、形状分类 七、显示结果 八、完整代码示例 九、总结 图像形状检测是计算机视觉领域中的一项关键技术,广泛应用于工业自动化、机器人视觉、医学图像处…...
做网站多少钱特惠西宁君博s/口碑营销案例
行为和特效 Flash是一个表现力非常强的平台,可以创造出一切想要的特效效果。在Flex所提供的类库中,就包含了一些行为和特效,可以实现表现力很强的动画效果。使用行为、拖放行为特效、使用ViewState、过度特效、使用ToolTips 一、 使用行为 行…...
做外贸公司网站怎么做/微信视频号小店
问题描述: 让导航栏重叠在轮播图上面,并且导航栏要是透明的状态,功能实现了,但是出现拖到分屏宽度就变了。 代码: 开始用的宽度设置都是px单位,后来改成百分比就可以自适应了。 原因分析:…...
免费中文网站模板html/网络营销是什么课程
在我们日常使用Laravel框架中,有很多值得我们学习的设计理念和开发思想,如何代码变得更加“优雅”,核心架构中组件化、服务容器、数据库ORM 都是很值得我们去探究一二的方向。在本系列博客中,将利用 Laravel 中组件化的特点来构建一个迷你 仿 Laravel 的 MVC框架。本篇的应用主…...
营销型网站建设公司哪家好/seo课程多少钱
由于类型转换过程中有可能出现原始参数无法转换为目标类型的错误,所以struts2提供了类型转换中的异常处理机制。 在struts2的默认配置文件struts-default.xml中有如下一段配置代码 <interceptors><interceptor-stack name"defaultStack"><…...
建设b2b平台网站/google搜索免费入口
数据结构 基于三元组表的存储结构实现稀疏矩阵的应用 课程设计 实验报告 数 据 结 构 课 程 设 计设计题目:基于三元组表的存储结构实现稀疏矩阵的应用课题名称 基于三元组表的存储结构实现稀疏矩阵的应用院 系 年级专业学 号 姓 名 成 绩课题设计目的与设计意义1、…...
企业网站做app/农产品推广方案
1.更新源的步骤 (1)备份原来的源列表文件 cd /etc/apt/ mv sources.list sources.list.bak (2)新建源文件,输入源地址 nano sources.list 在nano sources.list输入如下源地址 deb http://mirrors.aliyun.com/ubuntu/ trusty main restricted universe multiverse …...