英文:
How to Call A Function inside a Ko.Observable Array? Knockout
问题
I'm learning more about knockout.js. I have built a little dialogue system using it and it works! One thing I'd like to do is have a function that can jump from the data after a button is pressed to run a new function.
How the data below works is there's text that shows, the image changes, and the choices are buttons that when pressed go to the next story/data set. In this case, it goes back to the start (storyLink 1).
Here's a snippet of my data with said function:
 "106":{"text":"[The game ended you Died.]",
  "image": "death face.gif",
  "choices":[{"choiceText":"Oops.","storyLink":"1", function () { console.log("lmao");}}]},
Here is a snippet of the HTML:
    <div data-bind="with: activeStory">
    <img data-bind="attr: { src: image }">
<button id="button" class="Button-data imgLink" onclick="handleClick()" data-bind="click: $root.onChoice, text: choiceText"></button>
Here's a bit of the view model. I did not include the part where the bindings are applied, as that's a chunk of code that takes the text above and creates a typewriter effect:
var activeStoryId = ko.observable(1)
  .extend({ notify: "always" });
  
  var activeStory = ko.pureComputed(() => 
  story[activeStoryId()] ?? 
  { text: "[There was an Error.]", choices: [{ choiceText: "Back to start", storyLink: 1 }] }
);
var onChoice = ({ storyLink }) => activeStoryId(storyLink);
    // Apply bindings
      registerBinding();
      ko.applyBindings({
        onChoice,
        activeStory
      });
This isn't running, and I assume this is because of a syntax error or perhaps I need to call it a different way. I keep finding my syntax is wrong when using knockout, so any insight would be great!
Edit 2:
Here's an example of what I am trying to figure out:
let a = 1;
let b = 2;
let arr = [
  a,
  b,
  function () {
    return a + b;
   },
  ];
console.log(arr[2]()); // returns 3
console.log(typeof arr); // returns object
In this code, there's a function that runs inside the array. It doesn't currently work in my code when I try to do this.
英文:
I'm learning more about knockout.js. I have built a little dialogue system using it and it works! One thing I'd like to do, is have a function that can jump from the data after a button is pressed to run a new function.
How the data below works is there's text that shows, the image changes, and the choices are buttons that when pressed go to the next story/data set. In this case it goes back to the start (storyLink 1).
Here's a snippet of my data with said function:
 "106":{"text":"[The game ended you Died.]",
  "image": "death face.gif",
  "choices":[{"choiceText":"Oops.","storyLink":"1", function () { console.log("lmao");}}]},
here is a snippet of the html:
    <div data-bind="with: activeStory">
    <img data-bind="attr: { src: image }">
<button id ="button" class ="Button-data imgLink" onclick = "handleClick()" data-bind="click: $root.onChoice, text: choiceText"></button>
here's a bit of the view model. I did not include the part where the bindings are applied as that's a chunk of code that takes the text above and creates a typewriter effect.
var activeStoryId = ko.observable(1)
  .extend({ notify: "always" });
  
  var activeStory = ko.pureComputed(() => 
  story[activeStoryId()] ?? 
  { text: "[There was an Error.]", choices: [{ choiceText: "Back to start", storyLink: 1 }] }
);
var onChoice = ({ storyLink }) => activeStoryId(storyLink);
    // Apply bindings
      registerBinding();
      ko.applyBindings({
        onChoice,
        activeStory
      });
This isn't running, and I assume this is because of a syntax error or perhaps I need to call it a different way. I keep finding my syntax is wrong when using knockout so any insight would be great!
I tried adjusting the syntax based on Javascript arrays and I'm still missing something. I haven't found a solution that works yet.
Edit 2:
Here's an example of what I am trying to figure out:
let a = 1;
let b = 2;
let arr = [
  a,
  b,
  function () {
    return a + b;
   },
  ];
