Brief introduction:


  • Eng is a MVVM mode super lightweight component data rendering JS local plug-in, only 16KB. It supports the core functions of React, Vue, and Angular family bucket packages, so it’s a lighter implementation that has the least, simplest, and easiest learning curve of any of these tools.

  • Eng is decoupled from 99% of the background in most cases. Eng components encapsulated according to Eng rules have the characteristics of writing once and deploying everywhere. The backend only needs to configure the data request interface. In the special case of using local data, the back-end involvement in the front-end work is close to zero;

  • Main features of Eng: data multi-direction binding, component closure communication (dynamic), component group circulation communication, data state sharing (in cross-page mode: Cross-component, multi-direction control), component require (automatically load JS and CSS on demand), component self-request data, support list data filtering, achieve Excel data statistical calculation, component method self-cache reuse

  • Eng compared with similar tools: fewer and simpler instructions/methods to achieve the same operation, no component communication barriers, no special complex routing controller (1 ID1 interface) in the background, data state sharing only need a short declaration, the component is a complete closure of the full function of automatic independent operation.

  • The Eng data structure and DOM hierarchical division are mutually structured views. Under the deep development, it provides exceptionally clear thinking mode of law logic and example deduction effect;


Eng:


  • Eng-nos: 1.7KB compatible with all browsers js component pure data rendering plug-in, the first rendering has the world’s top performance, can only be executed by eng-drive compiled files.
  • Eng-drive: Eng component server rendering tool, can only render pure data instructions, its compilation file can be executed by ENG-NOS in the local end


Version Description:


  • 0.8 x: slightly
  • 0.9 x: slightly
  • 1.0.0: (currently) component method automatic cache reuse, temporarily off for some possible extreme issues (enable to see update notifications)


Notice (Must See) :


  • The beginning of $_ is the exclusive naming field for Eng, the data key name of Eng, and other custom attribute methods, and should be avoided at all times
  • {{obj.value}} this writing method will destroy the idea of mutual structural view of Eng data and DOM, as well as the thinking mode of regular logic under deep development. The author believes that the benefits of the rule rule far outweigh the freedom of randomness, so Eng will never support this writing method, specifically refer to the E-base directive
  • $_value: Can output only three constant types: Number, Boolean, and String, also based on the preceding rule. Null, undefined, NaN data should be output as String, otherwise the default data is “” empty String
  • Eng component development implements the closure principle and supports dynamic communication of closures, which should be followed in normal development mode


Basic instructions:


E – base: (important)


<div>
    <div e-base='base'>
        <p>{{value1}}</p>
        <p>{{value2}}</p>
     </div>
</div>
Copy the code
 var  data={
        base:{
            value1:'xxx',
            value2:'xxxx',
        }
 };
Copy the code

The value of {{value}} is an e-base object, equivalent to base.value1; base.value2
The JSON objects in the Eng component data are all E-Base, which completely correspond to the parent-child hierarchical design planning of DOM data structure and are mutually structured views. In the in-depth development, this rule will form the logic of law thinking, and all the Eng component methods run under a unified logic of law, with consistent behavior everywhere, with example effect


e-html:


<div>
    <div e-html='html'>
    </div>
</div>
Copy the code
Var data={HTML :"<p> insert HTML text </p>"};Copy the code

E-html is dom.innnerhtml = HTML text and overwrites its children, so any other instructions written to the children will be invalidated


e-attr:


<div e-attr='class=value'> .... </div> <div e-attr='class=value? (css1):(css2)'> ... </div> <div e-attr='class=value2>=10? (css1):(css2)'> .... </div> <div e-attr='XXXX=value; title=value2; class=value3>=10? (css1):(css2)'> .... </div>Copy the code

E-attr: Can write almost any inline attribute, supports ternary operation, use “; “between multiple expressions Delimit by semicolon.
There can be no extra Spaces in the current version of the expression, and no other “; “in the () of the expression. Semicolons and () parentheses


e-id:


  <div>
     <div e-id='idName'> ...... </div>
  </div>
Copy the code

E-id: used to obtain the current DOM object. It is used in itMES parameter of all methods in the component by means of items. IdName


e-event:


    <div>
        <button e-event='onclick:fun'>

            click

        </button>

    </div>
