Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Modernizing the Ext JS Class System - SenchaCon Roadshow 2016

Sencha
June 05, 2017
170

Modernizing the Ext JS Class System - SenchaCon Roadshow 2016

Sencha

June 05, 2017
Tweet

Transcript

  1. Agenda •  New JavaScript Syntax - Sencha’s Approach •  JavaScript:

    Past, Present and Future •  Transpilers & Sourcemaps •  Ext JS 7 Class system content -  Modules -  Classes & Mixins -  Life-cycle -  Goals for language and tools •  The Road Ahead
  2. Future-proofing New JavaScript Syntax - Sencha’s Approach A Balance Between…

    Compatibility Ext.define works as before Existing code organization is supported Ext.require works as before callParent must be available Ext namespace is globally available ES2015 Class syntax can derive from any class Module-based structure import and export syntax is supported super calls must work (strict mode) Ext is scoped to its module
  3. What you know as JavaScript in browsers and Node.js is

    actually a superset of ECMAScript. Browsers and Node.js add more functionality through additional objects and methods, but the core of the language remains as defined in ECMAScript. ES2015/ES6: The Present!
  4. 7 ES2015/ES6! •  Module Syntax! •  The class keyword! • 

    Arrow Functions! •  Template Strings! •  Native Promises! •  Block Scoping! •  Enhanced Object Literals! •  Destructuring! •  Rest! •  Spread! ES2016/ES7! •  Array.prototype.includes! •  Exponentiation Operator! ES2017/ES8! •  Trailing Commas! •  Property Initializers! •  Async/Await! New JavaScript Syntax!
  5. ES2015/ES6: Arrow Functions! const times2 = x => x *

    2; // function(x) { return x * 2 }.bind(this) ! ! times2(2); // 4 ! !
  6. ES2015/ES6: Native Promises! function doThis() { ! return new Promise((resolve,

    reject) => { ! resolve(...) ! }); ! } ! ! doThis() ! .then(doThat) ! .catch(handleError) ! !
  7. ES2015/ES6: Block Scoping! { ! let x = 1; !

    x++; ! ! const foo = 'bar'; ! } ! ! ! !
  8. ES2015/ES6: Enhanced Object Literals! const foo = 'bar'; ! !

    const obj = { foo } // { foo: foo } ! !
  9. ES2015/ES6: Rest! const person = { ! firstName: 'Mark', !

    lastName: 'Brocato', ! age: 35, ! gender: 'Male' ! }; ! ! const { firstName, lastName, ...others } = person; ! ! // others = { age: 35, gender: ‘Male’ } ! !
  10. ['foo', 'bar'].includes('foo') // true ! ! ! 2**3 // 8

    ! ! ES2016/ES7: Array.prototype.includes and Exponentiation Operator!
  11. ES2017/ES8: Property Initializers! import React, { Component } from 'react';

    ! ! class MyComponent extends Component { ! ! state = { ! value: '' ! } ! ! render() { ! return <div>{value}</div> ! } ! ! } ! !
  12. ES2017/ES8: Property Initializers! import React, { Component } from 'react';

    ! ! class MyComponent extends Component { ! ! onClick = () => alert('Hello World!') ! ! render() { ! return <button onClick={this.onClick}>Say Hello</button> ! } ! ! } ! !
  13. ES2017/ES8: Async/Await! // before ! ! fetch(url) ! .then(data =>

    { ! updateView(data) ! }) ! .catch(e => { ! handleError(e); ! }); ! ! ! ! ! // after ! ! try { ! const data = await fetch(url); ! updateView(data); ! } catch (e) { ! handleError(e); ! }
  14. About Compatibility You can find an overview of compatibility, in

    one of these ECMAScript 2015 compatibility tables: http://kangax.github.io/compat-table/es6/ ES2015 Implementations: •  V8 (Chrome, Node.js, Opera) •  SpiderMonkey (Firefox) •  JavaScript Core (Webkit, Safari) •  Chakra (MS Edge) •  Mobile (iOS 9+, Android 4.4+)
  15. Transpilers •  Transpilers (like Babel) are JavaScript-to-JavaScript compilers •  Transpilers

    go beyond “polyfills” by providing missing language syntax! •  Transpilers are currently the only platforms that accept imports, exports and decorators •  Transpilers allow us to future-proof our code (unblocking the language adoption curve) -  No more “I have to develop code for the worst supported browsers” •  (though, not everything can be fixed by tools) .babelrc! {! "presets": ["latest"]! }! How I can use tomorrow’s JavaScript today!
  16. TypeScript! •  https://www.typescriptlang.org/! •  Written by Microsoft! •  Needs to

    be compiled! •  Superset of ES6/7/8! •  Visibility! •  Decorators! •  Compile-time type checking! •  Strong types => better code completion in IDEs, find usages! •  Easier to maintain and refactor! •  The preferred choice for Angular 2 apps, also works for React! •  Some libraries “play well”, some don’t!
  17. Source Maps •  Source Maps enable the debugger to display

    the original source code… -  …not the ugly transpiler output! •  Source Maps have been around since 2012 -  This is great because they are widely supported •  Source Maps are supported by: -  Chrome, Firefox, Edge, Safari -  IE11 (with Windows 8.1 Update) See: https://www.html5rocks.com/en/tutorials/developertools/sourcemaps/
  18. Ext  =  {};   Ext.global  =  window;   Ext.global.Ext  =

     Ext;     Ext.define('App.some.Thing',  {        extend:  'App.foo.Bar',        requires:  [  'Ext.grid.Panel'  ],     ExtJS: Namespaces •  Namespaces are nested objects •  Ext.define() defines class & adds to the namespace •  The Loader maps names to URL’s •  Files are loaded at global scope  Ext  =  {          global:  {                Ext:  Ext,                App:  {                      foo:  {                            Bar:  constructor                      },                      some:  {                            Thing:  constructor                      }                }          },          grid:  {                Panel:  constructor          }    }    Ext.Loader.setPath({          Ext:  '../ext/src',          App:  './app'    });    //  Ext.grid.Panel    //  =>  '../ext/src/grid/Panel.js'      //  App.foo.Bar    //  =>  './app/foo/Bar.js'  
  19. var  foo  =  'bar';    //  private,  not  global  

      export  var  abc  =  'abc';     export  default  class  Bar  {          //  ...   }     New: ES2015/ES6 Modules •  Modules are files •  Modules execute in a private scope (not global) •  Modules publish values using export •  Modules can have one, unnamed “default” export value •  Modules use import to acquire values exported by other modules •  Modules are imported by path or name ./path/file.js   import  {  abc  }  from  '../path/file';     import  Bar  from  '../path/file.js';     import  Ext  from  '@extjs/kernel';     import  {  define  }  from  '@extjs/kernel';     ./other/thing.js  
  20. import  {  button  }  from  '@extjs/modern';     import  {

     hbox  }  from  '@extjs/modern/layout';     import  {  Ext_Button  }  from  '@extjs/modern';     New: Importing Components •  Classes are exported in several ways: -  By xtype -  By alias family -  By class name •  These would be used where strings might be used today •  These exports can be generated by the new build tool
  21. Ext.define('App.some.Thing',  {        extend:  'App.foo.Bar',      

     requires:  [  'Ext.grid.Panel'  ],          alias:  'thing',        text:  'Hello',          constructor:  function  (config)  {              this.callParent([config]);        },          method:  function  (x)  {              return  this.callParent([x])  *  42;        },          statics:  {              create:  function  (cfg)  {                    cfg.type  =  'thing';                    return  this.callParent([cfg]);              }        }   });   ExtJS: Classes Ext.define() •  Inheritance •  Requires (directives) •  Properties •  Constructors •  Methods •  Static methods •  callParent
  22. import  {  define  }  from  '@extjs/kernel';   import  {  grid

     }  from  '@extjs/modern';   import  Bar  from  'app/foo';     @define('App.some.Thing',  {        alias:  'thing',        text:  'Hello'   })   class  Thing  extends  Bar  {        method  (x)  {              return  super.method(x)  *  42;        }          static  create  (cfg)  {              cfg.type  =  'thing';              return  super.create(cfg);        }   }   export  default  Thing;   New: ES2015 Classes import - export - class - @define •  Inheritance •  Directives •  Properties •  Methods •  Static methods •  Super calls (callParent) Decorator
  23. function  define  (className,  body)  {          return

     T  =>  {                  T.define(className,  body);          };   }     @define('App.some.Thing',  {        alias:  'thing',        text:  'Hello'   })   class  Thing  extends  Bar  {   }     define('App.some.Thing',  {        alias:  'thing',        text:  'Hello'   })(Thing);     New: Decorators •  Decorators are functions that manipulate classes (or methods) •  Decorators can accept arguments… -  But must return a function to call as if no arguments were provided •  The @decorator  syntax is just a different way to call these functions •  Decorators are currently a Stage 2 proposal (not yet standardized) https://github.com/tc39/proposals
  24. class  Foo  {          constructor  (x)  {

                     this.x  =  42;          }   }     new  Foo(42);     let  obj  =  {};   Foo.call(obj,  42);     ES2015: Restrictions on constructor •  A constructor can only be called with the new operator. •  Calling a constructor with call() or apply() throws a TypeError.
  25. Ext.define('App.mixin.Foo',  {          method:  function  (x)  {

                     return  x  *  42;          }   });     Ext.define('App.some.Thing',  {          extend:  'App.foo.Bar',          mixins:  [  'App.mixin.Foo'  ],   });     Ext.define('App.some.OtherThing',  {          extend:  'App.foo.Bar',          mixins:  [  'App.mixin.Foo'  ],            method:  function  (x)  {                  return  10  *  this.mixins.foo.method.call(this,  x);                    }   });   ExtJS: Mixins •  Mixins is multiple inheritance •  Mixins are classes •  Methods from the mixin prototype are copied to the target class prototype •  Unless there is already a method present
  26. import  {  Ext,  define  }  from  '@extjs/kernel';   import  Bar

     from  'app/foo';     class  Mixable  extends  Ext.Base  {        method  (x)  {              return  x  *  42;        }   }     @define({  mixins:  [  Mixable  ]  })   class  Thing  extends  Bar  {        method  (x)  {              return  10  *  this.mixins.mixable.method.call(this,  x);        }   }     @define({  extend:  [  Mixable  ]  })   class  OtherThing  extends  Bar  {        method  (x)  {              return  10  *  super.method(x);        }   }   ES2015: Mixins •  Mixins are classes (that extend Ext.Base) •  Use @define to mix in the mixin(s) •  Mixins will be able to act more like a true base -  The extend directive accepts mixins -  Calls to overlapping methods are handled in the super call
  27. The Life-cycle of Ext.Base Creation •  Instances are created with

    operator new   -  or Ext.create()  or other factory •  The native constructor is available to ES2015 classes -  Not recommended in most cases •  The construct method is available to all classes -  The new name for the old constructor  
  28. The Life-cycle of Ext.Base Configuration •  Use the config directive

    to define configuration properties •  Config system calls your apply and update methods •  Ext.Base construct calls initConfig  
  29. The Life-cycle of Ext.Base Destruction •  Cleanup is handled by

    destroy   •  Sets flags like destroying and destroyed   •  Ignores multiple calls •  Calls destruct (just once) •  New: Clears instance properties to avoid memory leaks
  30. The Road Ahead Sencha Cmd 6.5 •  Available now! • 

    Uses Google Closure Compiler •  Supports much of the ES2015 syntax (http://kangax.github.io/compat-table/es6/) •  Provides polyfills as well •  Transpiling is optional •  New compressor (replaces YUI) can process native ES2015 code
  31. The Road Ahead Ext JS.Next •  Framework will have changes

    in Ext.Base •  New Build Tool and new Sencha Cmd •  Upgrade tool to convert from projects from Cmd to Build •  Estimated at 2nd half of 2017