多个vue js实例与组件,ajax标签

时间:2018-02-23 14:22:22

标签: javascript ajax vue.js bootstrap-tabs

我想使用vue js渲染ajax标签。对于每个选项卡,ajax请求从api获取模板+数据。

所以这些是标签:

<div id="tabs">
  <ul class="nav nav-tabs">
    <li class="active"><a href="#tab1" role="tab" data-toggle="tab">Tab1</a></li>
    <li><a href="#tab2" ajax-url="/tab2" role="tab" data-toggle="tab">Tab2</a></li>
    <li><a href="#tab3" ajax-url="/tab3" role="tab" data-toggle="tab">Tab3</a></li>
    <li><a href="#tab4" ajax-url="/tab4" role="tab" data-toggle="tab">Tab4</a></li>
  </ul>

  <div class="tab-content">
    <div role="tabpanel" class="tab-pane active" id="tab1"></div>
    <div role="tabpanel" class="tab-pane" id="tab2"></div>
    <div role="tabpanel" class="tab-pane" id="tab3"></div>
    <div role="tabpanel" class="tab-pane" id="tab4"></div>
  </div>
</div>

<script>
$('#tabs').on('shown.bs.tab', function (event) {
   var url = event.target.getAttribute("ajax-url");
   // fetch template and data..
   // init vue instance for the new tab
})
</script>

我应该如何将vue整合到此?每个选项卡或组件的单独vue实例?我还需要支持预加载一些标签 由于我需要按需初始化vue实例,因此我不确定管理它的好方法是什么。对于角度,我会为每个选项卡定义ng-controller。但是在vue.js中似乎没有一个正确的项目架构。

2 个答案:

答案 0 :(得分:3)

对于标签,请使用vue-router

每条路线在激活时都会加载单独的视图/组件。但是,这是预加载的,因为vue.js包文件包含呈现所需的所有代码。

Vue Lifecycle hooks,例如createdmounted,通常用于在每个视图中执行设置或获取其他数据。

看起来你的例子足够同质,单个vue实例可以处理所有工作(不需要jQuery / AJAX)。

