requirejs、vue、vuex、vue-route的结合使用,您认为可行吗?

     在五一节之前和一网友讨论前端技术时,对方提到vue、vue-route如果配合requirejs应用。当时的我没有想得很明白,也没能这位网友一个准确的回复,但我许诺于他五一研究后给他一个回复。本是一天的研究却被我搞成了研究了一周,这拖延症。。。

闲话少数,进入正题

一、示例代码说明

代码结构说明:

  1. modules(存放的为组件,主要是模板与Js对象分成两个文件来写)
    1. route:测试子路由的组件
    2. title:就是一个简单的显示文字的组件
  2. app.js:核心类,提供vue的创建、以前modules组件加载的方法等
  3. chart.js:模拟的一个业务模块
  4. index.html:页面文件
  5. layout.css:整体样式文件(测试require加入样式文件)
  6. main.js:requirejs的配置文件(也是入口文件) 丑陋的效果图:

此示例没有样式,只是为了验证require如何加载一个vue组件,以子路由的动态注入的能力,示例代码下载

二、从.vue文件入手

      一个.vue文件可以包含模板、Js类、样式(可以不要)等三块。但我们通过vue的官网可以知道,vue提供了compile对象方法,可以把模板编译成VNode。并且我们通过webpack打包后生成的文件可以看出模板与Js类是混淆在一起了。这也就说明vue的组件就是一个Js对象。如下图所示:

三、requirejs对vue、vuex和vue-route的引入

     引入这三个都很容易,并将这三个注入到Vue对象也是相对简单的,难道的是需要解决动态注入向vue-route实例注入路由,以及vuex的动态加入一个数据模块的能力。好在这两点官网都给出了解决方案:

  • vue-route如何动态注入路由 根据官网帮助文档说明,存在addRoutes方法,向路由实体动态注入路由
  • vuex模块动态注入 也是根据官网帮助文档提示有registerModule方法实现。
  • 实现的部分代码: 初始化Vue对象
apt.init = function(){
    this.store = Object.create({
        modules:{}
    });        
    this.Vue.use(VueRouter);
    this.Vue.use(Vuex);
    this.router = new VueRouter(); 
    this.store = new this.Vuex.Store(this.store);
}

首先提供一个init方法,对Vue对象进行一些初始化,也就是把Vuex、vue-route都注入到Vue对象中。在这里我把创建的vuex和vue-route的实例都放到this对象,方便后面提供给组件注册实使用。 创建Vue实例:

apt.createVue = function(){
    this.vue = new this.Vue({
        store: this.store,
        router: this.router,
        computed: {
            childs: function(){
                if(!this.$store.state.router) return null;
                return this.$store.state.router.childs;
            }
        }
    });
    return this.vue;
}

只创建vue对象,没有进行mount。 为其他模块提供的上下文:

apt.createContext = function(){
    return {
        Vue: this.Vue,
        router: this.router,
        $vue: this.vue
    };
}

四、如何通过require加载html和js方式的组件

从项目结构图中可以看出在modules文件夹中定义了两个组件,分别是:routet和title,而他们的模板则是一个html文件。以下是这类组件如何加载的代码:

apt.acquire = function(path){
    var arrayPath;
    if(!this.isArray(path)){
        arrayPath = [path];
    }else{
        arrayPath = path;
    }
    var promise = this.dfd(function(dfd){
        require(arrayPath,function(){
            dfd.resolve(Array.prototype.slice.call(arguments));
        },function(error){
            dfd.reject(error);
        });
    }).promise();
    return promise;
}

apt.createComponent = function(componentName){
    //可以重载,读取.vue的文件
    var path = this.$modulePrefix + componentName,
    html = 'text!' + path + '/index.html',
    js = path + '/index.js',
    self = this;
    var promise = this.acquire([html,js]);
    promise.done(function(result){
        var obj = result[1], content = result[0];
        obj.template = content;
        obj.__path__ = path;
        self.$components.push(obj);
    });
    return promise;
}

