原创 vuejs 无node单页应用方案二(babel-standalone or traceur,vue-router实现、组件按需懒加载)

分类:js,vuejs2017-06-20 08:04:46   510人阅读  评论   分享

前提、摘要及相关模块详解请看前一篇戳这里


本方案针对前片优化点的问题

1、模版按需懒加载(Promise和vue异步组件实现)

2、可以使用完全的es6语法

3、组件不会重复创建(vue-router不会重复创建组件,创建后会缓存)

4、如何使用实现AMD、Commonjs标准的模块加载器(未实现,大侠是该你出手了)


本片涉及知识及传送门

1、promise es6异步编程解决方案  传送门

2、babel es6到es5转码器之一  传送门

因为没有使用node、webpack所以无法使用vue-loader,自定义组件加载方法如下

说明:组件的生成和解析自定义,此处生成异步组件

function loadComponent(componentName, path) {
        return new Promise(function(resolve, reject) {
            $.ajax({
                type: "GET",
                url: path,
                dataType:'text',
                success(data) {
                    var result = null;
                    var arr = [];
                    arr = data.split('/*###*/');
                    var template = arr[0];
                    result = arr[1];
                    result = result.replace('<script>','').replace('</script>','');
                    result = eval(result);
                    result.template = template;
 
                    Vue.component(componentName, result);
                    var component = Vue.component(componentName);
                    if (component) {resolve(component);} else { reject('create component fail');}
                },error(XMLHttpRequest, textStatus, errorThrown){reject(textStatus);}
            });
        });
    }


交流加群:391053981

好了,上完整代码:


index.html:


<script src="https://unpkg.com/vue/dist/vue.js"></script>
<script src="https://unpkg.com/vue-router/dist/vue-router.js"></script>

<div id="app">
    <el-row>
        <el-col :span="4"><div class="grid-content bg-purple">IFace后台</div></el-col>
        <el-col :span="20">
            <el-menu theme="dark" :default-active="activeIndex" class="el-menu-demo" mode="horizontal" @select="handleSelect">
                <el-menu-item index="1">处理中心</el-menu-item>
                <el-submenu index="2">
                    <template slot="title">我的工作台</template>
                    <el-menu-item index="2-1">选项1</el-menu-item>
                    <el-menu-item index="2-2">选项2</el-menu-item>
                    <el-menu-item index="2-3">选项3</el-menu-item>
                </el-submenu>
                <el-menu-item index="3"><a href="#" target="_blank">订单管理</a></el-menu-item>
            </el-menu>
        </el-col>
    </el-row>
    <el-row>
        <el-col :span="4">
            <el-menu default-active="2" class="el-menu-vertical-demo" @open="handleOpen" @close="handleClose">
                <el-submenu index="1">
                    <template slot="title"><i class="el-icon-message"></i>导航一</template>
                    <el-menu-item-group>
                        <template slot="title">分组一</template>
                        <el-menu-item index="1-1">选项1</el-menu-item>
                        <el-menu-item index="1-2">选项2</el-menu-item>
                    </el-menu-item-group>
                    <el-menu-item-group title="分组2">
                        <el-menu-item index="1-3">选项3</el-menu-item>
                    </el-menu-item-group>
                    <el-submenu index="1-4">
                        <template slot="title">选项4</template>
                        <el-menu-item index="1-4-1">选项1</el-menu-item>
                    </el-submenu>
                </el-submenu>
                <el-menu-item index="2"><i class="el-icon-menu"></i>导航二</el-menu-item>
                <el-menu-item index="3"><i class="el-icon-setting"></i>导航三</el-menu-item>
            </el-menu>
        </el-col>
        <el-col :span="20">
            <el-breadcrumb separator="/">
                <el-breadcrumb-item :to="{ path: '/foo' }">首页</el-breadcrumb-item>
                <el-breadcrumb-item :to="{ path: '/bar' }">活动管理</el-breadcrumb-item>
                <el-breadcrumb-item>活动列表</el-breadcrumb-item>
                <el-breadcrumb-item>活动详情</el-breadcrumb-item>
            </el-breadcrumb>
            <p>
                <router-link to="/contact">contact</router-link>
                <router-link to="/bar">news</router-link>
            </p>
            <router-view></router-view>
        </el-col>
    </el-row>
</div>

<link rel="stylesheet" type="text/css" href="/style/css/font-awesome-4.7.0/css/font-awesome.min.css" />
<link rel="stylesheet" href="https://unpkg.com/element-ui/lib/theme-default/index.css">
<script src="https://unpkg.com/vue/dist/vue.js"></script>
<script src="https://unpkg.com/vue-router/dist/vue-router.js"></script>
<script src="https://unpkg.com/element-ui/lib/index.js"></script>
<script src="https://cdn.bootcss.com/babel-standalone/6.25.0/babel.js"></script>
<script src="/style/js/jquery.min.js" type="text/javascript"></script>
<script type="text/babel" data-presets="es2015,stage-2">

    function loadComponent(componentName, path) {
        return new Promise(function(resolve, reject) {
            $.ajax({
                type: "GET",
                url: path,
                dataType:'text',
                success(data) {
                    var result = null;
                    var arr = [];
                    arr = data.split('/*###*/');
                    var template = arr[0];
                    result = arr[1];
                    result = result.replace('<script>','').replace('</script>','');
                    result = eval(result);
                    result.template = template;

                    Vue.component(componentName, result);
                    var component = Vue.component(componentName);
                    if (component) {resolve(component);} else { reject('create component fail');}
                },error(XMLHttpRequest, textStatus, errorThrown){reject(textStatus);}
            });
        });
    }

    var router = new VueRouter({
        mode: 'history',
        routes: [
            {
                path: '/',
                component: {
                    template: '<div>Home page</div>'
                },
            },
            {
                path: '/contact',
                component: function(resolve, reject) {
                    loadComponent('contact', '/backend/components/topicZone.vue').then(resolve, reject);
                }
            }
        ]
    });

    var app = new Vue({
        el: '#app',
        router: router,
        data: {
            activeIndex: '1',
            activeIndex2: '1',
            currentView: 'home'
        }, methods: {
            handleSelect:function(key, keyPath) {
                console.log(key, keyPath);
            },handleOpen:function(key, keyPath) {
                console.log(key, keyPath);
            },handleClose:function(key, keyPath) {
                console.log(key, keyPath);
            }
        }
    });
</script>
<style>
    body{margin:0px}
</style>


topicZone.vue

<el-table :data="tableData" style="width: 100%">
    <el-table-column prop="date" label="日期" width="180">
    </el-table-column>
    <el-table-column prop="name" label="姓名" width="180">
    </el-table-column>
    <el-table-column prop="address" label="地址">
    </el-table-column>
</el-table>
/*###*/
<script>
    (function(){
        return {
            data() {
                return {
                    tableData: [{
                        date: '2016-05-02',
                        name: 'IT小君',
                        address: '上海市普陀区金沙江路 1518 弄'
                    }, {
                        date: '2016-05-04',
                        name: '王小虎',
                        address: '上海市普陀区金沙江路 1517 弄'
                    }, {
                        date: '2016-05-01',
                        name: '王小虎',
                        address: '上海市普陀区金沙江路 1519 弄'
                    }, {
                        date: '2016-05-03',
                        name: '王小虎',
                        address: '上海市普陀区金沙江路 1516 弄'
                    }]
                }
            },
            mounted:function(){
                console.log('12222');
            }
        };
    })();
</script>
注意:loadComponent的变化

交流加群:391053981

分享到: