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運算後返回的結果有