useRef与JS设计模式学习(一)
useRef
1
2const refContainer = useRef(initialValue);
使用useRef Hook,你可以轻松的获取到dom的ref。
useRef 返回一个可变的 ref 对象,其 .current 属性被初始化为传入的参数(initialValue)。返回的 ref 对象在组件的整个生命周期内持续存在,在组件的整个生命周期保持不变。
当 ref 对象内容发生变化时,useRef 并不会通知你。变更 .current 属性不会引发组件重新渲染。
1
2
3
4
5
6
7
8
9
10
11
12
13
14function TextInputWithFocusButton() { const inputEl = useRef(null); const onButtonClick = () => { // `current` 指向已挂载到 DOM 上的文本输入元素 inputEl.current.focus(); }; return ( <> <input ref={inputEl} type="text" /> <button onClick={onButtonClick}>Focus the input</button> </> ); }
注意useRef()并不仅仅可以用来当作获取ref使用,使用useRef产生的ref的current属性是可变的,这意味着你可以用它来保存一个任意值。。
模拟componentDidUpdate
componentDidUpdate就相当于除去第一次调用的useEffect,我们可以借助useRef生成一个标识,来记录是否为第一次执行:
1
2
3
4
5
6
7
8
9
10
11function useDidUpdate(callback, prop) { const init = useRef(true); useEffect(() => { if (init.current) { init.current = false; } else { return callback(); } }, prop); }
什么是设计模式
一个模式就是一个可重用的方案,可应用于在软件设计中的常见问题。
模式的另一种解释就是一个我们如何解决问题的模板 - 那些可以在许多不同的情况里使用的模板。
设计模式的好处
- 模式是行之有效的解决方法:他们提供固定的解决方法来解决在软件开发中出现的问题,这些都是久经考验的反应了开发者的经验和见解的使用模式来定义的技术。
- 模式可以很容易地重用:一个模式通常反映了一个可以适应自己需要的开箱即用的解决方案。这个特性让它们很健壮。
- 模式善于表达:当我们看到一个提供某种解决方案的模式时,一般有一组结构和词汇可以非常优雅地帮助表达相当大的解决方案。
反模式
如果我们认为模式代表一个最佳的实践,那么反模式将代表我们已经学到一个教训。
Javascript的反模式例子如下:
- 在全局上面文中定义大量污染全局命令空间的变量
- 在调用setTimeout和setInterval时传递字符串(会用eval来执行)而不是函数。
- 修改Object的原型 (这是最糟糕的反模式)
- 使用内联Javascript
- 在本应使用document.createElement的地方使用document.write。document.write被错误的用了相当多的年头,它有相当多的缺点,包括如果在页面加载后执行它可能会覆盖我们的页面。再有它不能工作在XHTML下,这也是另外一个我们使用像document.createElement这种对DOM友好方法的原因。
设计原则
单一职责原则(SRP)
一个对象或方法只做一件事情。如果一个方法承担了过多的职责,那么在需求的变迁过程中,需要改写这个方法的可能性就越大。
应该把对象或方法划分成较小的粒度。
最少知识原则(LKP)
一个软件实体应当 尽可能少地与其他实体发生相互作用 。
应当尽量减少对象之间的交互。如果两个对象之间不必彼此直接通信,那么这两个对象就不要发生直接的 相互联系,可以转交给第三方进行处理。
开放-封闭原则(OCP)
软件实体(类、模块、函数)等应该是可以 扩展的,但是不可修改。
当需要改变一个程序的功能或者给这个程序增加新功能的时候,可以使用增加代码的方式,尽量避免改动程序的源代码,防止影响原系统的稳定。
创建对象的几种模式
工厂模式
在函数内创建一个对象,给对象赋予属性及方法再将对象返回。
1
2
3
4
5
6
7
8
9
10
11
12
13function createPerson() { var People = new Object(); People.name = 'CrazyLee'; People.age = '25'; People.sex = function(){ return 'boy'; }; return People; } var a = createPerson(); console.log(a.name);//CrazyLee console.log(a.sex());//boy
问题是没有解决对象识别的问题(即怎样知道一个对象的类型)。
构造函数模式
无需在函数内部重新创建对象,而是用this指代。
1
2
3
4
5
6
7
8
9
10
11function Person() { this.name = 'CrazyLee'; this.age = '25'; this.sex = function(){ return 'boy' }; } var a = new Person(); console.log(a.name);//CrazyLee console.log(a.sex());//boy
问题是每个方法都要在每个实例上重新创建一遍。
原型模式
函数中不对属性进行定义,利用prototype属性对属性进行定义,可以让所有对象实例共享它所包含的属性及方法。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16function Parent() { Parent.prototype.name = 'carzy'; Parent.prototype.age = '24'; Parent.prototype.sex = function() { var s="女"; console.log(s); } } var x =new Parent(); console.log(x.name); //crazy console.log(x.sex()); //女
问题是共享性,所有属性都是共享的,引用类型值的属性也是共享的。
混合模式
原型模式+构造函数模式。这种模式中,构造函数模式用于定义实例属性,而原型模式用于定义方法和共享属性。
1
2
3
4
5
6
7
8
9
10
11function Parent(){ this.name="CrazyLee"; this.age=24; }; Parent.prototype.sayname=function(){ return this.name; }; var x =new Parent(); console.log(x.sayname()); //CrazyLee
默认模式就是这个,使用最广的和认同度最高的模式。
动态原型模式
将所有信息封装在了构造函数中,而通过构造函数中初始化原型,这个可以通过判断该方法是否有效而选择是否需要初始化原型。
1
2
3
4
5
6
7
8
9
10
11
12
13function Parent(name,age){ this.name=name; this.age=age; if(typeof this.sayname != "function"){ Parent.prototype.sayname = function(){ return this.name; } } }; var x =new Parent('CrazyLee','14'); console.log(x.sayname()); //CrazyLee
可以说是完美的方法。不过使用时不能使用对象字面量重写原型,否则会切断现有实例和新原型的联系。
最后
以上就是斯文小蝴蝶最近收集整理的关于useRef与JS设计模式学习(一)useRef与JS设计模式学习(一)的全部内容,更多相关useRef与JS设计模式学习(一)useRef与JS设计模式学习(一)内容请搜索靠谱客的其他文章。
发表评论 取消回复