获取JSON对象key及vulue

- var arr = [
- {
- "原告性别": "女",
- "出生日期": "XX1年1月1X日",
- "居住地址": "北京市丰台区XXXXX",
- "所属民族": "汉族",
- "电话号码": "XXXXXX78",
- "原告姓名": "XXX"
- },
- {
- "原告性别": "男",
- "出生日期": "1992年6月10日",
- "居住地址": "北京市通州区XXXXX",
- "所属民族": "汉族",
- "电话号码": "18701519435",
- "原告姓名": "xxx"
- }
- ]
- /*** 遍历数组中的JSON对象 ***/
- for (var i=0; i<arr.length; i++){
- var keys=Object.keys(arr[i]);
- console.log('keys:', keys);
- }
- //keys: (6) ['原告性别', '出生日期', '居住地址', '所属民族', '电话号码', '原告姓名']
JS 中如何优雅的使用多层嵌套属性而不会发生报错

平时在写js的时候遇到多层属性嵌套,一般大家敢直接用点使用吗?
- if(obj.a && obj.a.b && obj.a.b.c && obj.a.b.c.d){
- // do something
- }
- function checkNested(obj /*, level1, level2, ... levelN*/) {
- var args = Array.prototype.slice.call(arguments),
- obj = args.shift();
- for (var i = 0; i < args.length; i++) {
- if (!obj || !obj.hasOwnProperty(args[i])) {
- return false;
- }
- obj = obj[args[i]];
- }
- return true;
- }
- var test = {level1:{level2:{level3:'level3'}} };
- checkNested(test, 'level1', 'level2', 'level3'); // true
- checkNested(test, 'level1', 'level2', 'foo'); // false
方法4:
- var myURL;
- if (Bro(app).doYouEven('config.environment.buildURL')) {
- myURL = app.config.environment.buildURL('dev');
- }
方法5:
- var object = { 'a': [{ 'b': { 'c': 3 } }] };
- _.get(object, 'a[0].b.c');
- // => 3
- _.get(object, ['a', '0', 'b', 'c']);
- // => 3
- _.get(object, 'a.b.c', 'default');
- // => 'default'
Object.getOwnPropertyNames()

- // 类数组对象
- const obj = { 0: "a", 1: "b", 2: "c" };
- console.log(Object.getOwnPropertyNames(obj).sort());
- // ["0", "1", "2"]
- Object.getOwnPropertyNames(obj).forEach((val, idx, array) => {
- console.log(`${val} -> ${obj[val]}`);
- });
js比较俩个对象是否相等

一、使用Object.getOwnPropertyNames()
该方法和Object.keys()功能一样,不同的地方在于Object.getOwnPropertyNames返回对象本身全部的属性,而Object.keys返回对象自身的(不含继承的)所有可枚举属性(不含Symbol属性)(即返回enumerable为false的属性)
共同点是俩者都不会返回自身原型链上的属性。
- var obj = {"name":"liuxinxiu","age":18,"info":"1234"}
- var obj2 = obj;
- var obj3 = {"name":"liuxinxiu","age":18,"info":"123"}
- function checkInfo(obj1, obj2){
- //判断是否指向同一内存
- if (obj1 === obj2) return true;
- let bankInfo = Object.getOwnPropertyNames(obj1),
- oldBankInfo = Object.getOwnPropertyNames(obj2)
- //判断长度不相同直接返回不同
- if(bankInfo.length !== oldBankInfo.length) return false
- for(let i=0,max=bankInfo.length; i<max; i++){
- let prop_name = bankInfo[i]
- if(obj1[prop_name] !== obj2[prop_name]){
- return false
- }
- }
- return true
- }
- console.log(checkInfo(obj,obj3))
二、使用Object.keys()或者Object.entries().toString()
Object.keys()是将对象中键先取出来组成数组,然后先比较键。而后通过键在比较值
Object.entries()是将键和值分别组成俩个数组。然后使用toString将键值数组转化为字符串去比较
- checkInfo() {
- // object.keys
- let bankInfo = Object.keys(this.params.bankInfo),
- oldBankInfo = Object.keys(this.params.oldBankInfo)
- if (oldBankInfo.length !== bankInfo.length) return false
- for (let i = 0; i <= bankInfo.length - 1; i++) {
- let key = bankInfo[i];
- if (!oldBankInfo.includes(key)){
- return false
- }
- if (this.params.oldBankInfo[key] !== this.params.bankInfo[key]){
- return false
- }
- }
- // object.entries
- console.log(Object.entries(this.params.bankInfo).toString() === Object.entries(this.params.oldBankInfo).toString()) //true
- console.log(Object.entries(this.params.bankInfo).toString()) //accountType,2,nationality,CHN,bankName,,bankCode,
- console.log(Object.entries(this.params.oldBankInfo).toString()) //accountType,2,nationality,CHN,bankName,,bankCode,
- }
三、使用JSON.stringify()或。适用于俩个对象属性顺序相同
- let bankInfo = {
- accountType : 2,
- nationality:'CHN', //国籍
- bankName : '', //银行名称
- bankCode : '', //银行code
- }
- let oldBankInfo = {
- accountType : 2,
- nationality:'CHN', //国籍
- bankName : '', //银行名称
- bankCode : '', //银行code
- }
- let flag2 = JSON.stringify(bankInfo) == JSON.stringify(oldBankInfo)
- console.log(flag2)
快速对字符转义,避免跨站攻击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 |
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;
- }
- }
- };
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 来携带参数
vue中http请求

