1. 前言
Vue.js是一个基于组件的Javascript框架,组件化编程是核心思想之一。通过组件化,Vue允许开发者将用户页面拆分成独立,可重用的部分,从而提升代码的可维护性,可读性以及可服用性。
本文主要讲解在Vue2中组件化编程模式
2. 组件的定义
组件是一个具有独立功能的Vue实例,具有自己的数据,模板,样式与逻辑。每个组件可以相互交互,接收输入(props),并可以产生输出(事件),从而形成一个灵活的用户界面
3. 组件化编程的结构
3.1 组件创建
Vue组件最常用的创建方式是使用Vue单文件组件,包含以下三个部分
1. 模板(Template):定义组件的HTML结构
Vue规定,在组件的模板中我们需要创建一个父标签囊括所有的标签
2. 脚本(Script):定义组件的逻辑和数据
3. 样式(Style):定义组件的CSS样式
以下是一个完整Vue组件模板:
javascript"><template></template><style></style><script></script>
3.2 Vue.app
使用Vue.app集成所有的子组件(components),是应用的核心,管理应用的状态和组件
javascript"><template>
</template><style>
</style><script>export component from './...'export default{components:{} //注册组件
}
</script>
3.3 main.js
应用的入口Javascript文件,管理应用的状态与组件。
创建Vue实例,定义路由,状态管理,以及全局组件和插件的配置
javascript">// main.js
import Vue from 'vue';
import App from './App.vue';
import Greeting from './Greeting.vue'; // 导入组件// 全局注册组件
Vue.component('Greeting', Greeting);new Vue({render: h => h(App),
}).$mount('#app');
3.4 index.html
应用文件的入口文件,提供挂载点
javascript"><!DOCTYPE html>
<html lang=""><head><meta charset="UTF-8"><link rel="icon" href="/favicon.ico"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Vite App</title></head><body><div id="app"></div><script type="module" src="/src/main.js"></script></body>
</html>
4. 组件的注册
组件可以在全局或局部进行注册
- 全局注册
定义:全局注册是指在Vue应用的整个生命周期,组件都可以被任何地方的模板使用
javascript">// main.js
import Vue from 'vue';
import App from './App.vue';
import Greeting from './Greeting.vue'; // 导入组件// 全局注册组件
Vue.component('Greeting', Greeting);new Vue({render: h => h(App),
}).$mount('#app');
优点:方便在多个组件中使用同一个组件,尤其是在大型应用中
缺点:如果有多个同名组件,全局注册可能会导致命名冲突
- 局部注册
定义:组件只可以在其父组件之中使用,其他组件无法访问该组件
在组件的components选项中进行注册
javascript"><template><div><Greeting></Greeting><div>
</template><style>
</style><script>
import Greeting from './Greeting.vue' export default{components:{Greeting;
}
}
</script>
5. 组件的通信
5.1 数据传递
在子组件中使用props定义子组件中相关属性,父组件通过数据代理模式传递父组件的数据或者方法至子组件
javascript">//父组件
<ChildComponent :message="parentMessage" />//子组件
export default{props:['message'],
}
5.2 事件传递
事件传递主要是通过this.$emit函数出发自定义事件,将数据传递给父组件
javascript">this.$emit('事件名',数据)
将会触发该事件,并传递对应的数据
只需要在父组件上设定好对应的事件,以及事件触发之后执行的函数,数据传递至函数,子组件便将数据传递给父组件了。
子组件:
javascript"><template><button @click='sendData'>Click me</button>
</template><script>export default{methods:{sendData(){this.$emit('childEvent','Hello')}} //通过调用该方法触发事件
}
<script>
父组件:
javascript"><template>
<child @childEvent='handle'></child>
</template><script>export default {components:{child}methods:{handle(message){console.log('这是子组件传来的数据',message)}}
}
</script>
5.3 插槽
插槽是一种非常重要的功能,用于实现组件的内容分发。插槽允许开发者在父组件中嵌套内容到子组件中,从而在不修改子组件代码的情况下灵活地定制其内容
5.3.1 默认插槽
子组件:
javascript"><template><div class='child'><slot></slot></div>
</template>
父组件:
javascript"><template>
<child>
<p>This is slot</p>
</child>
</template><script>export default{components:{child}
}
</script>
5.3.2 具名插槽
具名插槽允许一个组件中定义多个插槽,每个插槽都拥有自己的名字,这样父组件可以选择性的传递内容到不同的插槽位置
子组件:
javascript"><template><div class="child"><header><slot name="header"></slot></header> <!-- 具名插槽 --><main><slot></slot></main> <!-- 默认插槽 --><footer><slot name="footer"></slot></footer> <!-- 具名插槽 --></div>
</template>
父组件:
javascript"><template><div><child-component><template v-slot:header><h1>This is the header content</h1></template><p>This is the default slot content.</p><template v-slot:footer><footer>Footer content goes here</footer></template></child-component></div>
</template><script>
import ChildComponent from './ChildComponent.vue';export default {components: {ChildComponent}
}
</script>
5.3.3 插槽作用域
插槽不仅仅是用来传递静态内容,还可以向插槽传递数据通过插槽作用域,父组件可以将数据传递到子组件中的插槽,子组件可以在插槽模板内使用这些数据
javascript"><template><div class="child"><slot :message="childMessage"></slot> <!-- 传递数据到插槽 --></div>
</template><script>
export default {data() {return {childMessage: 'Hello from child!'}}
}
</script>
父组件:
javascript"><template><div><child-component><!-- 使用插槽作用域来访问子组件传递的内容 --><template v-slot:default="slotProps"><p>{{ slotProps.message }}</p> <!-- 输出从子组件传递来的数据 --></template></child-component></div>
</template><script>
import ChildComponent from './ChildComponent.vue';export default {components: {ChildComponent}
}
</script>