查看最近已登录的是连接到服务器的最大数量的IP的列表

如何确认是否受到DDOS攻击?
登录到你的服务器以root用户执行下面的命令,使用它你可以检查你的服务器是在DDOS攻击与否:
- netstat -ntu | awk '{print $5}' | cut -d: -f1 | sort | uniq -c | sort -n
执行后,将会显示服务器上所有的每个IP多少个连接数。每个IP几个、十几个或几十个连接数都还算比较正常,如果像上面成百上千肯定就不正常了,该命令将显示已登录的是连接到服务器的最大数量的IP的列表。
另外还有其他情况,使DDOS变得更为复杂,因为攻击者在使用更少的连接,更多数量IP的攻击服务器的情况下,你得到的连接数量较少,即使你的服务器被攻击了。有一点很重要,你应该检查当前你的服务器活跃的连接信息,执行以下命令:
- netstat -n | grep :80 |wc –l
上面的命令将显示所有打开你的服务器的活跃连接。
您也可以使用如下命令:
- netstat -n | grep :80 | grep SYN |wc –l
从第一个命令有效连接的结果会有所不同,但如果它显示连接超过500,那么将肯定有问题。
如果第二个命令的结果是100或以上,那么服务器可能被同步攻击。
一旦你获得了攻击你的服务器的IP列表,你可以很容易地阻止它。
php json 处理gbk转码utf-8问题( json_encode转换数组,值为null)

遇到个很幼稚的问题,用json_encode把数组转换为json时,发现转化的值为null。怎么回事呢?查找手册:发现了下面的话:
- function encodeConvert($str,$fromCode,$toCode)
- {
- if (strtoupper($toCode) == strtoupper($fromCode)) return $str;
- if (is_string($str)) {
- if (function_exists('mb_convert_encoding')) {
- return mb_convert_encoding($str, $toCode, $fromCode);
- } else {
- return iconv($fromCode, $toCode, $str);
- }
- } elseif (is_array($str)) {
- foreach ($str as $k => $v) {
- $str[$k] = encodeConvert($v, $fromCode, $toCode);
- }
- return $str;
- }
- return $str;
- }
- $json_api=json_encode(encodeConvert($json_api,'gb2312','utf-8'));
- $json_api=json_decode(json_decode($json_api));
今天数组json_encode转json的时候,输出一片空白,难道是数据量太大了?导致输出空白了?
后来检查下php程序似乎没有出错,就是json_encode的时候出现了问题,那到底是什么问题呢?
我们先来说下json_encode这个函数
- (PHP 5 >= 5.2.0, PECL json >= 1.2.0, PHP 7)
- json_encode — 对变量进行 JSON 编码
- 说明
- -----------------------------------------------------------
- string json_encode ( mixed $value [, int $options = 0 [, int $depth = 512 ]] )
- 参数
- -----------------------------------------------------------
- value
- 待编码的 value ,除了resource 类型之外,可以为任何数据类型。
- 所有字符串数据的编码必须是 UTF-8。
- options
- 由以下常量组成的二进制掩码: JSON_HEX_QUOT, JSON_HEX_TAG, JSON_HEX_AMP, JSON_HEX_APOS, JSON_NUMERIC_CHECK, JSON_PRETTY_PRINT, JSON_UNESCAPED_SLASHES, JSON_FORCE_OBJECT, JSON_PRESERVE_ZERO_FRACTION, JSON_UNESCAPED_UNICODE, JSON_PARTIAL_OUTPUT_ON_ERROR。
- depth
- 设置最大深度。 必须大于0。
- 返回值
- -----------------------------------------------------------
- 成功则返回 JSON 编码的 string 或者在失败时返回 FALSE 。
注意:上面对参数明确说明(所有字符串数据的编码必须是 UTF-8)
可能正是因为这一点导致我输出错误,但是我怎么知道,会是这个错误呢?因为我发现有一个这个函数json_last_error
我们看下这个函数
- (PHP 5 >= 5.3.0, PHP 7)
- json_last_error — 返回最后发生的错误
- 说明
- -----------------------------------------------------------
- int json_last_error ( void )
- 如果有,返回 JSON 编码解码时最后发生的错误。
- 参数
- -----------------------------------------------------------
- 此函数没有参数。
- 返回值
- -----------------------------------------------------------
- 返回一个整型(integer),这个值会是以下的常量之一:
- 例如:
- echo json_encode(array('error' => '0', 'message' => '没有错误'));
- var_dump(json_last_error());
- //这里也可以是json_decode
- //错误码对照
- 0 JSON_ERROR_NONE
- 1 JSON_ERROR_DEPTH
- 2 JSON_ERROR_STATE_MISMATCH
- 3 JSON_ERROR_CTRL_CHAR
- 4 JSON_ERROR_SYNTAX
- 5 JSON_ERROR_UTF8
- 6 JSON_ERROR_RECURSION
- 7 JSON_ERROR_INF_OR_NAN
- 8 JSON_ERROR_UNSUPPORTED_TYPE
我返回的是 int 5,对照返回错误码,自然而然就是(异常的 UTF-8 字符,也许是因为不正确的编码)这个错误了,知道错误后,然后检查你要返回的数据,再做下处理就OK了。
快速对字符转义,避免跨站攻击XSS

