0%

ElementUI, a Vue 2.0 based component library

Caution! 限定的引入顺序:

UI.css —> template —> vue.js —> UI.js —> vue controller

其中 template 和 vue.js 交换没有影响

响应式栅格布局

基础栅格,基于24划分。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<el-row>
<el-col :span="6">
<div class="grid-content bg-purple"></div>
</el-col>
<el-col :span="6">
<div class="grid-content bg-purple-light"></div>
</el-col>
<el-col :span="6">
<div class="grid-content bg-purple"></div>
</el-col>
<el-col :span="6">
<div class="grid-content bg-purple-light"></div>
</el-col>
</el-row>

间隔( :gutter )

栅格之间的水平间距
1
2
3
<el-row :gutter="20">
...
</el-col>

偏移( :offset )
1
<el-col :span="6" :offset="6"><div class="grid-content"></div></el-col>

弹性盒子( flex )
1
2
3
<el-row type="flex" justify="center" align="center">
...
</el-row>

水平值:start, center, end, space-between, space-around

垂直值:top, middle, bottom

响应式( Responsive )

1
2
3
<el-col :xs="4" :sm="6" :md="8" :lg="9" :xl="11">
<div class="grid-content"></div>
</el-col>

隐藏

  • hidden-xs-only - 当视口在 xs 尺寸时隐藏
  • hidden-sm-only - 当视口在 sm 尺寸时隐藏
  • hidden-sm-and-down - 当视口在 sm 及以下尺寸时隐藏
  • hidden-sm-and-up - 当视口在 sm 及以上尺寸时隐藏

    Form表单

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    <div id="app">
    <el-form ref="form" :model="formData" :rules="formValidators" label-width="80px">
    <el-form-item label="title" prop="title">
    <el-input v-model="formData.title"></el-input>
    </el-form-item>
    <el-form-item label="Date">
    <el-col :span="11">
    <el-date-picker type="date" placeholder="Pick a date" v-model="formData.date1" style="width: 100%;">
    </el-date-picker>
    </el-col>
    <el-col class="line" :span="2">-</el-col>
    <el-col :span="11">
    <el-time-picker placeholder="Pick a time" v-model="formData.date2" style="width: 100%;">
    </el-time-picker>
    </el-col>
    </el-form-item>
    <el-form-item label="Subscribe">
    <el-switch v-model="formData.isSubscribe"></el-switch>
    </el-form-item>
    <el-form-item label="TAG">
    <el-checkbox-group v-model="formData.tags">
    <el-checkbox label="Activity" name="type"></el-checkbox>
    <el-checkbox label="Bonus" name="type"></el-checkbox>
    <el-checkbox label="Online" name="type"></el-checkbox>
    </el-checkbox-group>
    </el-form-item>
    <el-form-item label="Comments">
    <el-input type="textarea" v-model="formData.Comments"></el-input>
    </el-form-item>
    <el-form-item>
    <el-button type="primary" @click="onSubmit">Create</el-button>
    <el-button>Cancel</el-button>
    </el-form-item>
    </el-form>
    </div>
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    var Main = {
    data() {
    return {
    formData: {
    title: '',
    date1: '',
    date2: '',
    isSubscribe: false,
    tags: [],
    Comments: ''
    },
    formValidators: {
    title: [{
    required: true,
    message: '请输入标题',
    trigger: 'blur'
    },
    {
    min: 3,
    max: 5,
    message: '长度在 3 到 5 个字符',
    trigger: 'blur'
    }
    ]
    }
    }
    },
    methods: {
    onSubmit(event) {
    this.$refs[formName].validate((valid) => {
    if (valid) {
    console.log(event);
    console.log(this.formData)
    } else {
    console.log('validate fail');
    return false;
    }
    });

    }
    }
    }
    var Ctor = Vue.extend(Main)
    new Ctor().$mount('#app')
    以上几乎就是官网的example,官方文档未给出submit事件触发form action的表单提交方式,api文档中未提及action属性。有资料表示存在“ this.$refs.formName.submit ”(QQs未验证)

    这种方式也造成了做表单校验时,要在提交方法中调用form.validate,form.validate又是个异步操作,后续动作(一般是http post)要放在其回调函数中

    而在我大Angular的响应式表单中,ngSubmit监听FormGroup当前值,在校验不通过时将禁用type=”submit”提交按钮

