哎,我真的是太难了,今天就被这个解构赋值(也可以叫做析构,貌似析构是在c++中的,所以我这里叫做解构赋值吧)弄的我很烦,本来以为很容易的,结果还是弄了好久。。。就总结一下解构吧!
1.解构的基本使用
什么叫做解构呢?其实就是类似正则表达式的这么一个东西,就是用一个有规则的表达式去匹配一个对象,这个表达式中刚好有一些属性,只要是匹配到了的东西都会自动赋值给这些属性,然后这个属性我们就可以随便使用了,所以通用的写法应该是下面这个样子的(这里是对象类型的解构,对于数组类型的解构比较容易,不多说,自己查一下资料就ok了):
//方式一,左边的表达式和右边的属性一 一对应,左边的顺序可以随意 let [属性2,属性1,属性3]={属性1:x,属性2:xx,属性3:xxx} //方式二,我们想换一下属性名,那么左边的表达式就需要用冒号将匹配到的值再赋值给冒号后面的变量,最后再返回给我们使用 let [属性2:attr2,属性1:attr1,属性3:attr3]={属性1:x,属性2:xx,属性3:xxx}
举个例子:
let {newName:nm,oldName:om}={oldName: '小王', newName: '老王'} console.log(nm);//老王 console.log(om);//小王
很舒服的是左边还可以设置默认值,匹配得到就用匹配到的值,没有匹配到就使用默认的值:
let {newName:nm='小李',oldName:om}={oldName: '小王'} console.log(nm);//小李 console.log(om);//小王
但是什么叫做没有匹配到呢?比如下面这个例子,右边根本就没有newName这个属性,这叫做没有匹配到,如果右边的newName为undefined也表示没有匹配到;但是:如果newName的值是null,这是匹配到了!!
let {newName:nm='小李',oldName:om,midName:mn='中间人'}={oldName: '小王', newName: null,midName:undefined} console.log(nm);//null,匹配到了右边的null,于是就用匹配到的值null console.log(om);//小王 console.log(mn);//中间人,右边为undefined,没有匹配到,使用默认值:‘中间人’
下面我们再来一个比较复杂的,随便找的一个例子,我们可以看到:左边第一个冒号前面的root匹配到对象立马就赋值给了后面的{ leaf: { left } },然后这个对象的leaf属性匹配到的东西赋值给{leaf},最后也就是相当于{leaf} = {leaf:5,right:5},就是最简单的解构了。
let tree = { root: { leaf: { left: 5, right: 5 } } } let { root: { leaf: { left } } } = tree;
// console.log(root); //这一行注释放开的话报错,提示root is not defined // console.log(leaf);//这一行注释放开的话报错,提示leaf is not defined console.log(left);//5 这是可以取到值的,匹配成功
2.复杂一点的解构
上面我说的是用一个表达式去匹配一个对象,那么问题来了,这个对象中可以有些什么形式呢?在1中我们的对象都是那种简单的对象{xx:'xx',xx2:'xxx'},那么这个对象可不可以是一个函数返回的对象呢?
举个例子,我们发现这样也是可以的;
function getPerson(na,num) { return { name: 'jack'+na, age: 19+num } } let { name, age } = getPerson('123',1); console.log(name);//jack123 console.log(age);//20
我又在想,既然类似let { name, age } = getPerson('123',1) 这种方式调用函数可以,那么继续变形一下,将getPerson(xxx)中的形参做一个变形,注意,我要变形了!w(°o°)w
function getPerson({na,num}) { return { name: 'jack' + na, age: 19 + num } } //注意,这里我们调用函数传递的是一个对象,上面函数形参接收的也要是一个对象 let { name, age } = getPerson({na:'123',num:1}); console.log(name);//jack123 console.log(age);//20
发现还是可以,于是我又继续变形:
function getPerson(obj){ return obj.commit("123",1); } //传递的对象更加复杂了 let obj = { commit:(na, num)=>{ return { name: 'jack' + na, age: 19 + num } } } //调用函数的参数还是一个对象,只不过更加复杂了,对象里面有一个commit属性,对应着一个函数 let { name, age } = getPerson(obj); console.log(name);//jack123 console.log(age);//20
居然还可以,然后我又默默地做了一次变形:
//注意这里形参,是一个{commit}对象 function getPerson({commit}){ return commit("123",1); } //这里是实参,里面有一个commit属性,和上面的形参对应 let obj = { commit:(na, num)=>{ return { name: 'jack' + na, age: 19 + num } } } //在调用的函数的时候,传入实参obj,形参那里的{commit}就可以拿到对应的commit函数了 //这就是es6的解构,或者叫做析构 let { name, age } = getPerson(obj); console.log(name);//jack123 console.log(age);//20
是不是有种日了狗一样的感觉,明明一个简单的东西为什么要弄的这么复杂呢?还有那个你为什么要在实参那里面还定义一个commit函数呢?简直坑爹!!
然而用过vuex的人应该对这个commit很熟悉才对,类似下面代码所示,mutations就不贴出来了,怎么样,现在是不是觉得那个({commit},num)这种东西就亲切多了;
// 定义 actions ,要执行的动作,如流程的判断、异步请求 const actions ={ // {commit,state}外面还能自定义参数num,这个参数我们随便定义 increment({commit},num){ //提交一个名为 increment 的变化,名字可自定义,可以认为是类型名,与下方 mutations 中的 increment 对应 //简单的做个判断,如果自定义参会素是奇数,啥也不干 if(num%2 == 1) return; //是偶数的话,commit 提交变化,修改数据的唯一方式就是显式的提交 mutations commit('increment') } }
顺便说一下,这里有个自定义参数的话,我们要传递参数的话,可以这样:
methods:{
//用这种三个点的写法也是es6中的,好像是叫做展开运算符,可以了解一下,用这种方式的话就可以使得mapActions这种东西和其他的方法例如incr函数,都可以放在methods里面 ...mapActions([ //该 increment 来自 store.js 中导出的 actions 和 mutations 中的 increment 'increment' ]),
//incr这是自定义的一个点击事件函数 incr(){ //这里传递自定义参数1,随便定义 this.$store.dispatch('increment',1) } }
3.小小的总结
还是那句话,我真的是太难了!妈耶,每次想学一点vue的时候,看到一些没见过的用法的时候,我就很头痛,其实如果真的要用的话,vuex很容易用,其实就是定义那三个东西,写法基本都是固定死的,然后在我们自己的组件中dispatcher调用就ok了,不过我个人习惯还是喜欢将一个不是很懂,或者是云里雾里的知识点给弄清楚来龙去脉;
说实话,一直没怎么看es6的解构赋值,或者说是只是看了数组的解构,哈哈哈,就类似这种let [a, b, c] = [1,2,3],哈哈,最基本的用法,今天才无聊好好的看了一下,肯定还有很多用法每看到,下次有时间再说吧!
还有在看这个解构赋值的时候,冒出一个想法,类似这种写法 let sum=(a,b)=>{return a+b};这是不是也可以看作是一种特殊的解构赋值呢?只不过由于返回的只有一个,所以就直接返回给sum,嘿嘿(^.^),到此结束