backbonejs 演示案例不能很好地与堆栈片段中添加的本地存储一起使用

backbonejs demo case can't work well with localstorage added in stack snippet

我正在尝试使用堆栈片段工具将实时演示案例嵌入到我的 post 中。但是我发现当我把localstorage功能添加到demo case中时,它不能很好地工作。
所以我将我的问题简化为基本的 backbone 情况,以强调上述本地存储问题。
如果我去掉localstorage流程,demo可以运行很好地通过,但是如果添加了localstorage,那么它就不能很好地工作了。来自控制台的错误消息说 Failed to read the 'localStorage' property from 'Window': The document is sandboxed and lacks the 'allow-same-origin' flag.

有什么想法吗?

// A simple case

var Daymodel = Backbone.Model.extend({
 defaults : {
  day: 1,
 }
});

var DayCollection = Backbone.Collection.extend({
 model: Daymodel,
 localStorage: new Backbone.LocalStorage("test-simple")
});


// The view for each day panel
var DayView = Backbone.View.extend({
 tagName:"div",
 template: _.template( $('#eachday-template').html() ),
 initialize: function() {
  this.listenTo(this.model, "change", this.render);
 }, 
 render: function(){
  this.$el.html(this.template(this.model.toJSON()));
  return this;
 }
});
// The view for the entire application
var AppView = Backbone.View.extend({
  el: $('#todoapp'),
  events: {
 "click #add-firebase":"addToLocalhost"
  },
  initialize: function() {
    this.daylist = this.$("#container"); // the daylist to append to
    this.listenTo(this.collection, 'add', this.addOne);
 this.collection.fetch();
  },

  addOne: function(todo) {
 var view = new DayView({model:todo});
    this.daylist.append(view.render().el);

  },
  addToLocalhost: function(){
 this.collection.create({
  day : this.collection.length + 1,
 });
  }

});

// Create a function to kick off our BackboneFire app
function init() {
  // The data we are syncing from our remote Firebase database
  var collection = new DayCollection();
  var app = new AppView({ collection: collection });
}
// When the document is ready, call the init function
$(function() {
  init();
});
<div id="todoapp">
  <div id="container"></div>
  <button id="add-firebase">Add to Localstorage</button>
</div>
<script type="text/template" id="eachday-template">
 <h3 class="which-day"> day <%= day %></h3>
    <ul id="todo-list"></ul>
</script> 
 
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/underscore.js/1.8.3/underscore-min.js">
</script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/backbone.js/1.3.3/backbone-min.js">
</script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/backbone-localstorage.js/1.1.16/backbone.localStorage-min.js">
</script>

答案在您收到的错误消息中:"The document is sandboxed"。您不能乱用 localStorage,因为它是所有沙盒 iframe 文档的受限功能 ,除非 明确解除限制。

如果您查看页面源代码,您会看到 iframesandbox 属性选项。

<iframe name="d62428c9-4eba-3156-6ef7-8815d959a281" 
        sandbox="allow-modals allow-scripts" 
        class="snippet-box-edit" frameborder="0">

有关详细信息,请参阅 Play safely in sandboxed IFrames

The framed document is loaded into a unique origin, which means that all same-origin checks will fail; unique origins match no other origins ever, not even themselves. Among other impacts, this means that the document has no access to data stored in any origin's cookies or any other storage mechanisms (DOM storage, Indexed DB, etc.).

[...]

With the exception of plugins, each of these restrictions can be lifted by adding a flag to the sandbox attribute’s value. Sandboxed documents can never run plugins, as plugins are unsandboxed native code, but everything else is fair game:

  • allow-forms allows form submission.
  • allow-popups allows popups (window.open(), showModalDialog(), target="_blank", etc.).
  • allow-pointer-lock allows (surprise!) pointer lock.
  • allow-same-origin allows the document to maintain its origin; pages loaded from https://example.com/ will retain access to that origin's data.
  • allow-scripts allows JavaScript execution, and also allows features to trigger automatically (as they'd be trivial to implement via JavaScript).
  • allow-top-navigation allows the document to break out of the frame by navigating the top-level window.

对于allow-modalsAdd allow-modals to the sandbox of Stack Snippets给出了更多的细节:

Chrome blocks modal dialogs such as alert, confirm and prompt in sandboxed iframes unless allow-modals is set. This behavior became the default as of Chrome 46 and Opera 34.