如上例所示,表单验证需添加表单的:rules属性,表单项的prop属性(注意在label,值同name),提交方法中调用form.validate

Table

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<template>
<el-table :data="tableData" border style="width: 100%">
<el-table-column fixed prop="date" label="日期" width="150">
</el-table-column>
<el-table-column prop="name" label="姓名" width="120">
</el-table-column>
<el-table-column prop="address" label="地址" width="300">
</el-table-column>
<el-table-column prop="zip" label="邮编" width="120">
</el-table-column>
<el-table-column fixed="right" label="操作" width="100">
<template slot-scope="scope">
<el-button @click="handleClick(scope.row)" type="text" size="small">查看</el-button>
<el-button type="text" size="small">编辑</el-button>
</template>
</el-table-column>
</el-table>
</template>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
var Main = {
data() {
return {
tableData: [{
date: '2016-05-02',
name: '王小虎',
address: '上海市普陀区金沙江路 1518 弄',
zip: 200333
}, {
date: '2016-05-04',
name: '王大虎',
address: '上海市普陀区金沙江路 1517 弄',
zip: 200333
}]
}
},
methods: {
handleClick(row) {
console.log(row);
}
}
}
var Ctor = Vue.extend(Main)
new Ctor().$mount('#app')

比较有意思的是这个el-table-column label可以设置 多级表头

模板与绑定

1
2
3
4
5
6
7
<span>Message: {{ msg }}</span>
<span v-html="rawHtml"></span>
<div v-bind:id="dynamicId"></div>
<img v-bind:src="url" />
<p v-if="seen">现在你看到我了</p>
<a v-on:click="doSomething">...</a>
<li v-for="item in items">...</li>

@click is short for v-on:click

方法的括号()不是必须的

支持动态属性名和事件名称

1
2
<a v-bind:[attributeName]="url"> ... </a>
<a v-on:[eventName]="doSomething"> ... </a>

Vue实例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
<template>
<div id="container" >
<span>{{ title }}</span>
<span v-once>{{ title }} 没变吧</span>
<span v-if="flag">now shown</span>
<p>
<a v-on:click="handleClick">
<img v-bind:src="url" :class="[flag? 'imgSize1':'imgSize2']" />
</a>
</p>
<p>

</p>
</div>
</template>
<script>
import * as THREE from 'three'
export default {
name:'viewPort',
props:{
//target
},
data(){
return{
title:"titleXXX",
flag:true,
items:["item1","item2","item3"],
url: require('@/assets/images/threelogo.png')
}
},
//
created(){

},
mounted(){
this.initScene()
},
methods:{
initScene(){
// 创建3D场景对象Scene
const scene = new THREE.Scene();
console.log(scene);

},
handleClick() {
this.flag = !this.flag;
}
}
}
</script>

<style scoped>
#container {
margin: 0;
width: 100%;
height: 100vh;
background: #fff;
}

.imgSize1 {
width: 100px;
height: 100px;
}

.imgSize2 {
width: 50px;
height: 50px;
}
</style>

当一个 Vue 实例被创建时,它将 data 对象中的所有的属性加入到 Vue 的响应式系统中。当这些属性的值发生改变时,视图将会产生“响应”,即匹配更新为新的值。

常用实例方法:

1
2
3
4
5
vm.$data === data // => true
vm.$el === document.getElementById('example') // => true
vm.$watch('a', function (newValue, oldValue) {
// 这个回调将在 `vm.a` 改变后调用
})

生命周期钩子
生命周期
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
new Vue({
data: {
a: 1
},
created: function () {
// `this` 指向 vm 实例
console.log('a is: ' + this.a)
}
mounted: function () {
console.log('a is: ' + this.a)
}
beforeDestroy:function(){

}
})

内联处理器方法
1
2
3
4
5
6
7
8
new Vue({
data: {

},
methods:{
// TODO functions
}
})

官网

爬行起步方式

Caution! 限定的引入顺序:
template —> vue.js —> vue controller
其中 template 和 vue.js 交换没有影响

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
<html>
<head>
<meta charset="UTF-8">
<title>Hi vue</title>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
</head>
<body>
<div id="app">
{{ message }}
</div>
<script type="text/javascript">
var app = new Vue({
el: '#app',
data: {
message: 'here here'
}
})
</script>
</body>
</html>

常规起步方式

1
2
3
npm install -g @vue/cli

