【验证模型】3-7 「今晚,我想来点⋯⋯」动手做的餐点选择器进化!(下集)

昨天我们辛苦地完成了饲料清单的渲染与新增删除後,现在我们要将各个显示的部分与储存机制串连起来。

流程六:饲料清单之主画面取得饲料

要处理有关於画面中的资料第一个当然要找到的是 getTemplate 函式当中,而我们最主要是修改位於 .meal-text 元素当中的显示内容,并且我们将预设资料 currentMeal 对齐 mealList 饲料清单中的格式:

var currentMeal = {
  id: 1602386309696,
  content: '杜格'
}

function getTemplate (pagename){
  var template = {
    mainpage: `
      <div class="card-wrapper">
        <h1 class="card-title">Today's meal</h1>
        <div class="card-content">
            <p class="meal-text">${currentMeal.content}</p>
        </div>
        <div class="card-footer">
            <div class="btn btn-get">Get Meal</div>
        </div>
      </div>
    `,
    settingpage: `
      <div class="card-wrapper">
        <h1 class="card-title">Menu</h1>
        <div class="card-content">
            <ol class="meal-list">
                ${getMealListTemplate()}
            </ol>
        </div>
        <div class="card-footer">
            <div class="btn btn-add">Add Meal</div>
        </div>
      </div>
    `
  }
  return template[pagename]
}

接着由於 currentMeal 中的资料并不会平白无故地出现, 因此我们撰写了一个 getMeal 函式,主要用意是从 mealList 列表中随机选取一个餐点来替换:

function getMeal(){
  var random = Math.floor(Math.random() * mealList.length)
  return mealList[random]
}

如此一来我们就可以在理应触发取得随机餐点的地方,透过执行此函式来更新目前显示的资料。

如处理负责处理主页点击的 handleMainPageClick 函式:

function handleMainPageClick(e){
  if(e.target.className === 'btn btn-get'){
    currentMeal = getMeal()
    renderPage('mainpage')
  }
}

另外一个则是在刚进入页面时需要初始化的位置:

function initPage(){
  currentMeal = getMeal()
  renderPage('mainpage')

  // 略⋯⋯
}

到此步骤的程序码请参考这里

流程七:饲料清单之储存机制

现在我们已经完成大部分的功能了,而唯一还没做到的是将使用者所操作的饲料清单储存起来。

如同在浏览器储存机制中所介绍的一样,我们这里并没有要实作会员登入与验证来使用资料库做储存,因为并没有一定要使用这个验证的理由
,因此我们这里要暂时透过 localStorage 的机制来处理。

而要将原先的饲料清单改为 localStorage 做储存时,第一个是在初始化的时候,我们就要从 localStorage 上来取得资料:

var mealList = JSON.parse(localStorage.getItem('mealList')) || []

其中,要注意的地方在於第一次使用 localStorage 取得资料的时候很有可能里面是没有值的,因此我们必须要塞一个预设值 [] 进去。

另外,由於在 localStorage 中所储存的是字串资料,因此我们可以透过 JSON.parse() 来将字串转变成物件形式的资料。

接着,我们要调整的地方是与 mealList 有关的内容,而真正的核心调整位置会在於有更动 mealList 的地方,也就是新增与删除 mealList 资料的两只函式。

新增函式:

function addMeal(){
  var mealName = prompt('add meal')
  if(mealName){
    mealList.push({
      id: +new Date(),
      content: mealName
    })

    localStorage.setItem('mealList', JSON.stringify(mealList))
  }
}

删除函式:

function deleteMeal(e){
  var targetID = e.target.dataset.id
  mealList = mealList.filter(item => {
    return item.id !== +targetID
  })

  localStorage.setItem('mealList', JSON.stringify(mealList))
}

在这两只函式当中,由於 localStorage 最主要只接受字串形式的资料(有的浏览器允许存入非字串值,但不建议这麽做),因此我们要使用 JSON.stringify() 来将阵列转变成字串。

最後,将原先的用於在主画面显示饲料的 currentMeal 改成预设值:

var currentMeal = null;

并在 getTemplate 的该行做判断:

`<p class="meal-text">${currentMeal ? currentMeal.content : '请新增餐点' }</p>`

如此一来就完成了饲料清单保存的功能,到此步骤的所有程序码可参考这里

https://ithelp.ithome.com.tw/upload/images/20201013/20119062VT8lLb0YYH.png
这份餐点选择器虽然到这边算是大功告成了,不过需求方却表示不想要用这个产品了,因为猫全都要。
再次显示接有关猫猫的案子一定有风险,开发前应详阅猫奴公开说明书(?~

不过若有兴趣的话,这个选择器还可以再加入更多的功能,例如新增纪录近一个礼拜的餐点,甚至是以早上中午下午为划分的版本,还可以做出人与猫都可以用的共用版本。

而到目前为止,我们已经累积了不少的开发体验,此时部分的读者们在开发的过程中会发现,怎麽有时候程序码执行时跟我想像的不太一样?又或是对於函式中的作用域(scope)不太清楚,而导致变数的值一直捉馍不定?

接下来我们将从浏览器中的 JavaScript 执行环境(Execution Context)开始讲起,让你清清楚楚地知道 JavaScript 到底是怎麽运作的!


<<:  总结

>>:  Day[-1] 今天我想来点Kibana的TSVB

Day28-台湾菜鸟工程师除错之卷三

由於没有发布紧急事态宣言 但是为了救旅游业却推出了旅游补助方案(goto キャンペーン) 当时候的...

[Day 22] 实作 - 介面篇6

开始在主场景下做出一个类似技能快捷键的视窗 从Spriteset_Map开始 在ActionBatt...

[Day13] - 於 Django 中进行资料库设定

建立完环境之後,我们需要在Django的设定中,也告诉Django 资料库的资讯,Django 才会...

DAY09 资料前处理-异常值处理方法

昨天简单的介绍了缺失值的处理,今天来探讨异常值的处理方式,资料在蒐集的过程中除了有遗失的状况,当然也...

用 Python 畅玩 Line bot - 08:Audio message part2

既然可以将音档转为文字回传了,接下来我们可以尝试看看将收到的 Text message 转为音档去进...