发表于: 2019-11-12 10:20:04
0 923
一、父组件与子组件及其通信
父组件通过import的方式导入子组件,并在components属性中注册,然后子组件就可以用标签<child>的形式嵌进父组件了。
1.通过prop实现通信
子组件的props选项能够接收来自父组件数据。没错,仅仅只能接收,props是单向绑定的,即只能父组件向子组件传递,不能反向。而传递的方式也分为两种:
(1)静态传递
子组件通过props选项来声明一个自定义的属性,然后父组件就可以在嵌套标签的时候,通过这个属性往子组件传递数据了。
(2)动态传递
我们已经知道了可以像上面那样给 props 传入一个静态的值,但是我们更多的情况需要动态的数据。这时候就可以用 v-bind 来实现。通过v-bind绑定props的自定义的属性,传递去过的就不是静态的字符串了,它可以是一个表达式、布尔值、对象等等任何类型的值。
2.通过$ref 实现通信
对于ref官方的解释是:ref 是被用来给元素或子组件注册引用信息的。引用信息将会注册在父组件的 $refs 对象上。
- 如果ref用在子组件上,指向的是组件实例,可以理解为对子组件的索引,通过$ref可能获取到在子组件里定义的属性和方法。
- 如果ref在普通的 DOM 元素上使用,引用指向的就是 DOM 元素,通过$ref可能获取到该DOM 的属性集合,轻松访问到DOM元素,作用与JQ选择器类似。
那如何通过$ref 实现通信?下面我将上面prop实现的功能,用$ref实现一遍:
通过ref=‘msg'可以将子组件child的实例指给$ref,并且通过.msg.getMessage()调用到子组件的getMessage方法,将参数传递给子组件。
这里再补充一点就是,prop和$ref之间的区别:
- prop 着重于数据的传递,它并不能调用子组件里的属性和方法。像创建文章组件时,自定义标题和内容这样的使用场景,最适合使用prop。
- $ref 着重于索引,主要用来调用子组件里的属性和方法,其实并不擅长数据传递。而且ref用在dom元素的时候,能使到选择器的作用,这个功能比作为索引更常有用到。
3.通过$emit 实现通信
上面两种示例主要都是父组件向子组件通信,而通过$emit 实现子组件向父组件通信。
语法:vm.$emit( event, arg )
$emit 绑定一个自定义事件event,当这个这个语句被执行到的时候,就会将参数arg传递给父组件,父组件通过@event监听并接收参数。
父子组件之间的通信就是 props down,events up,
父组件通过属性props向下传递数据给子组件,子组件通过事件events 给父组件发送消息。
比如,子组件需要某个数据,就在内部定义一个prop属性,然后父组件就像给html元素指定特性值一样,把自己的data属性传递给子组件的这个属性。
而当子组件内部发生了什么事情的时候,就通过自定义事件来把这个事情涉及到的数据暴露出来,供父组件处理。
例一
:msgTest='msgTest2'
:helloTest='helloTest2'
msgTest就是子组件接收的变量(无需再在子组件中声明),需要在子组件中的props中接收( props:['msgTest', 'helloTest', 'CCCount'] )。msgTest2是父组件的变量,需要在父组件中声明。只需要在父组件中给msgTest2赋值即可,子组件中的this.msgTest便能接收到。
例二
<my-component v-bind:foo="baz" v-on:event-a="doThis(arg1,...arg2)"></my-component>
foo是组件内部定义的一个prop属性,baz是父组件的一个data属性,
event-a是子组件定义的一个事件,doThis是父组件的一个方法
子组件向父组件中传值
是通过触发父组件中的函数,并传递一个参数来完成传值的,例如:
this.$emit('childsClick', '子组件触发父组件中的函数')
触发父组件中的@childsClick="btnClick"来调用btnClick方法,并向btnClick方法传参,通过触发方法来向父组件传值。
父组件触发子组件中的函数
通过父组件中的 ref 来触发,父组件中的 this.$refs.msgRef.msgs1() 便是触发子组件中的msgs1()函数。
二、编码规范
对于VUE
CSS样式:
全局样式统一写在 App.vue 中的 style 里面,并添加注释
局部页面加scoped,标明,不得写全局样式
基于模块开发:
始终基于模块的方式来构建你的 app,每一个子模块只做一件事情。()
对于HTML
- 单标签不要写闭合标签,例如 img,br,input
- ul/ol 直接元素只能是 li,li 只能写在 ul/ol 里面
- 行内元素里面不可使用块级元素,a 标签除外
- 文字类块级标签里面不能放其他块级元素
- 每个页面都要写<!DOCType html>,html 要加上 lang 属性
- html 要保持简介,标签嵌套的层数能少则少
- 使用合适的标签
- 如果是按钮就应该写一个 button 或者 input type=”button”,而不是写一个 a 标签设置样式
- 如果是下划线就应该使用 border,而不是写一个固定高度的占位标签
对于CSS
- class 用于标识某一类型的对象,命名必须言简意赅,不要使用样式特点命名,例如 p1,p2,p3 或者颜色
- 命名使用驼峰式命名
- 采用更简洁有语义的英文单词进行组合
- id 用于标识模块或页面的某一父容器区域,名称必须唯一,不要随意新建 id
- 尽量减少选择器的层数。
命名规范
命名规范 | |
---|---|
容器 | box |
页头 | header |
内容 | 内容 |
页面主体 | main |
页尾 | footer |
导航 | nav |
侧边栏 | sidebar |
栏目 | column |
左 右 中 | 左 右 中 |
菜单 | menu |
标题 | title |
摘要 | summary |
布局 | layout |
功能命名 | |
---|---|
标志 | logo |
广告图、轮播图 | banner |
登录 | login |
注册 | regsiter |
搜索 | search |
状态 | status |
按钮 | btn |
滚动 | scroll |
标签页 | tab |
列表 | list |
提示信息 | msg |
图标 | icon |
新闻 | news |
下载 | download |
表单 | form |
返回上一级 | back |
三、简单的正则表达式(基础部分)
万物皆有缘,正则也是如此,元字符是构造正则表达式的一种基本元素。
1. 常用的元字符:
有了元字符之后,我们就可以利用这些元字符来写一些简单的正则表达式了,
比如:
匹配有abc开头的字符串:
\babc或者^abc
匹配8位数字的QQ号码:
^\d\d\d\d\d\d\d\d$
匹配1开头11位数字的手机号码:
^1\d\d\d\d\d\d\d\d\d\d$
2. 重复限定符
有了元字符就可以写不少的正则表达式了,但细心的你们可能会发现:别人写的正则简洁明了,而不理君写的正则一堆乱七八糟而且重复的元字符组成的。正则没提供办法处理这些重复的元字符吗?
答案是有的!
为了处理这些重复问题,正则表达式中一些重复限定符,把重复部分用合适的限定符替代,下面我们来看一些限定符:
有了这些限定符之后,我们就可以对之前的正则表达式进行改造了,
比如:
匹配8位数字的QQ号码:
^\d{8}$
匹配1开头11位数字的手机号码:
^1\d{10}$
匹配银行卡号是14~18位的数字:
^\d{14,18}$
匹配以a开头,0个或多个b结尾的字符串
^ab*$
3. 分组
从上面的例子中看到,*限定符是作用在与他左边最近的一个字符,那么问题来了,如果我想要ab同时被*限定那怎么办呢?
正则表达式中用小括号()来做分组,也就是括号中的内容作为一个整体。因此当我们要匹配多个ab时,我们可以这样
如:匹配字符串中包含0到多个ab开头: ^(ab)*
4. 转义
我们看到正则表达式用小括号来做分组,那么问题来了:
如果要匹配的字符串中本身就包含小括号,那是不是冲突?应该怎么办?
针对这种情况,正则提供了转义的方式,也就是要把这些元字符、限定符或者关键字转义成普通的字符,做法很简答,就是在要转义的字符前面加个斜杠,也就是\即可。
如:要匹配以(ab)开头:
^(\(ab\))*
5. 条件或
回到我们刚才的手机号匹配,我们都知道:国内号码都来自三大网,它们都有属于自己的号段,比如联通有130/131/132/155/156/185/186/145/176等号段,假如让我们匹配一个联通的号码,那按照我们目前所学到的正则,应该无从下手的,因为这里包含了一些并列的条件,也就是“或”,那么在正则中是如何表示“或”的呢?
正则用符号 | 来表示或,也叫做分支条件,当满足正则里的分支条件的任何一种条件时,都会当成是匹配成功。
那么我们就可以用或条件来处理这个问题
^(130|131|132|155|156|185|186|145|176)\d{8}$
6. 区间
看到上面的例子,是不是看到有什么规律?是不是还有一种想要简化的冲动?
实际是有的
正则提供中括号 [] 来表示区间条件。
- 限定0到9 可以写成[0-9]
- 限定A-Z 写成[A-Z]
- 限定某些数字 [165]
那上面的正则我们还改成这样:
^((13[0-2])|(15[5-6])|(18[5-6])|145|176)\d{8}$
以上的正则表达式可以接受john_doe、jo-hn_doe、john12_as,但不能匹配Jo,因为它包含了大写字母而且长度不到3个字符。
四、HTTP协议
五层网络模型
URL构成
协议内容
请求(Request)
客户端发送一个HTTP请求到服务端的格式:
- 请求行
- 请求头
- 请求体
状态码
HTTP状态码由三个十进制数字组成,第一个十进制数字定义了状态码的类型,后两个数字没有分类的作用。HTTP状态码共分为5种类型:
但一般我们只需要知道几个常见的就行,比如
200 (成功):服务器已成功处理了请求。
通常,这表示服务器提供了请求的网页。如果是对您的 robots.txt 文件显示此状态码,则表示 Googlebot 已成功检索到该文件。
201: '新建或修改数据成功。',
202: '一个请求已经进入后台排队(异步任务)。',
204: '删除数据成功。',
304:协商缓存
400(错误请求):服务器不理解请求的语法
(发出的请求有错误,服务器没有进行新建或修改数据的操作)。
401(未授权):请求要求身份验证。对于登录后请求的网页,服务器可能返回此响应。
403(禁止):服务器或主机拒绝请求(用户得到授权,但是访问是被禁止的。)。
404(未找到):服务器找不到请求的网页(服务器没有进行操作)。
服务器上不存在该网页;文件命名错误或位于错误的位置;是旧链接或输入有误的链接。
500(服务器内部错误):服务器遇到错误,无法完成请求。
502(错误网关):服务器作为网关或代理,从上游服务器收到无效响应。
503(服务不可用):服务器目前无法使用(由于超载或停机维护)。通常,这只是暂时状态。
504: '网关超时。'
406: '请求的格式不可得。',
410: '请求的资源被永久删除,且不会再得到的。',
422: '当创建一个对象时,发生一个验证错误。',
请求方法
截止到HTTP1.1共有下面几种方法:
请求和响应常见通用头
注意
Content-Type,内容类型,一般是指网页中存在的Content-Type,用于定义网络文件的类型和网页的编码,决定浏览器将以什么形式、什么编码读取这个文件。
五、axios
axios 是一个基于Promise 用于浏览器和 nodejs 的 HTTP 客户端,本质上也是对原生XHR的封装,只不过它是Promise的实现版本,符合最新的ES规范,它本身具有以下特征:
1.从浏览器中创建 XMLHttpRequest
2.支持 Promise API
3.客户端支持防止CSRF
4.提供了一些并发请求的接口(重要,方便了很多的操作)
5.从 node.js /java创建 http 请求
6.拦截请求和响应
7.转换请求和响应数据
8.取消请求
9.自动转换JSON数据
防止CSRF:就是让你的每个请求都带一个从cookie中拿到的key, 根据浏览器同源策略,假冒的网站是拿不到你cookie中得key的,这样,后台就可以轻松辨别出这个请求是否是用户在假冒网站上的误导输入,从而采取正确的策略。
六、杂
1. 模块化
使用立即执行函数来实现模块化
var module = (function() {
var N = 5;
function print(x) {
console.log("The result is: " + x);
}
function add(a) {
var x = a + N;
print(x);
}
return {
description: "This is description",
add: add
};
})();
console.log(module.description); // 输出"this is description"
module.add(5); // 输出“The result is: 10”
模块化,就是根据需要控制模块内属性与方法的可访问性,即私有或者公开。在代码中,module为一个独立的模块,N为其私有属性,print为其私有方法,decription为其公有属性,add为其共有方法。
2. 变量提升
JavaScript会将所有变量和函数声明移动到它的作用域的最前面,这就是所谓的变量提升(Hoisting)。也就是说,无论你在什么地方声明变量和函数,解释器都会将它们移动到作用域的最前面。因此我们可以先使用变量和函数,而后声明它们。
但是,仅仅是变量声明被提升了,而变量赋值不会被提升。
console.log(y); // 输出undefined
y = 2; // 初始化y
上面的代码等价于下面的代码:
var y; // 声明y
console.log(y); // 输出undefined
y = 2; // 初始化y
3. 柯里化
柯里化,即Currying,可以是函数变得更加灵活。我们可以一次性传入多个参数调用它;也可以只传入一部分参数来调用它,让它返回一个函数去处理剩下的参数。
var add = function(x) {
return function(y) {
return x + y;
};
};
console.log(add(1)(1)); // 输出2
var add1 = add(1);
console.log(add1(1)); // 输出2
var add10 = add(10);
console.log(add10(1)); // 输出11
代码中,我们可以一次性传入2个1作为参数add(1)(1),也可以传入1个参数之后获取add1与add10函数,这样使用起来非常灵活。
4. apply, call与bind方法
它们的共同点是第一个参数都是this,即函数运行时依赖的上下文。
call方法是最简单的,它等价于指定this值调用函数:
var user = {
name: "Rahul Mhatre",
whatIsYourName: function() {
console.log(this.name);
}
};
user.whatIsYourName(); // 输出"Rahul Mhatre",
var user2 = {
name: "Neha Sampat"
};
user.whatIsYourName.call(user2); // 输出"Neha Sampat"
apply方法与call方法类似。两者唯一的不同点在于,apply方法使用数组指定参数,而call方法每个参数单独需要指定:
- apply(thisArg, [argsArray])
- call(thisArg, arg1, arg2, …)
var user = {
greet: "Hello!",
greetUser: function(userName) {
console.log(this.greet + " " + userName);
}
};
var greet1 = {
greet: "Hola"
};
user.greetUser.call(greet1, "Rahul"); // 输出"Hola Rahul"
user.greetUser.apply(greet1, ["Rahul"]); // 输出"Hola Rahul"
使用bind方法,可以为函数绑定this值,然后作为一个新的函数返回:
var user = {
greet: "Hello!",
greetUser: function(userName) {
console.log(this.greet + " " + userName);
}
};
var greetHola = user.greetUser.bind({greet: "Hola"});
var greetBonjour = user.greetUser.bind({greet: "Bonjour"});
greetHola("Rahul") // 输出"Hola Rahul"
greetBonjour("Rahul") // 输出"Bonjour Rahul"
评论