vue create vueproj

阅读 vue-cli指引

原力起飞方式

webpack 打包 vue 基础

多模块项目

vue-multi-module

vue渐进式

  • 完整版
  • 编译器 用以将模板字符串编译成js渲染函数
  • 运行时 不含编译器 用以创建vue实例 处理虚拟dom
  • UMD 通过\引入html的完整版本

vue对比其他框架

特性 Vue.js React Angular 2+
核心特点 渐进式框架,易学易用 虚拟DOM,组件化 完整的MVC框架
学习曲线 平缓,只需HTML/CSS/JS基础 中等,需掌握JSX和ES2015 陡峭,需掌握TypeScript和大量概念
性能优化 自动依赖追踪,精确更新 需手动使用PureComponent或shouldComponentUpdate 自动优化,但体积较大
模板语法 支持HTML模板,也支持JSX 强制使用JSX 使用类似HTML的模板
CSS处理 单文件组件中的scoped样式 CSS-in-JS方案(如styled-components) 支持组件样式,但不如Vue灵活
生态系统 官方维护路由和状态管理 丰富的第三方库,生态系统庞大 官方完整解决方案
向下扩展 简单,可通过CDN直接使用 需要构建系统,不适合简单项目 不适合简单项目
向上扩展 良好,官方提供CLI脚手架 强大,但配置较复杂 非常强大,适合大型企业应用
TypeScript支持 良好,官方提供类型声明 优秀,TS是React的一部分 必须使用TypeScript开发
项目体积 小(gzip后约30KB) 中等 较大(gzip后约65KB)
灵活性 高,不强制代码组织方式 中等,组件灵活但生态约束 低,有严格的代码组织规范
浏览器兼容性 IE9+ 现代浏览器 现代浏览器
响应式系统 基于依赖追踪的观察系统 基于状态管理和虚拟DOM 基于Zone.js和变更检测
原生渲染 通过Weex或NativeScript-Vue React Native Ionic或NativeScript
数据流 单向数据流 单向数据流(通过状态管理) 单向数据流
  • 易用性:Vue > React > Angular
    • Vue学习曲线最平缓,React需要掌握JSX,Angular最复杂
  • 灵活性:Vue > React > Angular
    • Vue不强制代码组织方式,React组件灵活但生态约束,Angular有严格规范
  • 性能:Vue ≈ React > Angular
    • Vue和React性能接近且优秀,Angular体积较大但性能也不错
  • 生态系统:React > Angular > Vue
    • React生态系统最庞大,Angular提供完整官方解决方案,Vue官方维护核心库
  • 适用场景
    • Vue:中小型项目,需要快速开发,团队技术栈多样
    • React:大型项目,需要丰富生态系统,团队熟悉JS
    • Angular:大型企业应用,需要完整解决方案,团队熟悉TypeScript

从Angular、React到Vue

  • 单文件组件 single file component
  • 相似的指令绑定
  • 直接赋值属性 无需setState
  • Composition API类React Hooks
  • props emit类似Angular装饰器风格

从vue2到vue3

RazorEngine: Open source templating engine based on Microsoft’s Razor parsing engine.

Razor文件类型

Razor可以在vb.net和C#中使用。分别对应了两种文件类型,.vbhtml和.cshtml

Razor的标识符

@字符被定义为Razor服务器代码块的标识符,表示是服务器代码。web form中使用<%%>中写服务器代码一个道理。

1
2
3
4
5
@{
string userName= "邓星林";
} <!-- 块级作用域 -->
<span>@userName</span>
<span>@DateTime.Now.ToString("yyyy-MM-hh")</span>

HTML

@Href(“~/“)//表示网站的根目录

@Html.Raw(Module.Content) 输出HTML

Razor标识混合HTML

1
2
3
4
5
6
7
8
9
@{
// html标签
<div></div>
var str = "abc";
// 下面会输出:this is a mail:dxl0321@qq.com, this is var: abc,this is mail@str,this is @;
@: this is a mail:dxl0321@qq.com, this is var: @str,this is mail@str,this is @@;
// 下面输出abc
@str
}

a.在作用域内如果是以html标签开始则视为文本输出

b.如果要输出符号@,则使用@@

c.如果要输出非html标签和非Razor语句的代码,则用@:,他的作用是相当于在处于html下面编写一样了,如在@:后面可以加上@就是表示Razor语句的变量