说明: acquire:提供通过require加载JS或者是html等文件的方法,并返回一个promise,这样就方便调用者使用。 createComponet:会根据调用传入的名称在modules文件夹中找出对应的js和html文件,然后调用acquire加载组件。

五、main.js是这样引用的

提供注册全局组件方法

apt.registerGlobalComponents = function(componentNames){
    var gloadComponet = componentNames, self = this;
    var promises = gloadComponet.map(function(data,index){
        return self.createComponent(data);
    });
    var dfd = this.dfd();
    $.when.apply(null, promises).done(function(){
        var _router = [];
        self.$components.forEach(function(data,index){
            self.Vue.component(data.name, data);
            _router.push({
                path: '/' + data.name,
                component: data
            });
        });
        self.router.addRoutes(_router); //全局注册都注册为路由
        dfd.resolve(_router);
    });
    return dfd.promise();
}

main.js中的引用

var _app = app.createApp();
_app.registerGlobalComponents(['title', 'route']).done(function(){
    var vue = _app.createVue();
    var cxt = app.getVue().createContext();
    var r = {
        state: {
            childs: []
        },
        mutations: {
            childs: function(state, data){
                state.childs = data;
            }
        },
        actions: {
            childs: function(state, data){
                state.commit('childs', data);
            }
        }
    }
    vue.$store.registerModule('router', r);
    vue.$mount('#app');
});

说明:

  1. 创建App的一个实例;
  2. 注册全局的组件:title、route;
  3. 注册完成后创建vue实例,并且向实例的vuex注入二级路由展示的模块

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏九彩拼盘的叨叨叨

CSS拓展语言:Sass介绍

CSS拓展语言出现的原因是,CSS自身支持的功能能有限(如不支持变量,条件控制,循环等编程元素),并不满足我们想要的一些功能。而CSS拓展语言支持CSS不支持的...

1082
来自专栏Jerry的SAP技术分享

善用Object.defineProperty巧妙找到修改某个变量的准确代码位置

我今天的工作又遇到一个难题。前端UI右下角这个按钮被设置为"禁用(disabled)"状态。

1541
来自专栏java一日一条

10+ 实用的 JavaScript 调试小技巧

除了console.log,debugger就是另一个我很喜欢的快速调试的工具,将debugger加入代码之后,Chrome会自动在插入它的地方停止,很像C或者...

751
来自专栏ShaoYL

UIViewController的生命周期及iOS程序执行顺序

29511
来自专栏Aloys的开发之路

Linux乱码问题解决方案

linux系统中文件名内容为urf8编码, windows系统中文件名默认为gbk编码, 多数文档使用gbk编码,系统采用utf8编码 无中文输入法导致的乱码 ...

4778
来自专栏林冠宏的技术文章

关于在用curl函数post网页数据时,遇上表单提交 type为submit 类型而且没有name和id时可能遇到的问题及其解决方法

curl函数库实现爬网页内容的链接在 http://www.cnblogs.com/linguanh/p/4292316.html 下面这个是没有name和id...

2077
来自专栏Crossin的编程教室

【编程课堂】selenium 祖传爬虫利器

一些网页,比如微博,只有在登录状态才能进行页面的访问,或者对数据有比较复杂的验证和保护,直接通过网络请求进行登录并获取数据就会比较麻烦。这种时候,就该本篇的主角...

2704
来自专栏精讲JAVA

14个你可能不知道的JavaScript调试技巧

以更快的速度和更高的效率来调试JavaScript 熟悉工具可以让工具在工作中发挥出更大的作用。尽管江湖传言 JavaScript 很难调试,但如果你掌握了几个...

2066
来自专栏做全栈攻城狮

全栈工程师必备:安卓移动端手机开发,第六课

本系列课程 致力于老手程序员可以快速入门学习安卓开发。系统全面的从一个.Net程序员的角度一步步学习总结安卓开发。

1343
来自专栏猿人谷

有趣的Linux命令行效果

有趣的Linux命令行功效 1. Linux"sl"命令行 尽管"sl"代表了"蒸汽机机头",但它是用来提醒那些命令行控们别把"ls"打成了"sl"。让我们看看...

2568

扫码关注云+社区

领取腾讯云代金券