XSS已经成为非常流行的网站攻击方式,为了安全起见,尽量避免用户的输入。可是有些情况下不仅不避免,反而要求鼓励输入,比如写博客。博客园开放性很高,可以运行手写的JS。之前比较著名的例子就是,凡是看到某一篇文章的,都自动关注他。
如果避免跨站攻击的话,我们就得对用户的输入,进行转义。例如<script type='text/javascript'>alert('hello world')</script>。如果直接保存这个字符串的话,然后再输出的话,就会运行JS了。我们需要将这个字符串转义成"<script type='text/javascript'>alert('hello world')</script>"。
转义,就是一个个字符的匹配,然后转换。看着不难,但是需要转义的字符也不少。另外当字符数量大的时候,效率成为一个问题。下面我写一个函数,让浏览器底层帮我们做到。
- function stringEncode(str){
- var div=document.createElement('div');
- if(div.innerText){
- div.innerText=str;
- }else{
- div.textContent=str;//Support firefox
- }
- return div.innerHTML;
- }
xss漏洞以及防御实现

XSS三种类型
- 存储型XSS:数据库中存在XSS攻击的数据,若数据未经过任何转义,返回给客户端。被浏览器渲染,就可能导致XSS攻击
- 反射型XSS:将用户输入的存在XSS攻击的数据,发送给服务端,服务端并未对数据进行存储,也未经过任何转义,直接返回给客户端。被浏览器渲染。就可能导致XSS攻击
- 纯粹发生在客户端的XSS攻击
XSS攻击演示
假设用户输入的参数为:
- <script>alert(xss)</script>
如果后台没有对该数据做任何过滤直接显示到前端<div>标签中的话,源代码就变成了这样:
- <div><script>alert(xss)</script><div>
那么在前端显示出来的是一个写着xss的弹窗,就发生了xss攻击
防御方案
我在项目中的主要的防御方案是对数据的过滤,对于数据中的危险字符进行相应的转义:
- &----->&
- <-----><
- >----->>
- "----->"
- '----->'
- /----->/
iPhone所有手机型号屏幕尺寸(2020-04-17更新)

手机型号 | 尺寸(对角线) | 物理点 | 宽长比例 | 像素点 | 倍数 | 状态栏高度 | 底部安全距离 | 导航栏高度 | tabbar高度 |
---|---|---|---|---|---|---|---|---|---|
iPhone 4/4S | 3.5英寸 | 320x480 | 0.667 | 640x960 | @2x | 20 | - | 44 | 49 |
iPhone 5/5S/5C | 4英寸 | 320x568 | 0.563 | 640x1136 | @2x | 20 | - | 44 | 49 |
iPhone SE | 4英寸 | 320x568 | 0.563 | 640x1136 | @2x | 20 | - | 44 | 49 |
iPhone 6 | 4.7英寸 | 375x667 | 0.562 | 750x1334 | @2x | 20 | - | 44 | 49 |
iPhone 6 Plus | 5.5英寸 | 414x736 | 0.563 | 1242x2208 | @3x | 20 | - | 44 | 49 |
iPhone 6S | 4.7英寸 | 375x667 | 0.562 | 750x1334 | @2x | 20 | - | 44 | 49 |
iPhone 6S Plus | 5.5英寸 | 414x736 | 0.563 | 1242x2208 | @3x | 20 | - | 44 | 49 |
iPhone 7 | 4.7英寸 | 375x667 | 0.562 | 750x1334 | @2x | 20 | - | 44 | 49 |
iPhone 7 Plus | 5.5英寸 | 414x736 | 0.563 | 1242x2208 | @3x | 20 | - | 44 | 49 |
iPhone 8 | 4.7英寸 | 375x667 | 0.562 | 750x1334 | @2x | 20 | - | 44 | 49 |
iPhone 8 Plus | 5.5英寸 | 414x736 | 0.563 | 1242x2208 | @3x | 20 | - | 44 | 49 |
iPhone X | 5.8英寸 | 375x812 | 0.462 | 1125x2436 | @3x | 44 | 34 | 44 | 83 |
iPhone XS | 5.8英寸 | 375x812 | 0.462 | 1125x2436 | @3x | 44 | 34 | 44 | 83 |
iPhone XS Max | 6.5英寸 | 414x896 | 0.462 | 1242x2688 | @3x | 44 | 34 | 44 | 83 |
iPhone XR | 6.1英寸 | 414x896 | 0.462 | 828x1792 | @2x | 44 | 34 | 44 | 83 |
iPhone 11 | 6.1英寸 | 414x896 | 0.462 | 828x1792 | @2x | 44 | 34 | 44 | 83 |
iPhone 11 Pro | 5.8英寸 | 375x812 | 0.462 | 1125x2436 | @3x | 44 | 34 | 44 | 83 |
iPhone 11 Pro Max | 6.5英寸 | 414x896 | 0.462 | 1242x2688 | @3x | 44 | 34 | 44 | 83 |
iPhone SE 2020款 | 4.7英寸 | 375x667 | 0.562 | 750x1334 | @2x | 20 | - | 44 | 49 |
Visual Studio Code 快捷键 Mac 版