注释

1
2
3
4
5
6
7
@{
@*
多行注释
多行注释
*@
var i = 10; @* asdfasf *@
}

Layout 视图片段

插入指定路径定义的布局视图模板

1
2
3
4
5
6
7
@{
ViewData["Title"] = "分享优惠券管理";
Layout = "~/Views/Shared/_Layoutv2.cshtml";
}
<div class="main">
...
</div>

插入Page

1
2
3
<div class="area">
@RenderPage("/b.cshtml")
</div>

Section

Helper

helper就是可以定义可重复使用的帮助器方法,不仅可以在同一个页面不同地方使用,还可以在不同的页面使用。

1
2
3
4
5
6
7
8
9
10
@helper sum(int a,int b)
{
var result=a+b;
  @result

}
<div >
<p>2+3=@sum(2,3)</p>
<p>5+9=@sum(5,9)</p>
</div>

自带类型转换

  • AsInt()
  • IsInt()
  • AsBool()
  • IsBool()
  • AsFloat()
  • IsFloat()
  • AsDecimal()
  • IsDecimal()
  • AsDateTime()
  • IsDateTime()
  • ToString()

inventing js

关于0.1+0.2==0.3 false

0.1 + 0.2不等于0.3?为什么JavaScript有这种“骚”操作?
关于浮点数的二进制表示,js浮点数精度(存目)

保留2位小数

Number.prototype.toFixed 返回指定小数位数的字符串 必要时四舍五入 且必要时以0补足位数
返回number的方法不如用类似 Math.round(num * 100) / 100 保留两位小数

动态语言

Dynamic Programming Language 动态语言或动态编程语言,程序在运行时可以改变其结构:新的函数可以被引进,已有的函数可以被删除等在结构上的变化。动态语言如Javascript Python Ruby等 C/C++ Jave则不是

另外 图灵完备

JS Tips

Caps lock sensitive

1
2
var input = document.getElementsByTag('input')[0];
input.addEventListener('keyup',function(event){console.log(event.getModifierState('CapsLock'))});

getModifierState方法挂在KeyboardEvent或者MouseEvent上,可获取的键盘状态见MDN:KeyboardEvent.getModifierState()

运算符

  • 幂运算 2**10=1024

this

this的设计目的是在函数体内部,指代函数当前的运行环境

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
var f = function () {
console.log(this.x);
}

var x = 1;
var obj = {
f: f,
x: 2,
};

// 全局环境执行
f() // 1

// obj 环境执行
obj.f() // 2

另外,严格模式(‘use strict’)下,全局环境下运行时,this不会自动绑定到‘全局对象’上,将变量绑定到全局对象需要显式调用形如global.name = ‘Global’

常用处理

应用场景标题 描述 补充1 补充2
数组去重 Array.from(new Set(array)) 通过内置数据解构特性进行去重 [] => set => [] 通过遍历并判断是否存在进行去重[many items].forEach(item => (item <不存在于> uniqueArr) && uniqueArr.push(item))
数组的最后一个元素 获取数组中位置最后的一个元素 使用array.at(-1)
数组对象的相关转换 对象到数组:Object.entries() 数组到对象:Obecjt.fromEntries()
短路操作 通过短路操作避免后续表达式的执行 a或b:a真b不执行 a且b:a假b不执行
基于默认值的对象赋值 通过对象解构合并进行带有默认值的对象赋值操作 {...defaultData, ...data}
多重条件判断优化 单个值与多个值进行对比判断时,使用includes进行优化 [404,400,403].includes
交换两个值 通过对象解构操作进行简洁的双值交换 [a, b] = [b, a]
位运算 通过位运算提高性能和简洁程度 按位与(&)或(\ )按位取反(~) 取整~~、<<、>> >>>移位
replace()的回调 通过传入回调进行更加细粒度的操作
sort()的回调 通过传入回调进行更加细粒度的操作 根据字母顺序排序 根据真假值进行排序

call 和 apply

1
2
3
4
5
6
7
8
9
10
11
12
// 已有构造函数
function Product(name, price) {
this.name = name;
this.price = price;
}
// 在新函数中复用已有逻辑
function Food(name, price) {
Product.call(this, name, price); // 实际上相当于将构造函数Product的两行拿过来
this.category = 'food';
}
// test
const bread = new Food('bread', 0.8) // Food {name: "bread", price: 0.8, category: "food"}