Copy the code
. Event :{fun: function(){alert('chlick'); //console.log( this.$_data, this.$_gData ,this.$_items) } } ...Copy the code

E-event = “onclick:fun” the relationship with native JS is equivalent to dom.onclick=fun
The e-event bound EVENT Dom object has access to data that modifs the current base ($_data) scope, global ($_gData) scope, and all associated components using all methods of the current component, as well as actions, through ($_items)
Therefore, e-Event is a universal DOM event binder, enabling almost all DOM events to interact with components
To use the e-event directive in the shard component, declare it before the shard component: items.$_event.fun = function(){… }
The following e-input and e-change directives extend implementations based on this principle


e-input:


    <div>
         <p>{{value}}</p>
         <input e-input='value'>
    </div>
Copy the code
Data ={value:' I'll try '}Copy the code

Let me try it out

E-input: indicates real-time response data changes. If a large number of operations are associated, e-change is recommended


e-change:


    <div>
         <p>{{value}}</p>
         <input e-change='value'>
    </div>>
Copy the code
Data ={value:' I'll try '}Copy the code

Let me try it out


e-for:


  <div>
       <div>
           <p e-for='arr1'>{{$_index}}___{{$_value}}</p>
       </div>
       <div>
            <div e-for='arr2'>
                  <p>{{$_index}}___{{v}}</p>
                  <div>
                       <p e-for='arr3'>{{$_index}}___{{$_value}}</p>
                  </div>
            </div>
       </div>
  </div>
Copy the code


Data = {arr1: [' a ', 'b', 'c'], arr2: [{v: 'arr2. V = 1, arr3:,8,9 [7]}, {v:' arr2. V = 2, arr3: [11]},]}Copy the code

Note that in the example, all e-for elements are wrapped with an empty div parent tag (absolute positioning)
The DOM element of E-for depends on its parent element for positioning. The author believes that the design of the parent element has absolute stability in the development of dom dynamic components with deep interaction. Thus, dom elements generated in the e-for directive are appended by default from the end of the child element queue within the parent element
{{$_index}} is the subscript output mode of data elements in the e-for instruction
{{$_value}} Can output only basic data types: Boolean, Number, and String. Use String instead of undefined and null. Otherwise, the default output is “” empty String
Eng e-for=’ XXX ‘is also a special type of E-base =’ XXX’ base object, so the child data must also be JSON objects in nested loops. Arr =[{v:’xx’,arr2=[x,x,x]}]; if arr=[[x,x], [x,x]], e-base= 0,1,2. Eng will not automatically process this data format. Again, this arbitrary writing method will destroy the regular logic thinking and example deduction effect of Eng in deep development, so this writing method will never be supported.
When array.push(), array.concat()… . Data. array= ‘update’; Json object data is also valid


Parameters & Methods:


el:


var app=new Eng({ el: // "idName" || document.getElementById("idName"); . })Copy the code

El: Accepts only the name value of the page ID and the native DOM object


id:


New Eng({el: XXX, id:'idName' // unique! Component closure communication, identification basis for data state sharing across pages (no requirement can be ignored)..... })Copy the code

Id: component identity name, unique. Component closure communication, identification basis for data state sharing across pages (no requirement can be ignored)


cache:


New Eng({el: XXX, cache:{a: XXX // component custom variable cache, equivalent to component let scope, through all items.$_cache, cache operation b: XXX}..... })Copy the code

A component’s custom variable cache is equivalent to a component’s let scope and is accessed through all items.$_cache and cache of the component


relate:


new Eng({ el:.... id:... , realte:['idName1', 'idNname2'] // Type:Array associated with other id components})Copy the code

Realte: [‘name1′,’name2’]. Associate components with ids idName1 and idName2, regardless of whether they are currently created
Usage: You can access all data and methods of modifying these components by means of items. Name1 and items. Name2 on the items parameter in any location of the current component, which is equivalent to directly manipulating items associated with other components
items.$Relate returns an arraylist of the idNames of all components that have been properly associated. For later associated components, you should check whether the items. Name object exists or loop through itemsRelate the array


require:


new Eng({ el:... The require: {CSS: ['/a.c ss ', '/ biggest ss', '/ Arthur c. ss', '/, dc ss'], / / priority load CSS, js: ['. / a. s', '/ b.j s','/SAN Antonio 's, './d.js'] } })Copy the code

The require: {CSS: […]. Js: […]. } The CSS section is loaded first, and the data rendering display is performed first



showStage( items , cache):


new Eng({ el:.... require:{ css:[......]  }, showStage:function( items , cache ){ //do something } })Copy the code

ShowStage will only be executed if the REQUIRED CSS pass argument exists. CSS styles have been loaded, do you want to do something first, without waiting for other JS to load


template:


New Eng ({el: XXXX, the template: "< div > {{value}} < / div >", / / HTML string template data: {value: 'XXX'}})Copy the code

Template: HTML string template. When the template argument is present, the generated component DOM is populated with child elements of el


data:


new Eng({ .... Data :{// nothing to say}})Copy the code


watcher:


new Eng({ el:... watcher:{ v:function(oldValue , newValue , items, cache){ <! // items.$_destory // items.$_caller <! -- Items are no longer specified see: The items & cache - - > / / items. $_wather as / / / / = = = watcher role items. $_watherFor as / / / / = = = watcherFor role... }, 'a.v':function(oldValue, newValue, items, cache){//.... } }, data{ v:'xxx', a:{ v:'xxxx' } } })Copy the code

Watcher: The registered observer is executed immediately, and the watcher registered items.$_watcher is triggered when data is modified
Items.$_value: Changes the current output value items.$_value =’ the value I want to change ‘, of course you can also change the output value items
$_destory: Internal logic to determine the self-destruct of the current Watcher object. Of course, you can also destroy the watcher object with the items.$_watcher({‘ XXX ‘: null}) again leaving the book empty on the items parameter at any time
Items.$_caller: The calling mechanism is used to avoid the “Wach nightmare”. In mutual watch communication and multi-component associated watch loop communication, it prevents both sides of the watch from writing judgment logic. When items.$_caller = true, the calling mechanism is enabled, and the watch is disconnected from the bottom layer to enter an infinite loop.


WatcherFor: (important)


new Eng({ el:.... Data: {arr1: [1, 2, 3], arr2: [{v: "', arr3:,8,9,10 [7]}]}. watcherFor:{ arr1:function( items ,cache){ //items.$_allow //items.$_data //items.$_gData //itesm.$_forData $_pos //items.$_gIndex //items.$_watcher //items. Items in watcherFor is a special items}}})Copy the code

WatcherFor can perform Excel functions, and if you want to dig deeper, the sorting function has been updated
For Array data types, push(), etc., and cannot respond to the data itself, simply execute data.arrray = ‘update’
Items.$_allow: Indicates whether to allow current data to pass. Default is true
Items.$_data: Data of the array elements currently being loaned
Items.$_gData: Full data of the component
Itesm. $_forData: the current loop array. If $_data is a non-reference data type, it can be modified according to the items.$_index subscript
Items.$_index: The index of the current looping array element data
Items. $_pos: The multidimensional subscript of the currently looped element, used in nested loops. Example: [1,2] indicates that the current element is the subscript 2 element of the child element of the parent element with subscript 1
Items.$_gIndex: The position of this loop in all loops of the entire component
Items.$_watcher: Registers watcher based on the current base path and automatically ignores the lead path. This is used to implement special application scenarios of Watcher inside the loop
Items. $_gWatcher: A plain Watcher method used to establish a Watcher relationship between data outside the loop and the current data
$_items: The items of the general property method, not the special items in watcherFor


created:


var app = new Eng({ el:... data:.... Created :function(items, cache){// If the component is created, all related programming should be written inside the created object. // If the component is created outside the object, it can also be written outside the Eng closure rule. Internal methods to manipulate components, you need to pass the items argument // app can only modify data}})Copy the code


$_setToSelf:

Shard component, non-data response


new Eng({ el:.... data:... created:function( items , cache){ var fragment = "<div><p> {{v}} </p></div>"; Var data={v: "shard component generated by $_setToSelf does not support data response"}; var dom = items.$_setToSelf(data, fragment ); document.body.appendChild(dom); }})Copy the code

Writing e-ID and e-for instructions is not supported in the shard component template, and the shard itself can be placed throughout the page


$_setToGlobal:

Shard component, data response


var app = new Eng({ el:.... Data: {a: 1,}, created: function (items, cache) {var fragments = "< div > < p > {{n}} < / p > < / div >"; Var data={v: "$_setToGlobal generates shard component support data response "}; Var dom = items.$_setToGlobal({el: fragment, key: "base", //) });});});}); document.body.appendChild(dom); / / modify app. Base. The value of v will respond to the console page. The log (app | | items. $_gData); / * data: {a: 1, base: {v: '$_setToGlobal fragments generated by the component Support data response '* /}}}})Copy the code

Writing e-ID and e-for instructions is not supported in the shard component template, and the shard itself can be placed throughout the page
Base: The path must be based on the existing factual data path if the path is not ignored


ajax:


new Eng({ el:.... ajax:{ type: // dataType: // Default: get dataType: // Default: json URL: // data interface address data: {id: }, success:function(data, items){items.$_addData(data); Error :function(err, items){}})Copy the code

Eng’s Ajax method is simply a simple Ajax data request scheme, with all the parameters shown in the example. No mandatory use restrictions
When using other tripartite Ajax request schemes, the items.$_addData in the example is used to add data
Other times, you can use items.$_ajax({.. }) using
Jsonp is not currently supported as it is only a secondary feature


The items & cache:



The Items and cache parameters are present in the Eng component’s Watcher, watcherFor, Created, Ajax, showStage, and E-Event bound Dom objects, and in any execution method body that requires a logical judgment operation
Items are only slightly different in Watcher and watcherFor, while other property methods have the same list of functions
Items are any door that accesses (realTE) associated components and can point from any component to another. Example: the items. App2.. App3. App1 (these components relate to each other)
Cache is the let scope within a component that is used to globally access the cache for logical determination of custom variables between component methods, equivalent to items.$_cache


Component encapsulation:

Component encapsulation is encapsulation for use, data state management (across pages), and one authoring deployment everywhere


$_XXXX=function(CFG){/* $_XXXX=function(CFG){$_XXXX=function(CFG){/* $_XXXX=function(CFG){ */ var template=""; */ var template=""; Var CSS =""; // Component CSS style text, can be ignored (if provided externally) if(cfg.css) eng.addstyle (CSS); New Eng({el:cfg.el, id:cfg.id, relate:cfg.relate, require:cfg.require, The template: CFG) template | | template, data: CFG. Data, ajax: CFG. Ajax, //------ else user-defined data ------ created:function(items, cache){// Component private user-defined data programming area}}); };Copy the code

Review the following page A, B demo source, reference


Data state sharing :


Var config={app:{//app is the XXX part of the package named $_xxx el:... // the page already has idName or DOM object, the component generated after the filling target id: 'app', // id: Relate :[], // List of component ids associated with the app, CSS :[], js:[]}, data:{}, // The local data or simulated data of the component will not execute the initial Ajax request if it exists. Template :... // The text template data of the component, if the package component is not wrapped, need to provide. , // The component initializes ajax requests for the component's data, and does not need to be ignored by CSS:... , // Boolean, whether to use the encapsulated CSS style, true is used, false can be ignored, in this case, the page should provide cache: }, app2:{.... },... // This parameter can be customized and is not required. The following Shared configuration format for the data ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ $_sharedData: {/ / all the parameters' < = > ': [' app'] / / two-way constraints (id) with the same component data sharing, Id list '=>':['app2'] // Unidirectional constraint full data share of the same (id) component, ID list '<? >':[] // Two-way constraint any id component, share specified path data to specified path '? >':[] // unidirectional constraint any component id, share the specified path data to the specified path '=':[] // only receive the same component ID data, no external constraint '? =':[] // Only receive the specified path data of the specified component, without external constraint}}; Eng.init(config);Copy the code


<=> : Example


/ / a configuration page ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ var CFG = {app: {el: the document body, id: 'app', CSS: true}. $_sharedData:{ '<=>':['app'] } }; Eng.init(cfg); / / use/configuration/b page ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ var CFG = {app: {el: the document body, id: 'app', CSS: true}. $_sharedData:{ '<=>':['app'] } }; Eng.init(cfg);Copy the code

Open the following two pages and you will find that the component data is the same no matter how the data is modified on the two pages
A page



Page b


=> and = : Example


// a page config =>':['app'] // b page config =':['app']Copy the code

Open the following two pages. The data of page B is always restricted by page A. Even if it is modified, it will be restored to page A and page B after refreshing or switching pages


<? > : Example


// a page config '<? >':['app1.a=app2.b'] // The value of current page app1.a is assigned to other pages app2.b; App1 App2 for component ID // B page config '<? >':['app2.b=app1.a'] // The value of the current page app2.b is assigned to other pages app1.a; App2 App1 is the component IDCopy the code

[‘app1=app2’] the current version is invalid. Only the specified path can be assigned to the specified path. Full copy is not allowed. Other values are not affected page A page B


? > with? = : Example


// a page config '? >':['app1.a=app2.b'] // The value of current page app1.a is assigned to other pages app2.b; App1 App2 for component ID // b page config '? ['app2.b=app1.a'] // The value of the current page app2.b is assigned to other pages app1.a; App2 App1 is the component IDCopy the code

[‘app1=app2’] the current version is invalid, only the specified path is allowed to assign data to the specified path, and full copy is not allowed. Open the following two pages, and you will find that the value of app2.b on page B is always constrained by the value of app1.a on page A, even if it is changed. Page A and page B are restored after the page is refreshed or switched


Conclusion:


  • Eng focuses on the understanding of its logic rules and the use of skills, which can achieve page level operation of all similar tools. If you feel that this part is not fully functional, please use your brain

Wang yan:


Eng is last July or so, accidentally generated in the network, rise to write a pure data response plug-in, thought that someone would like, but the response is few, then put aside no longer care. At the end of November, the base thing resigned to relax in March, cough! (the author is a student of arts) after the Lantern Festival looking for a job, after several rounds of sea investment, extremely disgusted! React, Vue, Angular Tide is sweeping, we can hear, in the eyes of HR is not as good as the picture, the heart is stuffy. Some of the implementations of these tools, which are at the heart of the implementation, are not considered worthy of much praise. This kind of thing, a little bit of JS experience of the front-end practitioner to spend some time can write out, Eng is not necessarily much clever implementation, such tools have appeared. Therefore, we decided to make up for Eng's shortcomings in supporting the core functions of other tools and make it simple and lightweight. Please comment on my stupid work... (Special thanks to the former company leader, who gave me the space to grow freely....)Copy the code