如果您的用例有很大不同,有时构建多个单独的组件会更有效,每个组件都编译成自己的JS文件(通常使用Webpack&#39; entry&#39 ;设置)。

<强>更新

有一种方法可以使用CLI捆绑Vue组件,请参阅:Compile .vue file into .js file without webpack or browserify

请注意,每个组件都可以使用el属性安装单独的标签,该属性与Angular&#ng; ng-controller&#39;指令:

new Vue({
  el: '#tab1',
  data () {
    return {
      obj
    }
  }
})

但是,我认为你要做的是从Vue外部控制Vue实例(即:使用jQuery)。可能不建议这样做。

如果你决定使用Webpack,你仍然可以使用Bootstrap。各种方法集成Bootstrap,我个人建议导入SCSS。但您的里程可能会有所不同但是不要被推迟,有很多在线资源可以让你继续前进。

答案 1 :(得分:1)

如果您不想要vue-router,则必须使用单独的Vue实例。 但它会导致一些内存泄漏一些问题所以对一些人来说.. 当你点击一个标签时你会发出一个ajax请求,你必须首先销毁当前的Vue实例..然后将数据添加到dom

 let app =  new Vue({
            el:  '#app',

        })
// doo other stuff
    $.ajax({
      // ajax settings
      success: function(data){
       // here you should destroy the Old Vue instance otherwise it will make issues
        app.$destroy()
        $('body').html(data);
      }
    })

我建议你制作一个小的javascript插件.. 当点击一个链接时,它将获取链接的url执行ajax请求,并在每次请求时将数据提供给页面,它将触发一个回调..在那里你破坏旧的新实例.. 对于某种类型的加载器,您可以在ajax请求之前使用另一个回调来显示页面加载器或其他东西..

我在我的一个项目中使用过这种技术..我用hquery ajax创建了一个插件... 这是......

    import $ from 'jquery';
import anime from 'animejs';
export let Loader = (function(window , document , undefined){

    class Loader{

        constructor(options = null){
            this.options = Object.assign({ pageProgressBar : false , pageProgressBarDuraion: 2000 } , options);
            this.functions = [];
            this.xhr = null;
            this.routes = this.options.routes || [];

            window.addEventListener('load' , this.init.bind(this));
        }        
        init(){

            if(this.options.container)
                this.$container = $(this.options.container).length ? $(this.options.container) : $(document.body)
            else            
                this.$container = $(document.body)    


            this.functions['popstate'] =  this.onPopState.bind(this);
            window.addEventListener('popstate' , this.functions['popstate'] );

            this.functions['handleLinks'] = this.handleLinks.bind(this);
            window.addEventListener('click' , this.functions['handleLinks']);
        }
        pushHistory(type , url){
            var state = {url : url , type : type};
            window.history.pushState(state , '' , url);
        }
        onPopState(e){
            var state = e.state;

            if(state == null)
                return true;

            this.loadUrl(state.url)
        }
        handleLinks(e){
            if(!e.target.matches('[ajax-link]'))
                return ;
            e.preventDefault();

            var url = e.target.href;
            var self = this;

            this.loadUrl(url).then(function(){            
                self.pushHistory('get' , url);
            });
        }

        load(url)
        {
            let self = this;
            return new Promise(function(resolve , reject){
                self.loadUrl(url).then(function(){

                    self.pushHistory('get' , url);
                    resolve();
                });    
            });
        }


        loadUrl(url){
            var isError = true;
            if(this.xhr)
            {
                isError = false;
                if(this.options.onAbort)
                    this.options.onAbort();
                this.xhr.abort();
                if(this.options.pageProgressBar)
                    restartProgressBar();
                this.xhr = null;
            }

            var route = this.getMatchingRoute(url);
            if(route)
            {
                if(route.beforeLoad)
                    route.beforeLoad();
            }

            if(this.beforeLoading)
                this.beforeLoading();


            var self = this;
            return new Promise(function(resolve , reject){
               self.xhr = $.ajax({
                    url : url,
                    type: 'get',
                    cache : false,
                    beforeSend (xhr){

                        if(self.options.onLoading)
                            self.options.onLoading(xhr);

                        if(self.options.pageProgressBar)
                            startProgressBar( self.options.pageProgressBarDuration );
                    },
                    success (data){

                        self.$container.html(data);
                        self.xhr = null;
                        resolve();

                        if(route && route.afterLoad)
                            route.afterLoad();

                        if(self.options.onLoaded)
                            self.options.onLoaded(data);
                        if(self.options.pageProgressBar)
                            endProgressBar();
                    },
                    error (response){
                        if(response.response)
                            window.location = url;
                    },
                });
            });
        }
        reload(){
            this.loadUrl(window.location.href);
        }
        getMatchingRoute(url){
            if(this.routes)
            {   
                for(let i = 0; i< this.routes.length ; i++)
                {
                    var route = this.routes[i];
                    if(url.indexOf(route.route) >= 0 ){
                        return route;
                    }
                };
            }
            return null;
        }
        destory(){
            window.removeEventListener('popstate' , this.functions['popstate'] );
        }
    }
    return Loader;



    // Provate progressbar methods
    var $pageProgressBar = null;

    function restartProgressBar(){
        $pageProgressBar.remove();
        anime.remove($pageProgressBar[0]);
    }
    function startProgressBar( duration = 3000){
        $pageProgressBar = $('<div>').addClass('page-progressbar')
        $('body').append($pageProgressBar)

        anime({
            targets: $pageProgressBar[0],
            width: '70%',
            easing : 'easeInOutQuad',
            duration : 3000
        });
    }
    function endProgressBar(){
        anime.remove($pageProgressBar[0]);
        var $prog = $('.page-progressbar');
        $prog.css({ width: '100%' , transition :".35s all" , 'webkit-transition' : ".35s all" });
        setTimeout(()=>{
            $prog.css({ opacity: '0'});
            setTimeout( () => $pageProgressBar[0].remove() , 200);
        },350);
    }


}(window , document , undefined));

它有一些进度条和其他你可以删除的东西来修改它 现在你所要做的就是

window.Loader = new Loader({
// tell it the tag you want to put data in 
container :"#app-data",
})

然后将ajax-link属性添加到您的标签链接的案例中的任何链接 它将拉出网址并将内容放入您指定的容器中 还有一些回电 你可以添加Loader.beforeLoading = function(){ app.$destroy(); } 那就是它

相关问题