当我们使用MobX的时候,首先要声明一个store, 用来保存状态,它的最基本的语法 如下:

class Todo {@observable title = "";@observable finished = false;
}

  其中 @observable 是装饰器写法, title= ''; 是实例属性的新的写法,这两个语法是es7 中的提案,但都没有被采纳, 之所以被使用,是因为有babel 时进行转译。

  首先看一下类的实例属性的新写法, 这是ES7 中关于静态属性的一个提案, 在这个提案对实例属性和静态属性规定了新的写法。

  1,对于实例属性来说, 如果在使用的时候,就要对它进行初始化,那么可以直接在类的定义中用赋值方式进行初始化。

class Car {color = 'red';
}

  这样,我们就声明了一个实例属性color,并且它的初始值为 'red';  如果用以前的写法,我们要在类中定义constructor构造函数,然后在构造函数中写实例属性,

class Car {constructor() {this.color = 'red';}
}

  可以发现,新的ES7 提案,大大简化了写法。

  2, 不光是实例属性,实例方法也可以用这种赋值的方法进行初始化, 如果学习过react, 你可以已经见过这种写法了。

class Car {color = 'blue';// 直接用赋值的方法,对实例方法进行初始化getColor = () => {return this.color;}
}

  3, 静态属性就是在实例属性的前面加上static关键字, 它表示这个属性属于整个类,用类名加属性名进行读取。

class Car {static country = 'china';
}

  4,静态方法,就是在方法前面加上static, 也示表示它属于这个类。

class Car {static country = 'china';static getCountry = () => {return Car.country;}
}

  现在就用babel进行转译,使它能够在生产环境中使用,为了通用性,我们使用webpack 进行配置。现在是webpack4, 我们也使用一下。新建mobx文件夹,npm init -y 生成package.json文件,安装依赖, 这里要注意,webpack4 把命令行抽离成了一个单独的包webpack-cli,所以安装webpack时,要安装webpack-cli, 否则不能使用webpack打包命令。

npm install webpack webpack-cli webpack-cli --save-dev.  对类进行转译,用到一个babel核心插件 babel-plugin-transform-class-properties. npm install babel-core babel-loader babel-plugin-transform-class-properties --save-dev. 再来写webpack.config.js, 这里比原来要简单,因为webpack4 提出一个零配置概念。默认入口文件 src/index.js, 输出文件 dist/main.js 文件,

同时提供了一个mode 配置选项,用来表示生产环境还是测试环境,那么webpack.config.js中只写module就可以了。

const path = require('path');module.exports = {module: {rules:[{test: /\.js$/,include: path.join(__dirname, 'src'),use: {loader: 'babel-loader',options: {plugins: ['transform-class-properties']}}}]}
}

  现在建立入口文件, 新建src目录,再在里面新建index.js文件, 把上面的代码都写到里面。

class Car {color = 'red';getColor = () => {return this.color;}static country = 'china';static getCountry = () => {return Car.country;}
}console.log(new Car().getColor())
console.log(Car.getCountry())

  现在就执行打包命令了, 在package.json文件中的scripts字段中,写上 "build": "webpack  --mode production",  --mode production , 就是在webpack4要求指定的mode 参数。npm run build 执行打包命令,完成后,可以看到多了个dist目录,里面有一个main.js文件,因为它是一个js 文件,我们直接用node 执行一下就好了,node main.js 可以看到l输出了 red, china,打包没有问题,说明也编译成功了。

  现在再来看装饰器,它的主要作用是来装饰一个类或类中的属性或方法,也就是说,它只能作用在class上,目的呢,则是对这个类,或属性方法,进行功能增强。怎么进行增强呢?  这就要说到装饰器的本质,它本身是一个函数,当js在进行编译的时候,会为这个函数注入默认的参数,如果作用到类上,则这个函数自动会获取到一个target的参数,表示这个类本身。

如果作用属性或方法上,则会为函数注入3个参数,target, key, descriptor, target 表示这个装饰的函数所属的对象,key 表示装饰的函数名称,descriptor, 装饰的函数的描述符,这三个参数和Obeject.defineProperty 的三个属性一致,为哪个对象的,哪个属性,设置怎么样的descriptor. 当函数获取到参数以后,就可以在函数内作任意的操作,所以可以进行增强。装饰器的语法是怎么样的,它是怎么作用到类上。语法其实很简单,就是在函数名的前面加@, 然后放到类或方法的上面,和java的注解一样。现在我们来体验一个装饰器,不过还是要先配置一个webpack, 装饰器的编译依赖一个核心插件,babel-plugin-transform-decorators-legacy. npm install 安装完成后,在webapck.config.js中的plugins进行配置。

  好了,基础搭建已经完成,我们就来学习装饰器了,首先装饰器要作用在类上,我们要先定义在一个类,名字就叫Numberic 好了。其次,装饰器是一个函数,它有默认参数, 那我们先声明两个函数, 一个作用到类上,一个作用到方法上,最后,装饰器作用到类中,用通过@函数名实现了。那基本框架如下:

