我想使用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中似乎没有一个正确的项目架构。
答案 0 :(得分:3)
对于标签,请使用vue-router
每条路线在激活时都会加载单独的视图/组件。但是,这是预加载的,因为vue.js包文件包含呈现所需的所有代码。
Vue Lifecycle hooks
,例如created
和mounted
,通常用于在每个视图中执行设置或获取其他数据。
看起来你的例子足够同质,单个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();
}
那就是它