PubSub ——“发布/订阅”模式
Vue中provide和inject
- 作用:用于父组件向子孙组件传递数据
- 原理:
向上找寻 - 何时使用 provide是非响应的,那么就决定它注定不能用于组件通信,和vuex根本没有可比性。至于为什么引入inject,可以参考mixin,简单来说就是业务逻辑的抽象,hook的抽象实现固然很好,但是没有必要把难以复用的逻辑抽象成函数,如果只是简单提供给子组件使用,那就使用provide,inject,否则使用hook,vuex不考虑,没人用vuex抽象业务逻辑。
EventBus(this.emit,this.on)
- 作用:用于兄弟组件传递数据
- 原理:
发布/订阅方法,通常称为Pub/Sub
EventBus.$emit("incremented", { num:this.num, deg:this.deg }); //发布
EventBus.$on("decreased", ({num,deg}) => {} //接受
EventBus.$off('decreased', {}) //移除
PubSub ——“发布/订阅”模式
- 作用
- 支持简单的广播通信,当对象状态发生改变时,会自动通知已经订阅过的对象。
- 可以应用在异步编程中 替代回调函数 可以订阅ajax之后的事件 只需要订阅自己需要的部分 (那么ajax掉用发布之后订阅的就可以拿到消息了)(不需要关心对象在异步运行时候的状态)
- 对象之间的松耦合 两个对象之间都互相不了解彼此 但是 不影响通信 当有新的订阅者出现的时候 发布的代码无需要改变 同样发布的代码改变 只要之前约定的事件的名称没有改变 也不影响订阅
- 缺点
- 创建订阅者需要消耗一定的时间和内存。
- 虽然可以弱化对象之间的联系,如果过度使用的话,反而使代码不好理解及代码不好维护等等
var Event = (function () {
var list = {},
listen,
trigger,
remove;
listen = function (key, fn) {
if (!list[key]) {
list[key] = [];
}
list[key].push(fn);
};
trigger = function () {
var key = Array.prototype.shift.call(arguments),
fns = list[key];
if (!fns || fns.length === 0) {
return false;
}
for (var i = 0, fn; fn = fns[i++];) {
fn.apply(this, arguments);
}
};
remove = function (key, fn) {
var fns = list[key];
if (!fns) {
return false;
}
if (!fn) {
fns && (fns.length = 0);
} else {
for (var i = fns.length - 1; i >= 0; i--) {
var _fn = fns[i];
if (_fn === fn) {
fns.splice(i, 1);
}
}
}
};
return {
listen: listen,
trigger: trigger,
remove: remove
}
})();
Event.listen("color", function (size) {
console.log(size)
})
Event.trigger("color", 42);
单例模式
class类
-
是什么 es6提供的一种新的生成实例对象的方法class可以看作只是一个语法糖 es5 构造函数的另外一种写法
-
作用 更接近传统语言的写法新的class写法只是让对象原型的写法更加清晰、更像面向对象编程的语法
-
es5以前生成对象
function Person(name, sex) {
this.name = name;
this.sex = sex
}
Person.prototype.say = function () {
console.log('学前端很幸福')
};
let person1 = new Person('张三','男')
console.log(person1.name);
person1.say()
- es6实现
class Person {
constructor(name,sex){
this.name = name
this.sex = sex
}
say(){
console.log('学前端很幸福');
}
}
let person1 = new Person('张三','男')
console.log(person1.name); // 张三
person1.say() // 我会说话
-
constructor 方法 constructor方法是类的默认方法,通过new命令生成对象实例时,自动调用该方法。一个类必须有constructor方法,如果没有显式定义,一个空的constructor方法会被默认添加。
-
静态属性 静态属性指的是 Class 本身的属性,即Class.propName,而不是定义在实例对象(this)上的属性。
class Person {
static age = 18
name = '张三'
}
let person = new Person();
console.log(person.age); // undefined
- 静态方法 类相当于实例的原型,所有在类中定义的方法,都会被实例继承。如果在一个方法前,加上static关键字,就表示该方法不会被实例继承,而是直接通过类来调用,这就称为“静态方法”。
class Foo {
static classMethod() {
return 'hello';
}}
Foo.classMethod() // 'hello'
foo.classMethod()
- ES6中的单例模式
- ES6创建对象 ES6中创建对象时引入了class和constructor用来创建对象。下面我们来使用ES6的语法实例化苹果公司
class LingYuan {
constructor(name, creator, products) {
this.name = name;
this.creator = creator;
this.products = products;
}
}
let lyCompany = new LingYuan('零远教育', '裴广斌', ['es6', 'vue', 'react', 'node']);
let lyCopyCompany = new LingYuan('苹果公司', 'walker', ['es7', 'vue', 'react', 'node']);
-
ES6中创建单例模式 零远公司明显有且只有一个, 就是裴老师创建的那个, 哪能容别人进行复制?所以LingYuan应该是一个单例, 现在我们使用ES6的语法将constructor改写为单例模式的构造器。
-
ES6的静态方法优化代码
ES6中提供了为class提供了static关键字定义静态方法, 我们可以将constructor中判断是否实例化的逻辑放入一个静态方法getInstance中,调用该静态方法获取实例, constructor中只包需含实例化所需的代码,这样能增强代码的可读性、结构更加优化。
class SingletonLy {
constructor(name, creator, products) {
this.name = name;
this.creator = creator;
this.products = products;
}
//静态方法
static getInstance(name, creator, products) {
if (!this.instance) {
this.instance = new SingletonLy(name, creator, products);
}
return this.instance;
}
}
let lyCompany = SingletonLy.getInstance('零远思维', '裴广斌', ['vue', 'react', 'node', 'js']);
let lyCopyCompany = SingletonLy.getInstance('零远copy', 'walker', ['vue', 'react', 'node', 'js'])
console.log(lyCompany === lyCopyCompany);