前后端采用异步接口进行数据交互,传统情况下,我们采用jquery中的$.ajax()方法来进行异步请求。而在vue中我们并没有引入jquery而是采用了vue的插件vue-resource,它同样对异步请求进行了封装,方便我们同服务端进行数据交互。
1、引用及使用
- cnpm install vue-resource --save-dev
在项目根目录下/src/main.js中:
- import VueResource from 'vue-resource'
- Vue.use(VueResource)
此时在vue文件中就可以使用this.$http()进行网络请求。
2、通常在项目中是需要将http请求进行封装的。
为了封装成全局因此使用vuex。
参照 vue的一些总结 这个文章进行配置vuex
配置成功后,将main.js中的VueResource内容去掉,写在vuex中的store.js中
store.js内容如下
- import Vue from 'vue'
- import Vuex from 'vuex'
- import VueResource from 'vue-resource'
- Vue.use(Vuex)
- Vue.use(VueResource)
- export default new Vuex.Store({
- state: {
- url: 'www.baidu.com'
- },
- mutations: {
- setUrl (state, res) {
- // 该方法用来改变全局变量的值
- state.url = res
- }
- }
- })
3、在store.js中封装http请求的方法
- import Vue from 'vue'
- import Vuex from 'vuex'
- import VueResource from 'vue-resource'
- Vue.use(Vuex)
- Vue.use(VueResource)
- export default new Vuex.Store({
- state: {
- // url: 'www.baidu.com'
- },
- mutations: {
- // setUrl (state, res) {
- // // 该方法用来改变全局变量的值
- // state.url = res
- // },
- get(state, data) {
- Vue.http({
- method: 'GET',
- url: data.url,
- emulateJSON: true
- })
- .then(function (success) {
- // console.log("成功",success)
- data.success(success.body);
- }, function (error) {
- // console.log("错误",error)
- data.error(error.body);
- })
- /*
- Vue.http.get("http://test.dcsf.hebeiwanteng.com/api/common/wxParking/getNowTime")
- .then((success)=>{
- console.log("成功",success)
- })
- .catch((error)=>{
- console.log("失败",error)
- })
- */
- },
- post(state, data) {
- Vue.http({
- method: 'POST',
- url: data.url,
- params: data.data,
- emulateJSON: true
- }).then(function (success) {
- data.success(success.body);
- }, function (error) {
- data.error(error.body);
- })
- },
- delete(state, data) {
- Vue.http({
- method: 'DELETE',
- url: data.url,
- params: data.data,
- emulateJSON: true
- }).then(function (success) {
- data.success(success.body);
- }, function (error) {
- data.error(error.body);
- })
- },
- put(state, data) {
- Vue.http({
- method: 'PUT',
- url: data.url,
- params: data.data,
- emulateJSON: true
- }).then(function (success) {
- data.success(success.body);
- }, function (error) {
- data.error(error.body);
- })
- },
- }
- })
此时封装好了http请求。
在vue的文件中调用:
- <script>
- import { mapState, mapMutations } from 'vuex'
- export default {
- name: 'HelloWorld',
- data () {
- return {
- }
- },
- methods: {
- ...mapMutations(['get','post','delete','put']), //引入方法
- },
- created() {
- let _this = this;
- _this.get({
- url:"此处写请求地址",
- success(success) {
- console.log("成功",success)
- },
- error(error) {
- console.log("错误",error)
- }
- });
- }
- }
- </script>
4、注意:在store.js中使用Vue.http和在vue文件中使用this.$http是一样的。
5、该方法只验证了get请求,其它请求没有做验证。