{"id":19523534,"url":"https://github.com/switer/zect","last_synced_at":"2026-04-02T01:19:05.379Z","repository":{"id":14306908,"uuid":"17015691","full_name":"switer/Zect","owner":"switer","description":"Lightweight Web components and MVVM framework, 11K (gzipped).Support IE 9+","archived":false,"fork":false,"pushed_at":"2016-11-10T08:10:37.000Z","size":786,"stargazers_count":35,"open_issues_count":0,"forks_count":5,"subscribers_count":6,"default_branch":"master","last_synced_at":"2025-04-11T19:54:26.976Z","etag":null,"topics":["mvvm-framework"],"latest_commit_sha":null,"homepage":"","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":"XX-net/XX-Net","license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/switer.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2014-02-20T09:53:32.000Z","updated_at":"2023-09-08T16:45:38.000Z","dependencies_parsed_at":"2022-09-11T11:13:43.633Z","dependency_job_id":null,"html_url":"https://github.com/switer/Zect","commit_stats":null,"previous_names":[],"tags_count":41,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/switer%2FZect","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/switer%2FZect/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/switer%2FZect/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/switer%2FZect/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/switer","download_url":"https://codeload.github.com/switer/Zect/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":250967633,"owners_count":21515634,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["mvvm-framework"],"created_at":"2024-11-11T00:43:45.324Z","updated_at":"2026-04-02T01:19:05.337Z","avatar_url":"https://github.com/switer.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"![logo](http://switer.qiniudn.com/zect.png?imageView2/0/w/160/) \nZect , component \u0026 mvvm\n====\n[![Build Status](https://travis-ci.org/switer/Zect.svg)](https://travis-ci.org/switer/Zect)\n[![npm version](https://badge.fury.io/js/zect.svg)](https://badge.fury.io/js/zect)\n\nA lightweight Web components and MVVM framework.\n**Zect**'s state observer is power by [muxjs](https://github.com/switer/muxjs)\n\n## Examples\n\n* Todo MVC: http://zectjs.github.io/zect-todo\n* Production: \n    - http://corner.ucweb.com\n    - http://m.v.qq.com/gift/bigbang/\n\n## Downloads\n- [zect.js](https://raw.githubusercontent.com/switer/zect/master/dist/zect.js)\n- [zect.min.js](https://raw.githubusercontent.com/switer/zect/master/dist/zect.min.js)\n\n## Usage\n\n```html\n\u003cscript src=\"dist/zect.js\"\u003e\u003c/script\u003e\n\u003c!-- mounted element --\u003e\n\u003cdiv id=\"app\"\u003e\n    \u003cspan\u003e{title}\u003c/span\u003e\n    \u003cinput type=\"text\" z-model=\"title\"\u003e\n\u003c/div\u003e\n```\nDefine and instance\n\n```js\nvar app = new Zect({\n    el: '#app',\n    data: function () {\n        return {\n            title: 'Hello, Zect'\n        }\n    }\n})\n```\n\n## API Reference\n- Global API\n    * [Zect()](https://github.com/switer/Zect/wiki/Global-API#zectoptions)\n    * [Zect.extend()](https://github.com/switer/Zect/wiki/Global-API#zectextendoptions)\n    * [Zect.component()](https://github.com/switer/Zect/wiki/Global-API#zectcomponentid-definition)\n    * [Zect.namespace(namespace)](https://github.com/switer/Zect/wiki/Global-API#zectnamespacenamespace)\n    * [Zect.directive(id, definition)](https://github.com/switer/Zect/wiki/Global-API#zectdirectiveid-definition)\n\n- Instance Options\n    * [el](https://github.com/switer/Zect/wiki/Instance-Options#el)\n    * [data](https://github.com/switer/Zect/wiki/Instance-Options#data)\n    * [mixins](https://github.com/switer/Zect/wiki/Instance-Options#mixins)\n    * [replace](https://github.com/switer/Zect/wiki/Instance-Options#replace)\n    * [methods](https://github.com/switer/Zect/wiki/Instance-Options#methods)\n    * [template](https://github.com/switer/Zect/wiki/Instance-Options#template)\n    * [computed](https://github.com/switer/Zect/wiki/Instance-Options#computed)\n    * [directives](https://github.com/switer/Zect/wiki/Instance-Options#directives)\n    * [components](https://github.com/switer/Zect/wiki/Instance-Options#components)\n\n- Lifecyle Methods\n    * [created](https://github.com/switer/Zect/wiki/Lifecyle-Methods#created)\n    * [ready](https://github.com/switer/Zect/wiki/Lifecyle-Methods#ready)\n    * [destroy](https://github.com/switer/Zect/wiki/Lifecyle-Methods#destroy)\n\n- Instance Methods\n    * [$set](https://github.com/switer/Zect/wiki/Instance-Methods#setkeypath-value)\n    * [$get](https://github.com/switer/Zect/wiki/Instance-Methods#getkeypath)\n    * [$watch](https://github.com/switer/Zect/wiki/Instance-Methods#watchkeypath-callback)\n    * [$unwatch](https://github.com/switer/Zect/wiki/Instance-Methods#unwatchcallback)\n    * [$compile](https://github.com/switer/Zect/wiki/Instance-Methods#compileel-scope)\n    * [$component](https://github.com/switer/Zect/wiki/Instance-Methods#componentid)\n    * [$destroy](https://github.com/switer/Zect/wiki/Instance-Methods#destroy)\n\n- Instance Properties\n    * [$el](https://github.com/switer/Zect/wiki/Instance-Properties#el)\n    * [$refs](https://github.com/switer/Zect/wiki/Instance-Properties#refs)\n    * [$methods](https://github.com/switer/Zect/wiki/Instance-Properties#methods)\n    * [$destroyed](https://github.com/switer/Zect/wiki/Instance-Properties#destroyed)\n\n- Template Syntax\n    * [if](https://github.com/switer/Zect/wiki/Template-Syntax#if)\n    * [repeat](https://github.com/switer/Zect/wiki/Template-Syntax#repeat)\n    * [template](https://github.com/switer/Zect/wiki/Template-Syntax#template)\n    * [{expression}](https://github.com/switer/Zect/wiki/Template-Syntax#expression)\n    * [{- expression}](https://github.com/switer/Zect/wiki/Template-Syntax#--expression)\n\n- Direcitves\n    * [on](https://github.com/switer/Zect/wiki/Directives#z-on)\n    * [show](https://github.com/switer/Zect/wiki/Directives#z-show)\n    * [html](https://github.com/switer/Zect/wiki/Directives#z-html)\n    * [attr](https://github.com/switer/Zect/wiki/Directives#z-attr)\n    * [class](https://github.com/switer/Zect/wiki/Directives#z-class)\n    * [style](https://github.com/switer/Zect/wiki/Directives#z-style)\n    * [component](https://github.com/switer/Zect/wiki/Directives#z-component)\n    * [static](https://github.com/switer/Zect/wiki/Directives#z-static)\n\n## Guide\n### Custom directive\n\nOptions's Methods: \n* **bind**    Call only once when directive is binding.\n* **update**  Call every time when expression's value has been changed.\n* **unbind**  Call only once when directive is unbinded.\n\nDirective instance properties:\n* **$vm**     Mounted VM of the directive\n* **$el**     Mounted target Node of the directive\n* **$id**     Current directive instance id\n* **$scope**  Repeat directive will create a scope for each item when compiling, \n              so your can access \"$index\", \"$value\" through \"$scope\". \n\n**Example below:**\n\n```html\n\u003cdiv z-tap=\"{onClick}\"\u003e\u003c/div\u003e\n```\n\n```js\nZect.directive('tap', {\n    bind: function (result, expression) {\n        // do something when init\n    },\n    update: function (result) {\n        // do something when state change or after init\n    },\n    unbind: function () {\n        // do something before destroy the directive instance\n    }\n})\n```\n\n### Two way binding\n\n```html\n\u003cdiv id=\"con\"\u003e\n    \u003cinput type=\"text\" z-model=\"search\" /\u003e\n    \u003cinput type=\"submit\" z-on=\"{onSubmit}\" value=\"submit\"\u003e\n\u003c/div\u003e\n```\n\n```js\nnew Zect({\n    el: '#con',\n    data: {\n        search: 'Please input'\n    },\n    methods: {\n        onSubmit: function () {\n            this.$data.search // input-value\n        }\n    }\n})\n```\n\n### Filter Expression\nFilters actually are function call using in template's expression.\n\n```html\n\u003cul id=\"con\"\u003e\n    \u003cz-repeat items=\"{lessThanFour(items)}\"\u003e\n        \u003cli data-index=\"{$index}\"\u003e{$value}\u003c/li\u003e\n    \u003c/z-repeat\u003e\n\u003c/ul\u003e\n```\n\n```js\nnew Zect({\n    el: '#con',\n    data: function () {\n        return [1,2,3,4,5]\n    },\n    methods: {\n        lessThanFour: function (items) {\n            return items.filter(function (item) {\n                if (item \u003c 4) return true\n            })\n        }\n    }\n})\n```\n\n* **Render result:**\n\n```html\n\u003cul id=\"con\"\u003e\n    \u003cli data-index=\"0\"\u003e1\u003c/li\u003e\n    \u003cli data-index=\"1\"\u003e2\u003c/li\u003e\n    \u003cli data-index=\"2\"\u003e3\u003c/li\u003e\n\u003c/ul\u003e\n```\n\n### Template syntax\n\n* **Content Render:**\n\n```html\n\u003c!-- escaped HTML value --\u003e\n\u003cp\u003e{title}\u003c/p\u003e\n\n\u003c!-- unescaped HTML value --\u003e\n\u003cp\u003e{- title}\u003c/p\u003e\n```\n\n* **Javascript Syntax In Expression:**\n\n```html\n\u003c!-- escaped HTML value --\u003e\n\u003cp\u003e{'Current time is: ' + new Date()}\u003c/p\u003e\n\n\u003c!-- unescaped HTML value --\u003e\n\u003cp\u003e{- 'Current Page: ' + page}\u003c/p\u003e\n```\n\n* **Condition Statements:**\n`\"is\"` is a keyword-attribute for the \"if\" directive.\nIf value is truly, the template that is included by \"if\" directive element will be compiled and insert into to parent's DOM tree.\nOtherwise template will be removed from parent's DOM tree.\n\n```html\n\u003c!-- if --\u003e\n\u003cz-if is=\"{title}\"\u003e\n    \u003cdiv\u003e{title}\u003c/div\u003e\n\u003c/z-if\u003e\n```\n\n* **Array Iterator:**\n`\"items\"` is a keyword-attribute for the \"repeat\" directive.\nThe value of items's expression should be an Array object.\n\n```html\n\u003c!-- repeat --\u003e\n\u003cz-repeat items=\"{items}\"\u003e\n    \u003cdiv data-row=\"{$index}\"\u003e{- $value}\u003c/div\u003e\n\u003c/z-repeat\u003e\n```\n\n### Reusable Component\n\nZect support reusable component that are conceptually similar to Web Components.\n\n* **define:**\n\n```html\n\u003cscript type=\"text/zect\" id=\"tpl-header\"\u003e\n    \u003cz-template class=\"header\"\u003e\n        \u003cdiv class=\"title\"\u003e{title}\u003c/div\u003e\n    \u003c/z-template\u003e\n\u003c/script\u003e\n```\n\n```js\nZect.component('c-header', {\n    template: document.querySelector('#tpl-header').innerHTML,\n    data: {\n        title: 'index'\n    },\n    ready: function () {\n\n    }\n})\n```\n* **use:**\n\n```html\n\u003cbody\u003e\n    \u003cdiv id=\"app\"\u003e\n        \u003cc-header title=\"header of page\"\u003e\u003c/c-header\u003e\n        \u003cdiv title=\"another header\" z-component=\"c-header\" class=\"another\"\u003e\u003c/div\u003e\n    \u003c/div\u003e\n    \u003cscript\u003e\n        new Zect({\n            el: '#app'\n        })\n    \u003c/script\u003e\n\u003c/body\u003e\n```\n\n* **render result:**\n\n```html\n\u003cdiv id=\"app\"\u003e\n    \u003cc-header title=\"header of page\" class=\"header\"\u003e\n        \u003cdiv class=\"title\"\u003eindex\u003c/div\u003e\n    \u003c/c-header\u003e\n    \u003cdiv title=\"another header\" class=\"header another\"\u003e\n        \u003cdiv class=\"title\"\u003eindex\u003c/div\u003e\n    \u003c/div\u003e\n\u003c/div\u003e\n```\n\n## Component Template\n\nZect will copy all attributes for \"template\" element to instance component element.\n\nComponent's HTML template:\n\n```html\n\u003cscript type=\"text/zect\" id=\"tpl-header\"\u003e\n    \u003cz-template class=\"c-header\" data-title=\"{title}\"\u003e\n        \u003cbutton\u003eBack\u003c/button\u003e\n        \u003cdiv\u003e{title}\u003c/div\u003e\n    \u003c/z-template\u003e\n\u003c/script\u003e\n```\n\nDefine component:\n```javascript\nZect.component('c-header', {\n    template: document.querySelector('#tpl-header').innerHTML\n})\n```\n\n\n## Component Attributes\n\n* **data**\n\"data\" property is used to declare binding data from the parent ViewModel. \nJust like your instance a component and pass data option. When those binding variables of expression change, \n`Zect` will be re-excute the expression and call component instance's \"$set\" method automatically for updating child component.\n\n\u003e Notice: r-data has multiple keys must using ';' as separator, otherwise can't create binding for each keys.\n\n```html\n\u003cdiv id=\"app\"\u003e\n    \u003cmy-component\n        z-data=\"{\n            title: 'child ' + title;\n            content: content;\n        }\"\n    \u003e\n    \u003c/my-component\u003e\n\u003c/div\u003e\n```\n\n* **methods**\nJust like your instance a component and pass method option. Methods only set once, so when those binding variables of expression change, it will do nothing. \n\n```html\n\u003cdiv id=\"app\"\u003e\n    \u003cmy-component\n        z-methods=\"{\n            onClick: onClickItem;\n            onTouchstar: onTouchItem;\n        }\"\n    \u003e\u003c/my-component\u003e\n\u003c/div\u003e\n```\n\n* **ref**\nThis option is used to save ref to parent ViewModel, so that access it's instance with the specified name by \"$refs\".\n\n```html\n\u003cdiv id=\"app\"\u003e\n    \u003cmy-component z-ref=\"header\"\u003e\u003c/my-component\u003e\n\u003c/div\u003e\n```\n\n```js\nthis.$refs.header // access child component instance.\n```\n\n* **replace**\nThis option is uesed to reduce one level document structure. if attribute value equal \"true\",\nwill replace component's element with it's main child element.\n\nComponent template:\n```html\n\u003cdiv class=\"header\" data-title=\"header\"\u003e\n    \u003ch1\u003eHeader\u003c/h1\u003e\n\u003c/div\u003e\n```\n\nUsage:\n```html\n\u003cdiv id=\"app\"\u003e\n    \u003cmy-component z-replace=\"true\" class=\"app-header\"\u003e\u003c/my-component\u003e\n\u003c/div\u003e\n```\n\nRender result:\n```html\n\u003cdiv id=\"app\"\u003e\n    \u003cdiv class=\"app-header header\" data-title=\"header\"\u003e\n        \u003ch1\u003eHeader\u003c/h1\u003e\n    \u003c/div\u003e\n\u003c/div\u003e\n```\n\n\n## Computed Properties\nFor those complicated logic, you should use computed properties to replace inline expressions.\n\n```js\nvar demo = new Zect({\n    data: {\n        host: 'https://github.com',\n        user: 'switer',\n        repos: 'zect'\n    },\n    computed: {\n        link: {\n            // property dependencies of getter\n            deps: ['host', 'user', 'repos'],\n            // property getter\n            get: function () {\n                var $data = this.$data\n                return [$data.host, $data.user, $data.repos].join('/') // https://github.com/switer/zect\n            },\n            // setter is optional\n            set: function (link) {\n                // input: https://github.com/zectjs/zect.github.io\n                var $data = this.$data\n                var parts = link.replace(/\\/$/, '').split('\\/')\n                $data.repos = parts.pop()\n                $data.user = parts.pop()\n                $data.host = parts.join('/')\n            }\n        }\n    }\n})\n\n```\n## List operate\n\n- **Display List**\n\nUse `z-repeat` block element to repeat display template.\n\n```html\n\u003cdiv id=\"list\"\u003e\n    \u003cul\u003e\n        \u003cz-repeat items=\"{items}\"\u003e\n            \u003cli\u003e{$value}\u003c/li\u003e\n        \u003c/z-repeat\u003e\n    \u003c/ul\u003e\n\u003c/div\u003e\n```\n```js\nnew Zect({\n    data: {\n        items: [\"Switer\", \"Zect\", \"Xiaokai\"]\n    }\n})\n```\nResult:\n```\n* Switer\n* Zect\n* Xiaokai\n```\n\n- **Append More**\n\n```js\nvm.$data.items.$concat(['Web Component'])\n```\nWill delta update:\n```\n* Switer\n* Zect\n* Xiaokai\n+ Web Component\n```\n\n- **Append Before**\n\n```js\nvm.$data.items.splice(0, 0, 'Web Component', 'MVVM')\n```\nResult:\n```\n+ Web Component\n+ MVVM\n* Switer\n* Zect\n* Xiaokai\n```\n\n- **Remove**\n\n```js\nvm.$data.items.splice(1, 1)\n```\nResult:\n```\n+ Web Component\n- MVVM\n* Switer\n* Zect\n* Xiaokai\n```\n\n- **Push**\n\n```js\nvm.$data.items.push('Web Component')\n```\nResult:\n```\n* Switer\n* Zect\n* Xiaokai\n+ Web Component\n```\n\nand `shift`, `unshift`, `sort`, `reverse`, `pop`. `shift`, `unshift`, `pop` whill be Update in delta (includes `splice` and `concat`).\n\n\n![Footer](http://switer.qiniudn.com/red-brick.jpg)\n\n## License\n\nMIT\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fswiter%2Fzect","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fswiter%2Fzect","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fswiter%2Fzect/lists"}