angular4 + ts + es6 自造轮子,理解组件化操作。以及怎么应用一些需要数据展示的组件
1、为什么要将某个功能块拿出来做成一个组件。
2、改组件应该考虑哪些可塑性或者或使用者怎么进行自定义。
3、组件实现了什么功能?
4、怎么使用组件与当前的程序嵌合
eg:下拉选组件的制造
一、造组件
webstrom 的cmd(左下角的灰色方块点开选terminal)控制台可以快速创建组件。
html代码
<div class="row text-center base-dropdawn">
<div class="col">
<div ngbDropdown class="d-inline-block">
<button class="btn btn-outline-primary show-plan" id="dropdownBasic1" ngbDropdownToggle [ngStyle]="showStyle">{{showData[code]}}
<span class="glyphicon glyphicon-menu-down"></span>
</button>
<div class="select-plan" ngbDropdownMenu aria-labelledby="dropdownBasic1">
<!-- <button class="dropdown-item" (click)="checkSelect($event)"[ngStyle]="selectStyle">Action - 1</button>
<button class="dropdown-item" (click)="checkSelect($event)"[ngStyle]="selectStyle">Another Action</button>
<button class="dropdown-item" (click)="checkSelect($event)"[ngStyle]="selectStyle">Something elsehhhhhhh</button>-->
<button class="dropdown-item" *ngFor="let select of selectData, index as i" (click)="checkSelect($event,i)"[ngStyle]="selectStyle" [ngClass]="{'active': isIndex===i}">{{select}}</button>
</div>
</div>
</div>
</div>
ts代码
import {Component, OnInit, Output, EventEmitter, Input} from '@angular/core';
@Component({
selector: 'app-dropdawn',
templateUrl: './dropdawn.component.html',
styleUrls: ['./dropdawn.component.css']
})
export class DropdawnComponent implements OnInit {
showData: Array<any> = []; // 要展示的下拉选的数组
isIndex: number = 0; // 选中哪个选择项,默认为第一个
@Input() initShow: string = '';
@Input() showStyle: any= {}; // 展示面板的样式数据
@Input() selectStyle: any= {}; // 下拉面板的样式数据
@Input() selectData: any = []; // 待选择的下拉列表的数组
@Input() code: string = '';
@Output() selectChange: EventEmitter<any> = new EventEmitter<any>(); // 返回数据结构
constructor() {
}
ngOnInit() {
// 初始化数据
this.showData[this.code] = '请选择';
this.showData[this.code] = this.initShow || '请选择'; // 如果需要初始化可以赋值
this.selectData = ['上对我的', 'wwrweg d', '3r3f3'] ;
this.showStyle = {
color: '#666',
background: '#fff',
width: '120px',
height: '24px'
};
this.selectStyle = {
color: '#666',
background: '#fff',
width: '120px',
height: '24px'
};
}
checkSelect(event, i) {
const _event = event.target;
this.showData[this.code] = _event.innerText;
debugger;
// 判断哪个是正在**的
this.isIndex = i;
console.log( this.showData);
this.selectChange.emit(this.showData);
}
}
css代码
.base-dropdawn button{
width:120px ;
height:24px;
line-height: 24px;
padding: 0;
padding-left: 5px;
margin: 0 auto ;
white-space:nowrap;
text-align: left;
text-overflow:ellipsis;
overflow: hidden;
}
/*固定下拉图标的位置*/
.base-dropdawn .show-plan{
position: relative;
}
.base-dropdawn .show-plan .glyphicon {
position: absolute;
top: 5px;
right: 5px;
}
.base-dropdawn .show-plan{
border: 1px solid #CCCCCC;
border-radius: 4px;
}
.base-dropdawn .select-plan{
overflow: hidden;
border-radius: 0;
width:122px ;
min-width: 60px;
padding: 0;
border-bottom-left-radius: 4px;
border-bottom-right-radius: 4px;
}
.base-dropdawn .select-plan button{
border: 0;
}
.base-dropdawn .select-plan button:hover{
background: #3484f5 !important;
color:#fff !important;
}
.active{
background: #3484f5 !important;
color:#fff !important;
}
二、其他组件调用
a、HTML代码(第一个初始化数据的,第二个没有初始化数据)
<app-dropdawn [code]="'demo'"[initShow]="this.showData[0].value" (selectChange)="selectChangeShow($event)"></app-dropdawn>
<app-dropdawn [code]="'work'" (selectChange)="selectChangeShow($event)"></app-dropdawn>
b、ts代码
import {Component, OnInit} from '@angular/core';
import {Router} from '@angular/router';
import {UserService} from '../../service/user/user.service';
// 引入状态码
import { ERR_OK/*, ERR_OUTTIME*/ } from '../../../assets/configs/config';
// 引入状态管理
import { Store } from '@ngrx/store';
import { SET } from '../../store/user.reducer';
// 引入表单控制模块
import { FormBuilder, FormGroup, Validators } from '@angular/forms';
@Component({
selector: 'app-login',
templateUrl: './login.component.html',
styleUrls: ['./login.component.css']
})
export class LoginComponent implements OnInit {
// demo
showData: Array<any> = [];
userForm: FormGroup; // 登录录入信息
loginType: number = 1; // 登录角色 1-会员 2-管理员
showBtnGroup: boolean = true; // 按钮
showLoginForm: boolean = false; // 是否显示登录框
showRegistry: boolean = false; // 是否显示注册框
onSubmit: boolean = false;
userInfo: object = {
uuid: '',
captcha: ''
};
constructor(
private router: Router,
private userService: UserService,
private store: Store<object>,
private fb: FormBuilder
) {
this.userForm = fb.group({
username: ['', [Validators.required, Validators.pattern(/^\d{11}$/)]], // 用户名当前为 11位手机号码
userpwd: ['', [Validators.required]],
vcode: ['', [Validators.required, Validators.pattern(/^\d{4}$/)]] // 验证码当前为 4位数字组合
}, {validator: null});
}
ngOnInit() {
// this.getCode();
//demo
this.showData = [
{code: 'demo',
value: ''
},
{code: 'work',
value: ''
}
];
}
/**
* @desc 变更登录角色
* @param type 角色类型 1-会员 2-管理员
* */
loginTypeChange(type) {
this.showBtnGroup = false;
this.showLoginForm = true;
this.loginType = type;
}
/**
* @desc 判断显示登录框或者注册框
* @param type 1-登录 2-注册
* */
btnClick(type) {
this.showBtnGroup = false;
this.showLoginForm = type === 1;
this.showRegistry = type === 2;
}
/**
* @desc 执行登录
* @param null
* */
doLogin() {
this.onSubmit = true;
Object.values(this.userForm.controls).forEach(val => val.disable());
this.userService.login(Object.assign({}, this.userInfo, this.userForm.value)).then(res => {
if (res && res[2].ANS_MSG_HDR.MSG_CODE === ERR_OK) {
sessionStorage.setItem('SESSION_INFO', res[0][0].SESSION);
sessionStorage.setItem('OP_USER', res[0][0].USER_CODE);
sessionStorage.setItem('OP_ROLE', res[0][0].USER_ROLES.substr(0, 1));
sessionStorage.setItem('OP_TYPE', this.loginType + ''); // 记录是会员登录还是管理员登录
sessionStorage.setItem('ACCOUNT', JSON.stringify(res[0][0]));
this.store.dispatch({type: SET, payload: res[0][0]});
this.router.navigate(['/home']);
} else /*if (res && res[2].ANS_MSG_HDR.MSG_CODE === ERR_OUTTIME) */{
this.getCode();
}
this.onSubmit = false;
Object.values(this.userForm.controls).forEach(val => val.enable());
}).catch(err => {
this.onSubmit = false;
Object.values(this.userForm.controls).forEach(val => val.enable());
});
}
// 获取文件服务器返回的数据示例,判断e的数据类型
selectChangeShow(e) {
debugger
console.log(Object.prototype.toString.call(e));
// Object.prototype.toString.call(e)最精准的判断对象类型的方法,除此之外有instanceof 和typeof
// instanceof运算符用来判断一个构造函数的prototype属性所指向的对象是否存在另外一个要检测对象的原型链上console.log(Object instanceof Object); //true
//typeof typeof操作符返回一个字符串,表示未经计算的操作数的类型。 不能区分对象、数组、正则,对它们操作都返回"object"
console.log(typeof 42);
// expected output: "number"
if (Object.prototype.toString.call(e) === '[object Array]') {
this.showData.forEach(val => {
const d = e[val.code];
if (d) {
val.value = d;
}
});
}
console.log(this.showData);
}
/**
* @desc 获取图形验证码
* @param null
* */
getCode() {
Object.assign(this.userInfo, this.userService.getCaptcha());
}
}
三、
父组件与子组件通过本地变量互动
父组件通过#timer获得子组件的所有属性和方法
注释:typeof运算后返回的结果有