console.log(arr[2]()); // return 3
console.log(typeof arr); // returns object
In this code, there's a function that runs inside the array. It doesn't currently work in my code when I try to do this.
答案1
得分: 1
Here is the translated content:
我认为我理解了你想要做什么。希望这会有所帮助。
var story = {
   "1": {
      "text": "[游戏结束,你死了。]",
      "image": "death_face.gif",
      "choices": [{
         "choiceText": "糟糕。",
         "storyLink": "1"
      }, {
         "choiceText": "差一点……",
         "storyLink": "2"
      }]
   },
   "2": {
      "text": "[开始新故事]",
      "image": "happy_face.gif",
      "choices": [{
         "choiceText": "我们走吧。",
         "storyLink": "1"
      }, {
         "choiceText": "也许下次吧。",
         "storyLink": "2"
      }]
   }
};
function ViewModel() {
   var self = this;
   self.activeStoryId = ko.observable(1)
      .extend({
         notify: "always"
      });
   self.activeStory = ko.pureComputed(() =>
      story[self.activeStoryId()] ?? {
         text: "[发生了错误。]",
         choices: [{
            choiceText: "回到起点",
            storyLink: 1
         }]
      }
   );
   self.onChoice = function(item) {
      console.log(item);
      self.activeStoryId(item.storyLink);
   }
}
var vm = new ViewModel();
ko.applyBindings(vm);
如果我理解正确,如果你想要将函数作为数据的一部分传递,你可以像下面这样做。拥有一个在你的选择对象之间相同的函数名称,然后你可以将该函数对象传递给click绑定以运行它。
var story = {
   "1": {
      "text": "[游戏结束,你死了。]",
      "image": "death_face.gif",
      "choices": [{
         "choiceText": "糟糕。",
         "storyLink": "1",
         "choiceCommand": function () { console.log("storylink 1-1") }
      }, {
         "choiceText": "差一点……",
         "storyLink": "2",
         "choiceCommand": function () { console.log("storylink 1-2") }
      }]
   },
   "2": {
      "text": "[开始新故事]",
      "image": "happy_face.gif",
      "choices": [{
         "choiceText": "我们走吧。",
         "storyLink": "1",
         "choiceCommand": function () { console.log("storylink 2-1") }
      }, {
         "choiceText": "也许下次吧。",
         "storyLink": "2",
         "choiceCommand": function () { console.log("storylink 2-2") }
      }]
   }
};
希望这对你有所帮助!
英文:
I think I understand what you are tying to do. Hopefully this will help.
<!-- begin snippet: js hide: false console: true babel: false -->
<!-- language: lang-js -->
var story = {
  "1": {
    "text": "[The game ended you Died.]",
    "image": "death_face.gif",
    "choices": [{
      "choiceText": "Oops.",
      "storyLink": "1"
    }, {
      "choiceText": "So close...",
      "storyLink": "2"
    }]
  },
  "2": {
    "text": "[Start New Story]",
    "image": "happy_face.gif",
    "choices": [{
      "choiceText": "Away we go.",
      "storyLink": "1"
    }, {
      "choiceText": "Maybe next time",
      "storyLink": "2"
    }]
  }
};
function ViewModel() {
  var self = this;
  self.activeStoryId = ko.observable(1)
    .extend({
      notify: "always"
    });
  self.activeStory = ko.pureComputed(() =>
    story[self.activeStoryId()] ?? {
      text: "[There was an Error.]",
      choices: [{
        choiceText: "Back to start",
        storyLink: 1
      }]
    }
  );
  self.onChoice = function(item) {
    console.log(item);
    self.activeStoryId(item.storyLink);
  }
}
var vm = new ViewModel();
ko.applyBindings(vm);
<!-- language: lang-html -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.4.2/knockout-min.js"></script>
<div data-bind="with: activeStory">
  <h2 data-bind="text: text"></h2>
  <img data-bind="attr: { src: image }">
  <!-- ko foreach: choices -->
  <button id="button" class="Button-data imgLink" data-bind="click: $root.onChoice, text: choiceText"></button>
  <!-- /ko -->
</div>
<!-- end snippet -->
EDIT
If I understand correctly, if you want to be passing functions as part of your data, I would do something like the following.  Have a function name that is the same across your choice objects. then you can pass that function object to the click binding for it to run.
<!-- begin snippet: js hide: false console: true babel: false -->
<!-- language: lang-js -->
var story = {
  "1": {
    "text": "[The game ended you Died.]",
    "image": "death_face.gif",
    "choices": [{
      "choiceText": "Oops.",
      "storyLink": "1",
      "choiceCommand": function () { console.log("storylink 1-1")}
    }, {
      "choiceText": "So close...",
      "storyLink": "2",
      "choiceCommand": function () { console.log("storylink 1-2")}
    }]
  },
  "2": {
    "text": "[Start New Story]",
    "image": "happy_face.gif",
    "choices": [{
      "choiceText": "Away we go.",
      "storyLink": "1",
      "choiceCommand": function () { console.log("storylink 2-1")}
    }, {
      "choiceText": "Maybe next time",
      "storyLink": "2",
      "choiceCommand": function () { console.log("storylink 2-2")}
    }]
  }
};
function ViewModel() {
  var self = this;
  self.activeStoryId = ko.observable(1)
    .extend({
      notify: "always"
    });
  self.activeStory = ko.pureComputed(() =>
    story[self.activeStoryId()] ?? {
      text: "[There was an Error.]",
      choices: [{
        choiceText: "Back to start",
        storyLink: 1
      }]
    }
  );
  self.onChoice = function(item) {
    console.log(item);
    self.activeStoryId(item.storyLink);
  }
}
var vm = new ViewModel();
ko.applyBindings(vm);
<!-- language: lang-html -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.4.2/knockout-min.js"></script>
<div data-bind="with: activeStory">
  <h2 data-bind="text: text"></h2>
  <img data-bind="attr: { src: image }">
  <!-- ko foreach: choices -->
  <button id="button" class="Button-data imgLink" data-bind="click: choiceCommand, text: choiceText"></button>
  <!-- /ko -->
</div>
<!-- end snippet -->
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。


评论