@time
class Numberic {@readonly
add (num) {
let sum = 0
for (let index = 0; index < num; index++) {
sum = sum + index;
}
return sum;
}

}// 由于time函数,是装饰类的,所以它自动会获取到一个target参数,我们可以打印一下target,就是类本身
function time(target) {console.log(target);
}
// 由于readonly是作用到类的方法上的,所以它获取到3个参数。
function readonly(target, key, descriptor) {console.log(target);console.log(key);console.log(descriptor);
}

  这两个装饰器time, readonly 要对它装饰的类或函数起到什么增强作用呢? time, 我们来计算类的原型上所有方法的执行时间.  readonly, 则表示这个方法不可以被复写。

  先来看time是怎么写的?

function time(target) {const desc = Object.getOwnPropertyNames(target.prototype);for (let key of desc) {if (key === 'constructor') {continue;}const func = (target.prototype)[key];if (typeof func === 'function') {Object.defineProperty(target.prototype, key, {value: function(...args) {console.time('time');let ret = func.apply(this, args);console.timeEnd('time');return ret;}})}}
}

  在类中定义的方法,实际上都是定义在类的原型上,所以要对定义在类中所有方法都进行增强,就要在原型上先获得这些方法, 由于装饰的函数,自动会获得target, 所以target.prototype就可以获得原型。由于原型是一个对象,所以获取它上面的方法,就要获取到对象的属性,然后进行遍历。所以time函数的第一个句,就是用getOwnPropertyNames获取整个原型对象的属性名,这里打印一下,可以知道结果,是一个数组["constructor", "add"], 注意这里不要使用keys 方法,因为Object.keys()获取的是一个对象上的可枚举属性,而在原型上定义的方法,都是不可以枚举的,如果使用Object.keys(), 这里将会得到空数组。Object.getOwnProperyNames 可以获取到对象的非枚举属性,所以在这里使用没有问题。

  然后使用了for of 对["constructor", "add"]数组进行编历,首先要去除构造函数,因为构造函数用来创建对象的,所以使用了 if (key === 'constructor') ,那么剩下的key值,就是我们想要的了,比如在这里key 为add. 我们声明了一个func变量来获取到属性值,这里也可以打印一下, 它是一个函数。

   现在获取到了原型对象上的所有属性或对应的属性值,那现在就要对它进行增强,这时你会看到, 我们是用Object.defineProperty 重新给属性定义了一个新的函数,key 就是指代我们的add, value 就是给add 重新定义的方法,在value中,我们是用apply 方法,调用了原方法func.apply ,所以原有的方法,不会消失,正常使用。但是我们在方法的调用前后,分别调用了console.time 和console.timeend 来计算时间,所以我们对原来的函数进行了增强。

  这时我们声明一个Numberic 对象,来体验一下time 装饰器。

let obj = new Numberic();
console.log(obj.add(1000));

  这时控制台上输出结果,同时输出了计算时间,看来我们的装饰器time 起作用了。

  所谓的装饰器,就是获取到对象原来定义属性,或属性值,然后用Object.defineProperty 方法重新定义新的属性或属性值,在新的属性值里面,调用原有方法的同时,增加新的功能,这样,原的方法调用了,同时增加了新的功能,所以增强了。

  现在我们再来看一个readonly装饰器,它不可复写,就设置它的属性描述符writable: false.就好了, 由于它是装饰单个方法,所以它自动会获取到descriptor 属性,它就是属性描述符。

function readonly(target, key, descriptor) {console.log(descriptor);}

  这时可以看到add完整的属性描述符,writable 为true,  表示可以复写,那直接修改为false 就可以了。

function readonly(target, key, descriptor) {descriptor.writable = false;
}

  readonly 装饰器就写完了。我们来测试一下, 组obj增加一个add 方法,

obj.add = function() {console.log('add');
}

  如果如被复写,它就是调用我们新写的方法,输出add.

console.log(obj.add(1000));

  可以看到,控制台仍然输出的是1000的和,表示add函数并没有被复写。

  

转载于:https://www.cnblogs.com/SamWeb/p/9219144.html

