这里有新鲜出炉的 vue.js 教程,程序狗速度看过来!
Vue.js 是构建 web 界面的 JavaScript 库,提供数据驱动的组件,还有简单灵活的 API,使得 MVVM 更简单。
这篇文章主要介绍了 Vue 结合原生 js 实现自定义组件自动生成示例, 小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
就目前三大前端主流数据驱动框架(vue,ng,react)而言,均具有创建自定义组件的 api,但都是必须先做到事先写好挂载点,这个挂载点可以是原有静态元素标签也可以是自定义模板;对于多种组件通过同一数据流生成的,如果事先在页面上写好挂载点 (mounted),然后通过 dom 操作去动态添加,会遇到类似这样一条错误提示信息:Failed to execute 'appendChild' on 'Node': parameter 1 is not of type 'Node'.(…)。这又是为何呢,下一步该怎么办?
原因是任何 dom 操作的对象必须是符合 W3C 标准的元素,除非如下所述的,改写生成 html 元素对象的原型(HTMLElement.prototype)并注册自定义元素,从而实现动态生成自定义组件的效果。
不过,大家都明白使用数据驱动框架的初衷就是尽可能避免 dom 操作,而如下代码中还是有一些 dom 操作的,就目前认知水平而言,感觉这些必要的 dom 操作还是避免不了的。其它不多说了,直接看代码。。。
- <!DOCTYPE html>
- <html>
- <head>
- <meta charset="utf-8">
- <meta http-equiv="Content-type" content="text/html,charset=utf-8" />
- <meta http-equiv="X-UA-Compatible" content="IE-edge">
- <meta name="viewport" content="width=device-width,initial-scale=1">
- <link href="CSS/mui.min.css" rel="stylesheet">
- <link href="css/app.css" rel="stylesheet">
- <script src="js/vue.js" type="text/javascript">
- </script>
- </head>
- <body>
- <div id="main" class="mui-content">
- </div>
- </body>
- <script src="js/fuhao-components.js" type="text/javascript">
- </script>
- <script>
- var jsonData = [{
- "keyname": "姓名鄂然失色而热重重中之重重中之重杂志的热热",
- "type": "text",
- "key": "name11"
- },
- {
- "value": "姓名鄂之重杂志的热热",
- "key": "name11"
- },
- {
- "keyname": "姓名鄂然失色而热热热热是重中之重重中之重重中之重杂志的热热",
- },
- {
- "keyname": "姓名鄂然失色而热热热热是重中之重重中之重重中之重杂志的热热",
- "type": "textarea",
- "key": "name"
- },
- {
- "keyname": "性别",
- "type": "radio",
- "key": "sex",
- "values": [{
- "key": "man",
- "value": "男辅导班"
- },
- {
- "key": "women",
- "value": "女"
- }]
- },
- {
- "keyname": "复选",
- "type": "checkbox",
- "key": "checkbox",
- "values": [{
- "key": "man",
- "value": "男"
- },
- {
- "key": "women",
- "value": "女"
- }]
- },
- {
- "keyname": "类型",
- "type": "select",
- "key": "type1",
- "values": [{
- "key": "type1",
- "value": "类型1"
- },
- {
- "key": "type2",
- "value": "类型2"
- },
- {
- "key": "type3",
- "value": "类型3"
- },
- {
- "key": "type4",
- "value": "类型4"
- }]
- },
- {
- "keyname": "定位",
- "type": "gps",
- "key": "btn",
- "value": "地图获取定位"
- },
- {
- "keyname": "拍照",
- "type": "photo",
- "key": "btn",
- "value": "拍照"
- }]; (function() {
- AnalyJson(jsonData);
- })();
- function AnalyJson(data) {
- if ('id' in data) {
- arguments.callee(data.values);
- } else {
- if ('name' in data) {
- htmlname = data.name;
- CreateInputViewer(data.name);
- arguments.callee(data.values);
- } else {
- if ('type' in data) {
- CreateInputViewer(data);
- } else {
- for (var p in data) {
- CreateInputViewer(data[p]);
- }
- }
- }
- }
- }
- function CreateInputViewer(data) {
- switch (data.type) {
- case 'text':
- {
- fh_C(data, 'c-input-text' + '-' + data.key, 'fhInputText', textTpl);
- break;
- }
- case 'textarea':
- {
- fh_C(data, 'c-textarea' + '-' + data.key, 'fhInputTextarea', textareaTpl);
- break;
- }
- case 'radio':
- {
- fh_C(data, 'c-input-radio' + '-' + data.key, 'fhInputTextarea', radioTpl);
- break;
- }
- case 'checkbox':
- {
- fh_C(data, 'c-input-checkbox' + '-' + data.key, 'fhInputCheckbox', checkboxTpl);
- break;
- }
- case 'select':
- {
- fh_C(data, 'c-select' + '-' + data.key, 'fhSelect', selectTpl);
- break;
- }
- case 'photo':
- {
- fh_C(data, 'c-photo' + '-' + data.key, 'fhPhoto', photoTpl);
- break;
- }
- case 'gps':
- {
- fh_C(data, 'c-gps' + '-' + data.key, 'fhGPS', gpsTpl);
- break;
- }
- default:
- {
- fh_C(data, 'c-default' + '-' + data.key, 'fhInputDefault', defaultTpl);
- break;
- }
- }
- }
- function fh_C(d, c, cn, tpl) {
- console.log(d);
- Vue.component(c, {
- template: tpl,
- // props:['key','keyname','values','value'],
- data: function() {
- return d
- }
- });
- new Vue({
- el: '.mui-content',
- components: {
- cn: cn
- },
- });
- var MyElementProto = Object.create(HTMLElement.prototype);
- MyElementProto.createdCallback = function() {
- this.innerHTML = tpl
- };
- var MyComponent = document.registerElement(c, {
- prototype: MyElementProto
- });
- document.querySelector('.mui-content').appendChild(new MyComponent());
- }
- </script>
- </html>
为了保持代码的可维护性及易读性,我将模板部分单独放在 fuhao-components.js 的文件里边,如下所示:
- var textTpl='';
- <div class="mui-content-padded">
- <input :type="type" :name="key" :placeholder="keyname" >
- </div>
- var textareaTpl= '';
- <div class="mui-content-padded ">
- <textarea rows="5" :placeholder="keyname">
- </textarea>
- </div>
- var radioTpl= '';
- <form class="mui-input-group mui-content-padded">
- <div class="mui-input-row mui-radio mui-left"v-for="value in values">
- <label>{{value.key}}</label>
- <input :name="key" :type="type" :value="key">
- </div>
- </form>
- var checkboxTpl= '';
- <form class="mui-input-group mui-content-padded">
- <div class="mui-input-row mui-checkbox mui-left"v-for="value in values">
- <label>{{value.key}}</label>
- <input :name="key" :type="type" :value="key">
- </div>
- </form>
- var selectTpl= '';
- <div class="mui-content-padded">
- <h5 class="mui-content-padded" v-text="keyname"></h5>
- <select class="mui-btn mui-btn-block " :name="key">
- <option value="key" v-text="value.key" v-for="value in values">{{value.key}}</option>
- </select>
- </div>
- var photoTpl= '';
- <div class="mui-content-padded">
- <span v-text="keyname"></span>
- <button :name="key" onclick="takePhoto(this.name)" class="mui-btn mui-btn-primary">拍照</button>
- <img :id="key" height="70" width="100" class="img-rounded">
- </div>
- var gpsTpl='';
- <div class="mui-content col-xs-12">
- <button class="mui-btn mui-btn-primary" :id="key" onclick="takeLocation(this.id)">
- 获取定位
- </button>
- </div>
- var defaultTpl= '';
- <div class="mui-content-padded " v-if="key">
- <ul class="mui-table-view">
- <li class="mui-table-view-cell mui-media">
- <span class="fuhaoKey" v-text="key"></span>
- <span class="fuhaoValue" v-text="value"></span>
- </li>
- </ul >
- </div>
最终渲染效果如下:
鉴于 vue 结合 dom 操作动态生成自定义组件,控制台会报一定的错误这一点 bug 还在努力修复中,可能需要更加深入地了解 vue 数据绑定及传递机制与 js 动态注册自定义组件的深入领会,继续努力中。。。
来源: http://www.phperz.com/article/17/0626/328242.html