FunctionX.call(thisArg,…args)中的第一个参数也可以是对象,函数相当于将剩余参数以FunctionX的实现方式应用到该对象内返回一个结果
apply与call的区别仅在:剩余参数是数组,即FunctionX.call(thisArg,[…args])

bind

bind是基于call或apply实现的函数原型方法 FunctionX.bind(thisArg,…args)返回一个新的函数,该函数套用FunctionX的样子,但以thisArg代替FunctionX的this,剩余参数填补FunctionX所需参数(即结果函数所需参数为FunctionX所需参数减去…args)
模拟实现

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
Function.prototype.bind = function (context) {
// 调用 bind 的不是函数,需要抛出异常
if (typeof this !== "function") {
throw new Error("Function.prototype.bind - what is trying to be bound is not callable");
}

// this 指向调用者
var self = this;
// 实现第2点,因为第1个参数是指定的this,所以只截取第1个之后的参数
var args = Array.prototype.slice.call(arguments, 1);

// 创建一个空对象
var fNOP = function () {};

// 实现第3点,返回一个函数
var fBound = function () {
// 实现第4点,获取 bind 返回函数的参数
var bindArgs = Array.prototype.slice.call(arguments);
// 然后同传入参数合并成一个参数数组,并作为 self.apply() 的第二个参数
return self.apply(this instanceof fNOP ? this : context, args.concat(bindArgs));
// 注释1
}

// 注释2
// 空对象的原型指向绑定函数的原型
fNOP.prototype = this.prototype;
// 空对象的实例赋值给 fBound.prototype
fBound.prototype = new fNOP();
return fBound;
}

关于替换this的操作可用于回调函数调用类函数, 如下类型A中定义回调函数,该回调函数会作为目标对象B的函数形参,process是类A的函数,但如果在目标对象B中调用callback函数,函数中的this会指向到B
1
2
3
4
5
callback = (response)=>{
this.process(response) // 这里的this指向当前运行环境
}

B.getDataAsync(this.callback)

应使用bind
1
B.getDataAsync(this.callback.bind(this))

柯里化Currying

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
style=function(){this.x="";this.y="";} // 构造函数style
style.prototype.addA=function(){
this.A='A'
return this
}
style.prototype.addB=function(){
this.B='B'
return this
}
style.prototype.addC=function(){
this.C='C'
return this
}
// test
xxx=new style()
xxx.addA()
xxx.addB().addC()

Garbage Collection

  • 游离dom

    1
    2
    3
    4
    5
    6
    let root=document.getElementById("root")
    for(let i=0;i<2000;i++){
    let div=document.createElement("div")
    root.appendChild(div)
    }
    document.body.removeChild(root)

    此时document中移除了dom,但内存中root还在,而且上千个子元素仍然被root对象引用,应设root=null解除引用

  • clearInterval和clearTimeOut

关于严格模式

strict mode

通知浏览器以严格模式运行脚本,严格模式下会将一些在非严格模式下被忽略的错位识别为异常,一些静默行为(无效但非异常操作)会被禁止

  • 防止无意添加全局变量,声明全局变量必须用global关键字
  • 静默行为被禁止 抛出TypeError
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    // 如无效的赋值 
    NaN=0
    // 写入不可写属性
    var obj={}
    Object.defineProperty(obj, 'x', {value:0, writable:false})
    // 写入只读
    var obj={
    get x(){
    return 0;
    }
    }
    obj.x = 2
    // 扩展不可扩展对象
    var fixed = {}
    Object.preventExtensions(fixed)
    fixed.newProp = 0

    vanilla.js

    it’s a joke. 这是一个空的js,用以提醒其他开发者使用plain JavaScript实现,而不要引入任何library

javascript 手写面试题

task 和 microtask

Tasks, microtasks, queues and schedules

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
console.log('script start'); // task

setTimeout(function () {
console.log('setTimeout'); // scheduled task
}, 0);

Promise.resolve()
.then(function () {
console.log('promise1'); // microtask
})
.then(function () {
console.log('promise2');
});

// 结果:
// script start
// promise1
// promise2
// setTimeout

至少Chrome中, Promise.resolve().then()中的回调作为microtask会立即排队等待当前任务执行完, 而setTimeout的回调则在给定延迟之后,排队任务队列中。

节流和防抖

防抖,全时间内后面的覆盖前面的