Mac 键盘符号说明
⌘
==Command
⇧
==Shift
⇪
==Caps Lock
⌥
==Option
⌃
==Control
↩
==Return/Enter
⌫
==Delete
⌦
==向前删除键(Fn+Delete)
↑
==上箭头
↓
==下箭头
←
==左箭头
→
==右箭头
⇞
==Page Up(Fn+↑)
⇟
==Page Down(Fn+↓)
Home
==Fn + ←
End
==Fn + →
⇥
==右制表符(Tab键)
⇤
==左制表符(Shift+Tab)
⎋
==Escape (Esc)
⏏
==电源开关键
俗话说得好,工欲善其事必先利其器,要想工作效率高,码代码的工具用的好是必须的,这里主要说一下 Mac 上 VScode 的快捷键,帮助大家快速搭建良好的开发工具。
必备插件
- Auto Close Tag - 自动闭合 HTML 标签
- Auto Import - 自动 import 插件
- Auto Rename Tag - 修改 HTML 标签时,自动修改匹配的标签
- Bracket Pair Colorizer - 给括号前后进行着色
- Can I Use - HTML5、CSS3、SVG 的浏览器兼容性检查
- Code Spell Checker - 检查代码中的拼写错误
- Code Runner - 运行选中代码段(支持大量语言,包括 Node)
- Git Blame - 在状态栏显示当前行的 Git 信息
- Git History - 查看 git log
- GitLens - 显示文件最近的 commit 和作者,显示当前行 commit 信息
- ESLint - ESLint 插件
- Debugger for Chrome - 配合 chrome 进行 debug
- HTML CSS Support - html,css 提示
- HTMLHint - HTML 格式提示
- JavaScript (ES6) code snippets - 支持 ES6 语法代码段
- JavaScript Snippet Pack - 使用简单的两个字母就可以生成 JS 语句,需要记忆
- jQuery Code Snippets - jquery 快捷提示,安装了之后输入 jq 就会看到很多提醒
- language-stylus - 支持 stylus
- Material Icon Theme - icon 样式,很好看
- npm - 运行 npm 命令
- npm Intellisense - 导入模块时,提示已安装模块名称
- open in browser - 在浏览器运行当前页面,快捷键(option+B)
- Output Colorizer - 控制台输出着色
- Panda Theme - 一个主题
- Path Intellisense - 路径自动补充
- Prettier - 代码美化,快捷键(shift+option+F)
- Vetur - 目前比较好的 Vue 语法高亮
常用
Mac 快捷键 | 介绍 |
---|---|
⇧⌘P, F1 | 显示命令面板 |
⌘P | 快速打开 |
⇧⌘N | 新建 窗口/实例 |
⌘W | 关闭 窗口/实例 |
基本编辑
Mac 快捷键 | 介绍 |
---|---|
⌘X | 剪切 |
⌘C | 复制 |
⌥↓ / ⌥↑ | 移动当前行向 下/上 |
⇧⌥↓ / ⇧⌥↑ | 复制当前行向 下/上 |
⇧⌘K | 删除当前行 |
⌘Enter / ⇧⌘Enter | 在下/上 插入一行 |
⇧⌘\ | 跳转到匹配的括号 |
⌘] / ⌘[ | 向左/向右 缩进当前行 |
Home / End | 跳到当前行的头部,尾部 |
⌘↑ / ⌘↓ | 跳到当前行的开始,结束 |
⌃PgUp | 滚动到 |
⌃PgDown | 滚动到行头/行尾 |
⌘PgUp /⌘PgDown | 滚动到页头/页尾 |
⇧⌘[ / ⇧⌘] | 折叠/展开区域 |
⌘K ⌘[ / ⌘K ⌘] | 折叠/展开所有子区域 |
⌘K ⌘0 / ⌘K ⌘J | 折叠/展开所有区域 |
⌘K ⌘C | 添加行注释 |
⌘K ⌘U | 删除行注释 |
⌘/ | 切换行注释 |
⇧⌥A | 切换块注释 |
⌥Z | 切换文字换行 |
多光标和选择
Mac 快捷键 | 介绍 |
---|---|
Alt+Click | 插入光标 |
⌥⌘↑ | 在上面插入光标 |
⌥⌘↓ | 在下面插入光标 |
⌘U | 撤消上一个光标操作 |
⇧⌥I | 在所选每行的末尾插入光标 |
⌘I | 选择当前行 |
⇧⌘L | 选择当前选择的所有事件 |
⌘F2 | 选择当前单词的所有出现 |
⌃⇧⌘→ | 展开选择 |
⌃⇧⌘← | 收缩选择 |
Shift+Alt + drag mouse(拖动鼠标) | 列(框)选择 |
⇧⌥⌘↑ | 向上列(框)选择 |
⇧⌥⌘↓ | 向下列(框)选择 |
⇧⌥⌘← | 向左列(框)选择 |
⇧⌥⌘→ | 向右列(框)选择 |
⇧⌥⌘PgUp | 列(框)选择 向上一页 |
⇧⌥⌘PgDown | 列(框)选择 向下一页 |
搜索和替换
Mac 快捷键 | 介绍 |
---|---|
⌘F | 查找 |
⌥⌘F | 替换 |
⌘G / ⇧⌘G | 查找下一个/上一个 |
⌥Enter | 选择查找匹配的所有匹配项 |
⌘D | 将选择添加到下一个查找匹配 |
⌘K ⌘D | 将最后一个选择移至下一个查找匹配项 |
丰富的语言编辑
Mac 快捷键 | 介绍 |
---|---|
⌃Space | 触发建议 |
⇧⌘Space | 触发参数提示 |
Tab | Emmet扩展缩写 |
⇧⌥F | 格式化文档 |
⌘K ⌘F | 格式选择 |
F12 | 转到定义 |
⌥F12 | Peek定义 |
⌘K F12 | 打开定义到一边 |
⌘. | 快速修复 |
⇧F12 | 显示引用 |
F2 | 重命名符号 |
⇧⌘. / ⇧⌘, | 替换为下一个/上一个值 |
⌘K ⌘X | 修剪尾随空格 |
⌘K M | 更改文件语言 |
导航
Mac 快捷键 | 介绍 |
---|---|
⌘T | 显示所有符号 |
⌃G | 转到行... |
⌘P | 转到文件... |
⇧⌘O | 转到符号... |
⇧⌘M | 显示问题“面板” |
F8 / ⇧F8 | 转到下一个/上一个错误或警告 |
⌃⇧Tab | 浏览编辑器组历史记录 |
⌃- / ⌃⇧- | 后退/前进 |
⌃⇧M | 切换选项卡移动焦点 |
编辑器管理
Mac 快捷键 | 介绍 |
---|---|
⌘W | 关闭编辑窗口 |
⌘K F | 关闭文件 |
⌘\ | 拆分编辑窗口 |
⌘1 / ⌘2 / ⌘3 | 聚焦到第1,第2,第3编辑器组中 |
⌘K ⌘← / ⌘K ⌘→ | 聚焦到上一个/下一个编辑器组 |
⌘K ⇧⌘← / ⌘K ⇧⌘→ | 向左/向右移动编辑器 |
⌘K ← / ⌘K → | 移动活动编辑器组 |
文件管理
Mac 快捷键 | 介绍 |
---|---|
⌘N | 新建文件 |
⌘O | 打开文件 |
⌘S | 保存 |
⇧⌘S | 保存为... |
⌥⌘S | 保存所有 |
⌘W | 关闭 |
⌘K ⌘W | 关闭所有 |
⇧⌘T | 重新打开已关闭的编辑器 |
⌘K | 输入保持打开 |
⌃Tab / ⌃⇧ | 选项卡打开下一个/上一个 |
⌘K P | 复制活动文件的路径 |
⌘K R | 在资源管理器中显示活动文件 |
⌘K O | 在新窗口/实例中显示活动文件 |
显示
Mac 快捷键 | 介绍 |
---|---|
⌃⌘F | 切换全屏 |
⌥⌘1 | 切换编辑器布局 |
⌘= / ⇧⌘- | 放大/缩小 |
⌘B | 切换侧栏可见性 |
⇧⌘E | 显示资源管理器/切换焦点 |
⇧⌘F | 显示搜索 |
⌃⇧G | 显示Git |
⇧⌘D | 显示Debug |
⇧⌘X | 显示扩展名 |
⇧⌘H | 在文件中替换 |
⇧⌘J | 切换搜索详细信息 |
⇧⌘C | 打开新命令提示符/终端 |
⇧⌘U | 显示输出面板 |
⇧⌘V | 切换Markdown预览 |
⌘K V | 打开Markdown预览到一边 |
调试
Mac 快捷键 | 介绍 |
---|---|
F9 | 切换断点 |
F5 | 开始/继续 |
F11 / ⇧F11 | 跳进/出 |
F10 | 跳过 |
⇧F5 | 暂停 |
⌘K ⌘I | 显示悬停 |
集成终端
Mac 快捷键 | 介绍 |
---|---|
⌃` | 显示集成终端 |
⌃⇧` | 创建新终端 |
unassigned(末分配) | 复制选择 |
unassigned(末分配) | 粘贴到活动终端 |
⌘↑ | 向上滑动 |
⌘↓ | 下身滑动 |
PgUp | 向上滚动页面 |
PgDown | 向下滚动页面 |
⌘Home | 滚动到顶部 |
⌘End | 滚动到尾部 |
Vue props用法详解

Vue props用法详解
组件接受的选项之一 props 是 Vue 中非常重要的一个选项。父子组件的关系可以总结为:
props down, events up
父组件通过 props 向下传递数据给子组件;子组件通过 events 给父组件发送消息。
父子级组件
比如我们需要创建两个组件 parent 和 child。需要保证每个组件可以在相对隔离的环境中书写,这样也能提高组件的可维护性。
这里我们先定义父子两个组件和一个 Vue 对象:
- <div id="example">
- <parent></parent>
- </div>
- var childNode = {
- template: `
- <div>childNode</div>
- `
- };
- var parentNode = {
- template: `
- <div>
- <child></child>
- <child></child>
- </div>
- `,
- components: {
- child: childNode
- }
- };
- new Vue({
- el: "#example",
- components: {
- parent: parentNode
- }
- });
这里的 childNode 定义的 template 是一个 div,并且内容是"childNode"字符串。
而在 parentNode 的 template 中定义了 div 的 class 名叫 parent 并且包含了两个 child 组件。
静态 props
组件实例的作用域是孤立的。这意味着不能(也不应该)在子组件的模板中直接饮用父组件的数据。要让子组件使用父组件的数据,需要通过子组件的 props 选项。
父组件向子组件传递数据分为两种方式:动态和静态,这里先介绍静态方式。
子组件要显示的用 props 声明它期望获得的数据
修改上例中的代码,给 childNode 添加一个 props 选项和需要的forChildMsg
数据;
然后在父组件中的占位符添加特性的方式来传递数据。
- var childNode = {
- template: `
- <div>
- {{forChildMsg}}
- </div>
- `,
- props: ["for-child-msg"]
- };
- var parentNode = {
- template: `
- <div>
- <p>parentNode</p>
- <child for-child-msg="aaa"></child>
- <child for-child-msg="bbb"></child>
- </div>
- `,
- components: {
- child: childNode
- }
- };
命名规范
对于 props 声明的属性,在父组件的 template 模板中,属性名需要使用中划线写法;
子组件 props 属性声明时,使用小驼峰或者中划线写法都可以;而子组件的模板使用从父组件传来的变量时,需要使用对应的小驼峰写法。别担心,Vue 能够正确识别出小驼峰和下划线命名法混用的变量,如这里的forChildMsg
和for-child-msg
是同一值。
动态 props
在模板中,要动态地绑定父组件的数据到子组件模板的 props,和绑定 Html 标签特性一样,使用v-bind
绑定;
基于上述静态 props 的代码,这次只需要改动父组件:
- var parentNode = {
- template: `
- <div>
- <p>parentNode</p>
- <child :for-child-msg="childMsg1"></child>
- <child :for-child-msg="childMsg2"></child>
- </div>
- `,
- components: {
- child: childNode
- },
- data: function() {
- return {
- childMsg1: "Dynamic props msg for child-1",
- childMsg2: "Dynamic props msg for child-2"
- };
- }
- };
在父组件的 data 的 return 数据中的 childMsg1 和 childMsg2 会被传入子组件中,
props 验证
验证传入的 props 参数的数据规格,如果不符合数据规格,Vue 会发出警告。
能判断的所有种类(也就是 type 值)有:
String, Number, Boolean, Function, Object, Array, Symbol
- Vue.component("example", {
- props: {
- // 基础类型检测, null意味着任何类型都行
- propA: Number,
- // 多种类型
- propB: [String, Number],
- // 必传且是String
- propC: {
- type: String,
- required: true
- },
- // 数字有默认值
- propD: {
- type: Number,
- default: 101
- },
- // 数组、默认值是一个工厂函数返回对象
- propE: {
- type: Object,
- default: function() {
- console.log("propE default invoked.");
- return { message: "I am from propE." };
- }
- },
- // 自定义验证函数
- propF: {
- isValid: function(value) {
- return value > 100;
- }
- }
- }
- });
- let childNode = {
- template: "<div>{{forChildMsg}}</div>",
- props: {
- "for-child-msg": Number
- }
- };
- let parentNode = {
- template: `
- <div class="parent">
- <child :for-child-msg="msg"></child>
- </div>
- `,
- components: {
- child: childNode
- },
- data() {
- return {
- // 当这里是字符串 "123456"时会报错
- msg: 123456
- };
- }
- };
还可以在 props 定义的数据中加入自定义验证函数,当函数返回 false 时,输出警告。
比如我们把上述例子中的 childNode 的for-child-msg
修改成一个对象,并包含一个名叫validator
的函数,该命名是规定叫validator
的,自定义函数名不会生效。
- let childNode = {
- template: "<div>{{forChildMsg}}</div>",
- props: {
- "for-child-msg": {
- validator: function(value) {
- return value > 100;
- }
- }
- }
- };
在这里我们给for-child-msg
变量设置了validator
函数,并且要求传入的值必须大于 100,否则报出警告。
单向数据流
props 是单向绑定的:当父组件的属性变化时,将传导给子组件,但是不会反过来。这是为了防止子组件五一修改父组件的状态。
所以不应该在子组件中修改 props 中的值,Vue 会报出警告。
- let childNode = {
- template: `
- <div class="child">
- <div>
- <span>子组件数据</span>
- <input v-model="forChildMsg"/>
- </div>
- <p>{{forChildMsg}}</p>
- </div>`,
- props: {
- "for-child-msg": String
- }
- };
- let parentNode = {
- template: `
- <div class="parent">
- <div>
- <span>父组件数据</span>
- <input v-model="msg"/>
- </div>
- <p>{{msg}}</p>
- <child :for-child-msg="msg"></child>
- </div>
- `,
- components: {
- child: childNode
- },
- data() {
- return {
- msg: "default string."
- };
- }
- };
这里我们给父组件和子组件都有一个输入框,并且显示出父组件数据和子组件的数据。当我们在父组件的输入框输入新数据时,同步的子组件数据也被修改了;这就是 props 的向子组件传递数据。而当我们修改子组件的输入框时,浏览器的控制台则报出错误警告
[Vue warn]: Avoid mutating a prop directly since the value will be overwritten whenever the parent component re-renders. Instead, use a data or computed property based on the prop's value. Prop being mutated: "forChildMsg"
修改 props 数据
通常有两种原因:
- prop 作为初始值传入后,子组件想把它当做局部数据来用
- prop 作为初始值传入后,由子组件处理成其他数据输出
应对办法是
- 定义一个局部变量,并用 prop 的值初始化它
但是由于定义的 ownChildMsg 只能接受 forChildMsg 的初始值,当父组件要传递的值变化发生时,ownChildMsg 无法收到更新。
- let childNode = {
- template: `
- <div class="child">
- <div>
- <span>子组件数据</span>
- <input v-model="forChildMsg"/>
- </div>
- <p>{{forChildMsg}}</p>
- <p>ownChildMsg : {{ownChildMsg}}</p>
- </div>`,
- props: {
- "for-child-msg": String
- },
- data() {
- return { ownChildMsg: this.forChildMsg };
- }
- };
这里我们加了一个<p>用于查看 ownChildMsg 数据是否变化,结果发现只有默认值传递给了 ownChildMsg,父组件改变只会变化到 forChildMsg,不会修改 ownChildMsg。
- 定义一个计算属性,处理 prop 的值并返回
由于是计算属性,所以只能显示值,不能设置值。我们这里设置的是一旦从父组件修改了 forChildMsg 数据,我们就把 forChildMsg 加上一个字符串"---ownChildMsg",然后显示在屏幕上。这时是可以每当父组件修改了新数据,都会更新 ownChildMsg 数据的。
- let childNode = {
- template: `
- <div class="child">
- <div>
- <span>子组件数据</span>
- <input v-model="forChildMsg"/>
- </div>
- <p>{{forChildMsg}}</p>
- <p>ownChildMsg : {{ownChildMsg}}</p>
- </div>`,
- props: {
- "for-child-msg": String
- },
- computed: {
- ownChildMsg() {
- return this.forChildMsg + "---ownChildMsg";
- }
- }
- };
- 更加妥帖的方式是使用变量存储 prop 的初始值,并用 watch 来观察 prop 值得变化。发生变化时,更新变量的值。
- let childNode = {
- template: `
- <div class="child">
- <div>
- <span>子组件数据</span>
- <input v-model="forChildMsg"/>
- </div>
- <p>{{forChildMsg}}</p>
- <p>ownChildMsg : {{ownChildMsg}}</p>
- </div>`,
- props: {
- "for-child-msg": String
- },
- data() {
- return {
- ownChildMsg: this.forChildMsg
- };
- },
- watch: {
- forChildMsg() {
- this.ownChildMsg = this.forChildMsg;
- }
- }
- };
初入大前端小白们,需要明白的几个概念问题(持续更新)

1, npm install是帮助安装 vue,或React到本地,npm install也可以安装vue,React的开发工具。当然你完全可以像jQuery一样自己找网站下载下来,在页面中引入。
2,没有npm可以使用vue,vue只是一个前端框架。
3,4,node是js的服务执行环境,前端常常借助 node帮助前端实现工程化。很多工具是基于node的,比如说你说的webpack,grunt。
5,webpack,grunt是前端工程化的工具,可以帮助前端完成混淆压缩,校验等工作。
6,7,实战中没用过,请参考官方文档http://cn.vuejs.org/v2/guide/...
8,可以单纯的利用 php+vue或者php+react开发。
9,最后一个问题太大,可以写本书。而且老实讲,一切都需要实战中才能有更深的体会。
最后总结一下:
前端圈所谓得“乱”,一个是近些年前端框架层出不穷,工程化,解决方案越来越多,已经脱离了一般人认为的那个“好单纯好不做作”的前端。就像后端开发有很多工具协作开发一样,前端也需要越来越多的工作完成前端面临巨大的工作量。 前端的行业发展已经不是那种后端在php,jsp中写一些html,前端来写一些css来完成工作的阶段。老实讲,我现在80%的时间在写js。前端已经不是后端开发的最后一步甚至“附属品”,而成为真正意义的“客户端”。复杂度也就慢慢和app等客户端越来越接近。
总的来说,你还是可以按照原先的开发方式来开发自己的应用,当然考虑引进工具一些先进的理念方法来协助开发。node,webpack,vue这些概念不应该成为自己开发中的阻碍,而是在自己在面临一些问题时的利剑。这些概念的学习需要一天一天的来,毕竟一口吃不成个胖子 :)
什么是npm?
从事网站制作的小前端们都知道cdn的概念,也就是在网站制作中如果我们需要jquery或者bootstrap等文件支持的话,就可以通过cdn引入的方式来实现调用。由于node的使用日益广泛,也带动了其组件npm的使用,而npm就是这些jquery以及bootstrap这些文件包的组合管理器。现在只要使用了node环境进行web网站开发,你就可以直接用npm进行调用以前所有的cdn文件了。
什么是webpack?
webpack简单来说就是前端代码资源的包管理工具,他自动整理你的项目结构,结合javascript的模块化组件,机型解析并交给浏览器渲染使用,大大提高前端的开发效率。
什么是vue-cli?它与vue脚手架有什么关系?
其实vue-cli就是vue的脚手架,vue脚手架的作用是用来自动一键生成vue+webpack的项目模版,包括依赖库,免去你手动安装各种插件,寻找各种cdn并一个个引入的麻烦。
什么是node.js?它与vue具体有什么关系?
提到vue就不得不说node了,vue作为一个前端框架技术,主要负责了数据渲染,界面展示效果,由于其易用性及便捷的维护应用日益广泛。而node作为一个服务器端语言,它是以javascript语言为基础的服务端程序语言,在实际的项目开发中,前端人员只要实现了环境的搭建,其实就可以仅仅从后台拿api接口进行数据调用,从而全部完成整个前端项目的展示。
前端由于近两年web前端技术发展革新速度飞快,一旦错过了,可能重新学的速度是非常慢的,只要尽早入手才能获得最好的学习效果。全栈网络专业从事郑州网站制作,我们也有专业的网站制作团队,愿意为每一个前端人员提供最新的前端知识分享。
vue await fetch 使用

