组件化介绍

背景:

原先一个复杂页面,如果不是组件化的开发模式的话,那么页面中所有的逻辑都是放在一块的,非常的混乱,不友好,彼此之间的依赖性也比较强,耦合度比较高,不便于后续维护,如果其中有一处有问题的话,很有可能会影响到别的地方

什么是组件化:

简单的讲就是将一个复杂页面拆分成具有各自功能的部分,这每个就单独包括展示结构、样式、逻辑控制,对功能的封装,这就是组件,组件与组件之间互不干扰,如果有数据来往,也可以正常的传值

组件化的优点:

  • 组件是模块化编程思想的体现,便于代码复用
  • 便于团队协作开发,提高了开发效率
  • 代码维护性好,对于代码的管理和使用非常方便,组件的加载和卸载只需要添加或删除一行代码即可完成
  • 组件提供了html、css、js的封装方法,实现了与同一页面其他代码的隔离
  • 组件非常灵活,定制非常容易,组件往往会留出接口,供使用者设置常用属性,比如title组件,使用者可以自定义标题、样式等

组件化开发的方式:

  • 原生DOM操作封装
  • jquery插件
  • YUI
  • ExtJs
  • 原生Web components
  • React
  • Vue
  • Angular

使用Web components

基本步骤:

  1. 首先现在html中定义一个模板Template,模板中书写组件的结构

    <Template id='hello-tem'>
    	<h1>hello world</h1>
    </Template>
    
  2. 在Template模板中定义组件专属的样式,用style标签包起来

    <Template id='hello-tem'>
    	<!-- 组件单独的样式,只对template内部的标签有效 -->
    	<style>
    		h1{
    			font-size: 20px;
    			color: aquamarine;
    			padding: 10px;
    			background-color: blueviolet;
    		}
    	</style>
    	<h1>hello world</h1>
    </Template>
    
  3. 定义组件类

    <script>
    	class HelloWorld extends HTMLElement{
    		constructor(){
    			super()
    			// 得到组件的模板内容
    			const template = document.querySelector('#hello-tem').content;
    		
    			//创建组件的根节点(也叫影子节点)
    			const shadowRoot = this.attachShadow({mode:'open'})
    		
    			//将模板节点添加到根节点中
    			shadowRoot.appendChild(template.cloneNode(true))
    		}
    	}
    </script>
    
  4. 在js中注册自定义组件

    <script>
    	.......
    	customElements.define('hello-world',HelloWorld)  //注册组件,组件名为‘hello-world’, 第二个参数是组件类
    </script>
    
  5. 在html中使用自定义组件,直接插入使用组件名标签即可

    <!-- 使用组件 -->
    <hello-world></hello-world>
    
  6. 这样你就可以在页面中看到一个最简单的自定义组件效果了
    在这里插入图片描述

注意
1、自定义组件名必须由中间的”-“连接
2、定义在template中的style样式只对template中的内容生效

组件传值:

上面的例子中,假设我们通过传值的方式来给内部组件的h1自定义内容,来看下如何处理:

组件调用时,就直接给组件添加自定义属性,这里比如定为content

<hello-world content="你好啊"></hello-world>

然后在组件内部的类中通过this.getAttribute(“属性名”)获取对应的属性数据:

	<script>
		class HelloWorld extends HTMLElement{
			constructor(){
				super()
				// 得到组件的模板内容
				const template = document.querySelector('#hello-tem').content;
				//创建组件的根节点(也叫影子节点)
				const shadowRoot = this.attachShadow({mode:'open'})
				//将模板节点添加到根节点中
				shadowRoot.appendChild(template.cloneNode(true))
				
				//通过操作DOM元素把获取到的值塞到元素内部作为值
				const content = this.getAttribute('content')      
				shadowRoot.querySelector('h1').innerText = content
				 
			}
		}
	</script>

组件生命周期:

它的生命周期包含以下四个:

  • connectedCallback: 当 custom element首次被插入文档DOM时,被调用
  • disconnectedCallback: 当 custom element从文档DOM中删除时,被调用
  • adoptedCallback: 当 custom element被移动到新的文档时,被调用
  • attributeChangedCallback: 当 custom element增加、删除、修改自身属性时,被调用

组件插槽(slot):

比如,此时我们要自定义一个卡片组件,卡片的内容部分自定义传入,我们可以这么做:

	<!-- 调用组件时,直接在组件内部写上要替换slot插槽的内容即可 -->
	<hello-world content="你好">
		<div slot='content'>我是插槽内容</div>
	</hello-world>
	
	<Template id='hello-tem'>
		<style>
			.card{
				height: 200px;
				width: 200px;
				border: 1px solid greenyellow;
			}
			.header{
				background-color: grey;
			}
		</style>
		// 在Template模板中的内容区可以写上一个slot标签,代表着这块的内容我可以通过外面自定义插槽的形式传入
		<div class="card">
			<div class="header">我是标题</div>
			<slot name="content"></slot>
		</div>
	</Template>

注意:调用组件时写的slot值要和定义插槽时的name值一致,不然它找不到要插槽的位置,因为可能存在多个插槽

Logo

开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!

更多推荐