插件可以在组件内实例化后,其实例驱动插件动作起来。
即只传入相关的
- 可配置
插件会完成所有的功能
- 动态渲染结构
- 事件处理函数实现
实例:做一个 Tab 选择卡组件
从外到里搭架子
创建顺序
- 先有一个 app.ts
- 为 app.ts 增加一个 pgRender() 方法
- 在 plugin 提供
- 建立 tab 组件
- 怎样使用驱动的 options 的设置
- 回到插件驱动 实现驱动的 options
app.ts
import Tab from './components/Tab';
import { PgRender } from './plugins/';
function App(): HTMLElement[] {
return [
Tab({
curIdx: 3
})
];
}
PgRender(
App(),
document.getElementById('app')!
);
plugins/index.ts
import PgTab from './pg-tab';
export function PgRender(domCollection: HTMLElement[], root: HTMLElement) {
const oWrapper: HTMLElement = document.createElement('div'),
oFrag: DocumentFragment = document.createDocumentFragment();
oWrapper.className = 'container';
domCollection.forEach((item: HTMLElement) => {
oFrag.appendChild(item);
})
oWrapper.appendChild(oFrag);
root.appendChild(oWrapper);
}
export {
PgTab
}
components/Tab/index.ts
import { PgTab } from '../../plugins'
interface IProps {
curIdx?: number
}
function Tab(props: IProps) {
return new PgTab(
{
currentIndex: props.curIdx,
data: [
{
navItem: '导航1',
pageItem: '页面1'
},
{
navItem: '导航2',
pageItem: '页面2'
},
{
navItem: '导航3',
pageItem: '页面3'
},
{
navItem: '导航4',
pageItem: '页面4'
},
],
callback(newIdx) {
console.log(newIdx);
}
}
).render();
}
export default Tab;
plugins\pg-tab\index.ts
interface IOptions {
currentIndex?: number;
data: any[];
callback?: (newIndx: number) => void | undefined;
}
class PgTab { // 驱动
private _curIdx;
private _data;
private _callback;
constructor(options: IOptions) {
this._data = options.data;
this._curIdx = this._checkIndex(options.currentIndex);
this._callback = options.callback;
}
private _checkIndex(index: number | undefined): number {
const _idx: number = index ? index >>> 0 : 0;
if (_idx >= this._data.length) {
return 0;
}
return _idx;
}
public render() {
}
}
export default PgTab;
驱动视图渲染
视图的组成
- 上面一个 Nav
- 下面一个 Page
点击 Nav Item 来切换 Page Item
所以需要 三个盒子
- 最外层的 wrapper
- 导航的 Nav
- 装 Page
plugins\pg-tab\index.ts
interface IOptions {
currentIndex?: number;
data: any[];
callback?: (newIndx: number) => void | undefined;
}
interface IData {
navItem: string;
pageItem: string;
}
class PgTab {
// 驱动
private _curIdx;
private _data;
private _callback;
private _oNavWrapper: HTMLElement | null = null;
private _oPageWrapper: HTMLElement | null = null;
constructor(options: IOptions) {
this._data = options.data;
this._curIdx = this._checkIndex(options.currentIndex);
this._callback = options.callback;
}
private _checkIndex(index: number | undefined): number {
const _idx: number = index ? index >>> 0 : 0;
if (_idx >= this._data.length) {
return 0;
}
return _idx;
}
public render() {
this._oNavWrapper = document.createElement("div");
this._oPageWrapper = document.createElement("div");
const oTabWrapper: HTMLElement = document.createElement("div");
this._oNavWrapper.className = "pg-nav";
this._oPageWrapper.className = "pg-page";
oTabWrapper.className = "pg-tab";
this._data.forEach((item: IData, index: number) => {
this._oNavWrapper!.innerHTML += `
<div
class="nav-item${this._curIdx === index ? " current" : ""}"
style="width: ${500 / this._data.length}px"
>${item.navItem}</div>
`;
this._oPageWrapper!.innerHTML += `
<div
class="page-item${this._curIdx === index ? " current" : ""}"
>${item.pageItem}</div>
`;
});
oTabWrapper.appendChild(this._oNavWrapper);
oTabWrapper.appendChild(this._oPageWrapper);
return oTabWrapper;
}
}
export default PgTab;
样式处理
plugins\pg-tab\index.scss
.pg-tab {
width: 500px;
height: 500px;
border: 1px solid #000;
.pg-nav {
height: 50px;
border-bottom: 1px solid #000;
.nav-item {
float: left;
line-height: 50px;
text-align: center;
}
& .current {
background-color: #000;
color: #fff;
}
}
.pg-page {
position: relative;
width: 100%;
height: 450px;
.page-item {
display: none;
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
text-align: center;
line-height: 450px;
font-size: 100px;
}
& .current {
display: block;
}
}
}
在 plugins\pg-tab\index.ts 引入样式 import "./index.scss";
绑定事件处理函数
plugins\pg-tab\index.ts
import "./index.scss";
interface IOptions {
currentIndex?: number;
data: any[];
callback?: (newIndx: number) => void | undefined;
}
interface IData {
navItem: string;
pageItem: string;
}
class PgTab {
// 驱动
private _curIdx;
private _data;
private _callback;
private _oNavWrapper: HTMLElement | null = null;
private _oPageWrapper: HTMLElement | null = null;
private _oNavItems: HTMLCollection | null = null;
private _oPageItems: HTMLCollection | null = null;
constructor(options: IOptions) {
this._data = options.data;
this._curIdx = this._checkIndex(options.currentIndex);
this._callback = options.callback;
}
private _checkIndex(index: number | undefined): number {
const _idx: number = index ? index >>> 0 : 0;
if (_idx >= this._data.length) {
return 0;
}
return _idx;
}
public render() {
this._oNavWrapper = document.createElement("div");
this._oPageWrapper = document.createElement("div");
const oTabWrapper: HTMLElement = document.createElement("div");
this._oNavWrapper.className = "pg-nav";
this._oPageWrapper.className = "pg-page";
oTabWrapper.className = "pg-tab";
this._data.forEach((item: IData, index: number) => {
this._oNavWrapper!.innerHTML += `
<div
class="nav-item${this._curIdx === index ? " current" : ""}"
style="width: ${500 / this._data.length}px"
>${item.navItem}</div>
`;
this._oPageWrapper!.innerHTML += `
<div
class="page-item${this._curIdx === index ? " current" : ""}"
>${item.pageItem}</div>
`;
});
oTabWrapper.appendChild(this._oNavWrapper);
oTabWrapper.appendChild(this._oPageWrapper);
this.bindEvent();
return oTabWrapper;
}
private bindEvent() {
this._oNavItems = this._oNavWrapper.getElementsByClassName("nav-item");
this._oPageItems = this._oPageWrapper.getElementsByClassName("page-item");
this._oNavWrapper.addEventListener(
"click",
this.handleNavClick.bind(this),
false
);
}
private handleNavClick(e: Event) {
const tar = e.target as HTMLElement,
className = tar.className;
if (className === "nav-item") {
this._oNavItems![this._curIdx].className = "nav-item";
this._oPageItems![this._curIdx].className = "page-item";
this._curIdx = [].indexOf.call(this._oNavItems, tar as never);
this._oNavItems![this._curIdx].className += " current";
this._oPageItems![this._curIdx].className += " current";
this._callback && this._callback(this._curIdx); // 处理 callback 事件
}
}
}
export default PgTab;