await/async 是 ES7 最重要特性之一,它是目前为止 JS 最佳的异步解决方案了。
- async function timeout() {
- return 'hello world';
- }
- async function timeout() {
- return 'hello world'
- }
- timeout();
- console.log('虽然在后面,但是我先执行');
fetch 基本使用方法点击 这里
下边一个小例子说个基本的请求吧
- <template>
- <div id="app">
- <button @click="fetchData()" >fetch 获取数据</button>
- <p>{{text}}</p>
- </div>
- </template>
- <script>
- export default {
- name: 'app',
- data () {
- return {
- text:''
- }
- },
- methods:{
- fetchData(){
- // fetch是相对较新的技术,当然就会存在浏览器兼容性的问题,当前各个浏览器低版本的情况下都是不被支持的,因此为了在所有主流浏览器中使用fetch 需要考虑 fetch 的 polyfill 了
- async function ff(){
- let data = await fetch('../static/data.json').then(res => res.json());
- console.log(data,'data');
- return data;
- }
- ff().then(res => {
- console.log(res,'res');
- this.text = 'name:'+res.name+',age:'+res.age+'sex:'+res.sex;
- }).catch(reason => console.log(reason.message));
- }
- }
- }
- </script>
- <style lang="scss">
- </style>
vue中 fetch跨域请求

