summaryrefslogtreecommitdiff
path: root/doc/development/fe_guide/design_patterns.md
diff options
context:
space:
mode:
Diffstat (limited to 'doc/development/fe_guide/design_patterns.md')
-rw-r--r--doc/development/fe_guide/design_patterns.md78
1 files changed, 78 insertions, 0 deletions
diff --git a/doc/development/fe_guide/design_patterns.md b/doc/development/fe_guide/design_patterns.md
new file mode 100644
index 00000000000..e05887a19af
--- /dev/null
+++ b/doc/development/fe_guide/design_patterns.md
@@ -0,0 +1,78 @@
+# Design Patterns
+
+## Singletons
+
+When exactly one object is needed for a given task, prefer to define it as a
+`class` rather than as an object literal. Prefer also to explicitly restrict
+instantiation, unless flexibility is important (e.g. for testing).
+
+```javascript
+// bad
+
+const MyThing = {
+ prop1: 'hello',
+ method1: () => {}
+};
+
+export default MyThing;
+
+// good
+
+class MyThing {
+ constructor() {
+ this.prop1 = 'hello';
+ }
+ method1() {}
+}
+
+export default new MyThing();
+
+// best
+
+export default class MyThing {
+ constructor() {
+ if (!this.prototype.singleton) {
+ this.init();
+ this.prototype.singleton = this;
+ }
+ return this.prototype.singleton;
+ }
+
+ init() {
+ this.prop1 = 'hello';
+ }
+
+ method1() {}
+}
+
+```
+
+## Manipulating the DOM in a JS Class
+
+When writing a class that needs to manipulate the DOM guarantee a container option is provided.
+This is useful when we need that class to be instantiated more than once in the same page.
+
+Bad:
+```javascript
+class Foo {
+ constructor() {
+ document.querySelector('.bar');
+ }
+}
+new Foo();
+```
+
+Good:
+```javascript
+class Foo {
+ constructor(opts) {
+ document.querySelector(`${opts.container} .bar`);
+ }
+}
+
+new Foo({ container: '.my-element' });
+```
+You can find an example of the above in this [class][container-class-example];
+
+
+[container-class-example]: https://gitlab.com/gitlab-org/gitlab-ce/blob/master/app/assets/javascripts/mini_pipeline_graph_dropdown.js