1
2
3
4
5
6
7
8
9
function debounce(fn, wait){
let timeout
return function(...args){
clearTimeout(timeout)
timeout = setTimeout(()=> {
fn.apply(this, args)
}, wait)
}
}

事实上带有 this 的函数在使用生命周期钩子的vue/react组件中可能并不好用,应在组件范围声明timer, 在响应函数中clear并重新赋值

注意组件unmount时清理timer避免泄露

节流

1
2
3
4
5
6
7
8
9
10
11
var throttle = function(delay, action){
// 这里是个全局变量
var last = 0
return function(){
var curr = new Date()
if (curr - last > delay){
action.apply(this, arguments)
last = curr
}
}
}

禁用文字选中

1
2
3
document.onmousemove = window.getSelection
? window.getSelection().removeAllRanges()
: document.selection.empty();

Angular 9 is available, new release switches applications to the Ivy compiler and runtime by default (Feb, 2020)

模板编译

「模版编译」的工作一般是将使用「声明式语言」描述的「模版」转化为「命令式语言」定义的逻辑代码。鉴于这里的主体是 JavaScript,可以理解为「文本」->「函数」的转换。

Angular 模板编译演变

v2 版本中,Angular 采用了和 Svelte 几乎相同的「编译到指令操作」策略,主要区别是对「视图操作」使用的是基于 Renderer 的抽象指令。这种编译方式确实带来了卓越的性能,但由此带来的明显不便之一是生成代码的大小,在 Trotyl Yu:如何评价 angular 2 中的 AoT?中有给出「模版编译」产物的示例,由于太过占用屏幕空间,不在此处贴出。

v4 版本中,Angular 引入了 View Engine 的概念,建立了公共的运行时部分以减少「编译产物」的大小,而「视图定义」部分也不再使用「编译到指令函数」的策略,而是「编译到工厂函数,类似于(详细代码可以参见 【MMR-A】全新的 View Engine 模式):

1
2
3
4
5
6
7
8
9
10
11
function View_MyComponent() {
return viewDef([
elementDef(1, 'div', [['id', 'foo']]),
elementDef(1, 'p', []),
textDef(['Hello ']),
], (check, view) => {
var comp = view.component;
const currVal_0 = inlineInterpolate('Hello, ', comp.name);
check(view, currVal_0);
});
}

注册响应式表单模块

该模块定义了响应式表单涉及到的组件等类型或构造方法
类定义在@angular/forms包中,会在组件中引用,那么为什么要注册模块?

1
2
3
4
5
6
7
8
9
import { ReactiveFormsModule } from '@angular/forms';

@NgModule({
imports: [
// other imports ...
ReactiveFormsModule
],
})
export class AppModule { }

FormControl

响应式控件类,每个实例对应页面表单中的一个控件,在template中使用formControl=”name”绑定,在FormGroup中使用formControlName=”name”绑定。
edit.component.ts:

1
name = new FormControl('QQstone')

edit.component.html
1
2
<input type="text" [formControl]="name">
<p>{{name.value}}</p>

FormGroup

用于管理一组响应式控件,一个表单可以标记为一个Group,也可以分为多个Group(QQs尚为实践过)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<form #f="ngForm" *ngIf="assetForm" (ngSubmit)="save()" nz-form [formGroup]="assetForm">
<nz-form-label nzSpan="4" nzRequired>Asset Name</nz-form-label>
<nz-form-control nzSpan="8">
<input nz-input formControlName="asset_name" name="name" maxlength="30" placeholder="Name" required />
</nz-form-control>
<nz-form-label nzSpan="4" nzRequired>Status</nz-form-label>
<nz-form-control nzSpan="8">
<nz-select formControlName="status" name="status" nzPlaceHolder="Status"
nzAllowClear required>
<nz-option *ngFor="let item of enum.asset_status" [nzLabel]="item.text" [nzValue]="item.code">
</nz-option>
</nz-select>
</nz-form-control>

</form>

FormBuilder

使用FormBuilder构造FormGroup,每个组件对应一个Array,Array第一个属性是控件初始value,其后是校验器,若存在多个校验器,则该属性为Array
注入 private fb: FormBuilder

1
2
3
4
profileForm = this.fb.group({
name:['', Validators.required],
status:['30']
})

前提 服务号

注册服务号

  • 企业名称
  • 营业执照注册号
  • 验证方式