fetch 是原生javaScript提供的,它可以当作全局变量使用,挂载在window对象身上的
fetch的get请求方法
简单基本的fetch请求(get)
- <div id="app">
- <button @click="getData">get请求</button>
- </div>
- <script>
- 是原生javaScript提供的,它可以当作全局变量使用,挂载在window对象身上的
- new Vue({
- // fetch
- el:"#app",
- methods:{
- getData(){
- // var p=fetch();
- // console.log(p)//fetch方法也是promise对象
- fetch('./data/name.json')
- .then( (res) => { return res.json() } )//对fetch进行格式化,否则读取不到内容
- .then( (data) => { console.log(data)} )//拿到格式化后的数据data
- .catch(error=>console.log(error))
- },
- },
- })
注意事项:
A: fetch 的 get 请求的参数是直接连接在url上的, 我们可以使用Node.js提供的url或是qureystring模块来将
Object --> String
B: fetch 的请求返回的是Promise对象,所以我们可以使用.then().catch(),但是要记住.then()至少要写两个, 第一个then是用来格式
- 格式化处理的其他方式
- fetch('./data.json')
- .then(res=>{
- res.json() //格式化json数据
- //res.text()格式胡文本数据
- //res.blob()==格式化二进制文件==
- })
- .then( data => console.log(data))
- .catch( error => console.log( error ))
fetch的post请求方法
代码示例
- <div id="app">
- <button @click="postData">post请求</button>
- </div>
- <script>
- new Vue({
- // fetch
- el:"#app",
- methods:{
- postData(){
- fetch('http://10.31.161.60:8080',{
- method:'post',
- hearders:new Headers({
- //设置请求头,解决跨域问题
- 'Content-Type':'application/x-www-form-urlencoded'
- }),
- //解决请求数据类型限制的问题
- // body:new URLSearchParams([["a", 1],["b", 2]]).toString()
- })
- .then( res => res.text() )
- .then( data => console.log( data ))
- .catch( error => console.log( error ))
- }
- },
- })
总结
fetch要手动进行一次数据格式化,但是axios是内部进行了数据的格式化
fetch get 方法请求数据,参数要直接连接在url上
fetch 格式化数据 有三种 处理方法
.json() 格式化 json 类型数据, 将 json类型 string 转换成 json 对象
.text() 格式化文本
.blob() 格式化二进制数据
fetch 书写post请求、处理
设置请求头
通过 new URLSearchPrams 来携带参数