gpt4 book ai didi

ajax - knockout SPA Ajax 加载模板

转载 作者:行者123 更新时间:2023-12-02 01:30:33 26 4
gpt4 key购买 nike

我对处理这种情况的可能性感到迷失:假设我们有以下限制:

  • knockout
  • 使用 Sammy.js 进行 SPA - 通过 Ajax 加载 Html

我的页面:

+-------------------------------+
| #navigation |
+---------+---------------------+
| #sidebar| #content |
| | |
| | |
| | |
+---------+---------------------+

目前,我有一个 appViewModel 来处理我网站的所有共享元素的数据绑定(bind):#navigation 和 #sidebar。这个 appViewModel 在我网站的每个页面上都使用了 observable。

appViewModel = function () {
var self = this;
self.sidebarItemArray = ko.observableArray([x, y, z]);
self.currentRoute = ko.observable();

...

self.updateView = function(path, currentRoute) {
return $.get(path, function( data ) {
var $data = $(data);
// Updates #content, TITLE and update the currentRoute observable.
$( '#content' ).replaceWith($data.find('#content'));
document.title = $data.filter('title').text();
self.currentRoute(currentRoute);
}, 'html');
}

Sammy(function() {
this.get(':link'', function() {
self.updateView(this.path, this.params.link);
});
}).run();
}
ko.applyBindings(new appViewModel());

现在,假设 #content 是通过 Ajax 调用加载的一段 DOM。每次用户单击 #navigation 或 #sidebar 中的链接时,Sammy.js 都会拦截它,然后更新 #content。问题在于#content 中的新 DOM 本身具有数据绑定(bind)。

1) 首先,我应该在 #content 上使用 html 数据绑定(bind)、replaceWith(如上所述)还是使用 template 绑定(bind)自定义函数来获取模板?(http://knockoutjs.com/documentation/template-binding.html#note-5-dynamically-choosing-which-template-is-used)? 这里的最佳实践是什么

2)Sammy 是否应该像文档或其他地方一样存在于 appViewModel 中就可以了?

3) updateView方法完成后,如何绑定(bind)新的DOM?像下面这样?是否存在重新绑定(bind)某些 DOM 的风险,因为 ko.applyBindings 已经在没有第二个参数的情况下被调用了?

ko.applyBindings(new routeSpecificViewModel() , document.getElementById("content")); 

非常感谢您的帮助。

最佳答案

一个简单的解决方案是使页面的 View 模型成为可观察的,并按需加载它。使用变量来记录是否已调用 ko.applyBindings。 Knockout-spa 框架的示例:

/*! knockout-spa (https://github.com/onlyurei/knockout-spa) * Copyright 2015-2016 Cheng Fan * MIT Licensed (https://raw.githubusercontent.com/onlyurei/knockout-spa/master/LICENSE) */

define(['app/shared/root-bindings', 'framework/page-disposer', 'ko', 'sugar'], function (
RootBindings, PageDisposer, ko) {

var initialRun = true;

var Page = {
init: function (name, data, controller, path) {
Page.loading(false);

name = name.toLowerCase();

if ((Page.page().name == name) && (Page.page().data == data)) { // if the requested page is the same page, immediately call controller without going further
if (controller) {
controller(data);
}

document.title = Page.title();

if (Page.initExtra) {
Page.initExtra(name, data, controller);
}

return data;
}

var autoDispose = (Page.page().data.dispose && Page.page().data.dispose(Page)) || true; // if the requested page is not the same page, dispose current page first before swap to the new page
if (autoDispose !== false) {
// auto-dispose page's exposed observables and primitive properties to initial values. if not desired, return
// false in dispose function to suppress auto-disposal for all public properties of the page, or make the
// particular properties private
PageDisposer.dispose(Page.page().data);
}

PageDisposer.init(data); //store initial observable and primitive properties values of the page
var initialized = (data.init && data.init(Page)) || true; // init view model and call controller (optional) before template is swapped-in
if (initialized === false) {
return false; // stop initialization if page's init function return false (access control, etc.)
}
if (controller) {
controller(data);
}

Page.pageClass([name, ('ontouchstart' in document.documentElement) ? 'touch' : 'no-touch'].join(' '));
Page.page({
name: name,
data: data,
path: path
}); // to test if template finished rendering, use afterRender binding in the template binding

document.title = Page.title();

if (Page.initExtra) {
Page.initExtra(name, data, controller); // useful for common init tasks for all pages such as anaylitics page view tracking, can be set in RootBindings
}

if (initialRun) {
ko.applyBindings(Page, document.getElementsByTagName('html')[0]); // apply binding at root node to be able to bind to anywhere
initialRun = false;
}

return data;
},
page: ko.observable({
name: '', // name of the page - auto-set by the framework, no need to worry
data: {
init: function () {}, // preparation before the page's template is rendered, such as checking access control, init/instantiate modules used by the page, etc.
dispose: function () {} // properly dispose the page to prevent memory leaks and UI leftovers (important for SPA since page doesn't refresh between page views) - remove DOM element event listeners, dispose knockout manual subscriptions, etc.
}
}),
pageClass: ko.observable(''),
loading: ko.observable(false),
title: function () {
return Page.page().name.titleize(); // override in RootBindings as needed
}
};

Object.merge(Page, RootBindings); // additional root bindings as needed by the app

return Page;

});

一个迷你但成熟的 SPA 框架,构建在 Knockout、Require、Director、jQuery、Sugar 之上。 https://github.com/onlyurei/knockout-spa

现场演示:https://knockout-spa.mybluemix.net

关于ajax - knockout SPA Ajax 加载模板,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26806033/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com