MobX基础 ----- 类的静态属性和装饰器相关推荐

  1. 一个ABAP调试器里查看类的静态属性的小技巧

    我们知道,像如图一这种类的静态属性,因为不属于类的实例所有,因此调试到这个类的方法内部时,只能通过图二演示的两种方式在调试器显示该属性的值.而一旦调试到该类方法的外部,通常就只能通过"类名= ...

  2. java spring注入 静态方法_java相关:spring为类的静态属性实现注入实例方法

    java相关:spring为类的静态属性实现注入实例方法 发布于 2020-3-31| 复制链接 在本篇文章里小妖给大家整理的是关于spring为类的静态属性实现注入实例方法,有需要的朋友们可以参考下 ...

  3. NodeJS 发送 POST 请求 curl -d JS 类的静态属性使用

    NodeJS 发送 POST 请求 curl -d & JS 类的静态属性使用 'use strict';const Service = require('../lib/ServiceBase ...

  4. python类的魔法方法和装饰器

    装饰器 闭包装饰器 装饰器的本质就是一个闭包, 闭包三要素:1 函数嵌套, 2 外部函数返回内部函数的引用, 内部函数使用外部函数的变量 1 使用装饰器简单实现一个登录校验功能 In [1]: use ...

  5. python 类的使用(5)之类装饰器(类的装饰器和类作为装饰器)

    在阅读博客中,发现了类装饰器的存在,由于之前就在写类相关的专栏,这次就赶紧补上之前的内容啦.类装饰器这个词是有歧义的,因为类本身可以作为装饰器,一个类也可以被函数装饰器所装饰.今天就简单介绍一下这两种 ...

  6. python类的静态属性和静态方法_详解Python中的静态方法与类成员方法

    前言 因为Python的水平目前一直是处于能用阶段,平时写的脚本使用的Python的写法也比较的简单,没有写过稍微大一点的项目.对Python中的类,类之间的组织关系,整个项目中类之间如何耦合还缺乏认 ...

  7. Python类的静态属性、类方法、静态方法

    1.静态属性.@property.作用就是把类的函数属性,封装成类似数据属性. class Student(object): school='szu'@propertydef printmassage ...

  8. fianl属性 java_java基础-类的高级属性(包、final、内部类)

    女神镇楼 类除了具有普通的特性之外,还有一些高级特性,比如包.内部类等.包在整个管理过程中起到非常积极的作用,使用包可以有效的管理繁杂的类文件,解决类重名的问题,当在类中配合包与权限修饰符使用时,可以 ...

  9. JS中Class类的静态属性和静态方法

    首先,关于类有两个概念: 1.类自身: 2.类的实例对象 总的来说:静态的是指向类自身,而不是指向实例对象,主要是归属不同,这是静态属性的核心. 静态方法使用:在方法前加上static关键字. 1.为 ...

最新文章

  1. c语言学生信息系统 完整版,C语言 学生信息管理系统(完整版).docx
  2. 二进制包 mysql_二进制包;mysql
  3. 【Cocos2d入门教程二】Cocos2d-x基础概念
  4. java可比较的和比较器的区别_Java中Compareable和Comparator两种比较器的区别
  5. ECShop显示某商品销售累计
  6. python 多分类情感_文本情感分类(一):传统模型
  7. C语言 结构体的初次运用
  8. 上位机获取单片机发来的数据并进行检验
  9. 有鱼上钩!卖鱼!卖鱼!
  10. linux 解压 7z 乱码,7z-linux下解决中文名乱码的终极办法
  11. DICOM医学图像处理:Orthanc Plugin SDK实现WADO服务
  12. 【matlab图像处理】图像直方图操作和matlab画图
  13. ic 卡获取帐号apdu指令_APDU指令格式解析
  14. baidumap vue 判断范围_vue-baidu-map 行政区域划分
  15. ora-00959(表空间不存在) 的另一种可能性
  16. 卢菲菲记忆课程(一、了解记忆认识大脑)
  17. matlab蒙特卡罗变量变换的分布,使用 copula 仿真相关随机变量
  18. python兔子_python 实现兔子生兔子示例
  19. 虾皮shopee跨境电商靠谱吗
  20. Android版优酷网闪亮登场

热门文章

  1. 在VS2012中实现ExtJS的智能提示
  2. SCI、EI、ISTP、ISR、SSCI、AHCI简介
  3. 查看mysql是否启用安全审计_如何查看oracle是否开启了审计功能?
  4. 常用sql操作语句实战演示
  5. windows下使用cmake+mingw配置makefile(1)
  6. Java7并发编程指南——第一章:线程管理
  7. 海岸鸿蒙慕建洲,用于校准液体自动颗粒计数器的标准物质及其制备方法.pdf
  8. 阵列卡直通模式和raid模式_DNF:希洛克Raid攻坚流程攻略
  9. 密码学原理与实践_到底什么是防火墙入侵检测密码学身份认证?如何高效建立网络安全知识体系?...
  10. 一个数等于两个不同素数的乘机_相亲数:数字所表达的友情和浪漫