留言板 plugin


Posted by s103071049 on 2021-07-12

拿一段 code 放著,在頁面上會插入 code。

用 webpack 做 plugin,因為 webpack 可以把東西包成 library。

改成 JS

因為之後內容都只有 JS,所以要將全部東西都改成 JS。所以 HTML、CSS 都要拿掉。

終極目標:BODY 為空,所有東西都以 JS 動態新增

先拿掉 callback function

先將這個拿掉,解放裡面的東西,現在裡面只有 getComments()

$(document).ready( () => {})

宣告初始化 function

如果在另外一個頁面,

假設最後打包出的是 commentPlugin,傳一些參數他就回給我一個留言板。

commentPlugin.init({
  apiUrl: '',
  siteKey: 'anglea',
  containerSelector: '#comments' //將plugin放在哪
})

要放到外面是因為其他 function 也要用到,另外 selector 本身不會用到所以先宣告為 null

let siteKey = ''
let apiUrl = ''
let containerElement = null
function init(options) {
  siteKey = options.siteKey
  apiUrl = options.apiUrl
  containerElement = $(options.container)
}

呼叫 init function,做完會解釋

init({
  siteKey: 'angela',
  apiUrl: 'http://mentor-program.co/mtr04group3/s103071049/week12/hw1/api_comments.php',
  containerElement: '.comments-area'
})

將留言區變成用 JS 產生,

將 HTML 變成 formTemplate,目的是為了之後的動態產生。

<form class="add-comment-form">
   <label for="form-nickname" class="form-label">暱稱</label>
   <input type="text" class="form-nickname" id="form-nickname" name="nickname">
  <div class="mb-3">
    <label for="comments__block" class="form-label">留言內容</label>
    <textarea class="form-control" id="comments__block" rows="3" name="content"></textarea>
  </div>
  <button type="submit" class="btn btn-primary">送出留言</button>
</form>
<div class="comments__list">
</div>
const formTemplate = `
<div>
      <form class="add-comment-form">
         <label for="form-nickname" class="form-label">暱稱</label>
         <input type="text" class="form-nickname" id="form-nickname" name="nickname">
        <div class="mb-3">
          <label for="comments__block" class="form-label">留言內容</label>
          <textarea class="form-control" id="comments__block" rows="3" name="content"></textarea>
        </div>
        <button type="submit" class="btn btn-primary">送出留言</button>
      </form>
      <div class="comments__list">
      </div>
</div>
`

有了 formTemplate,將他用 js 方式動態放上

function init(options) {
  siteKey = options.siteKey
  apiUrl = options.apiUrl
  containerElement = $(options.container)
  containerElement.append(formTemplate)
}
<body>
    <div class="container">
      <div class="comments-area"></div>
    </div>
</body>

因為執行順序的問題,放置位置導致 dom 的物件還沒載入完。
解決方式:
方式一、將 <script src="index.js"></script> 放到 </body> 前。
方式二、dom 的結構準備好後,才做初始化。

$(document).ready( () => {
  init({
    siteKey: 'angela',
    apiUrl: 'http://mentor-program.co/mtr04group3/s103071049/week12/hw1/api_comments.php',
    containerSelector: '.comments-area'
  })
})

將這一堆放到 init

  getComments()
  $('.comments__list').on('click', '.load-more', () => {
    getComments()
  })
  $('.add-comment-form').submit( (e) => {
    e.preventDefault()
    const datas = {
      'site_key': 'angela',
      'nickname' : $('input[name=nickname]').val(),
      'content' : $('textarea[name=content]').val(),
    }
    $.ajax({
      type: 'POST',
      url: 'http://mentor-program.co/mtr04group3/s103071049/week12/hw1/api_add_comments.php',
      data: datas
    }).done(function(data) {
      if (!data.ok) {
        alert(data.msg)
        return
      }
      $('input[name=nickname]').val(''),
      $('textarea[name=content]').val('')
      const commentToDom = $('.comments__list')
      appendCommentToDom(commentToDom, datas, true)
    })
  })

調整所有相關地方的 url

 url: `${apiUrl}/api_add_comments.php`

透過 siteKey 來區分不同的網站。


css 動態放入 js

參照文件

var css = 'h1 { background: red; }',
    head = document.head || document.getElementsByTagName('head')[0],
    style = document.createElement('style');

head.appendChild(style);

style.type = 'text/css';
if (style.styleSheet){
  // This is required for IE8 and below.
  style.styleSheet.cssText = css;
} else {
  style.appendChild(document.createTextNode(css));
}

所以原本的 css 這樣改

const css = `
  .card {
      margin-top: 12px;
      margin-bottom: 12px;
  }
  body {
      padding: 12px;
  }
`

function init(options) {
  siteKey = options.siteKey
  apiUrl = options.apiUrl
  containerElement = $(options.containerSelector)
  containerElement.append(formTemplate)
  commentDom = $('.comments__list')
  const styleElement = document.createElement('style') // 新建立一個 style 元素
  styleElement.type = 'text/css' // 指定 styleElement 的 type
  styleElement.appendChild(document.createTextNode(css)
  document.head.appendChild(styleElement) // 將 styleElement 給放進去
// 下面 code 同之前,所以略
}

變成 js 後就可以搬到 webpack 去。先做 webpack 的環境設置,做完後將 js 檔案放到 src 中。在 src 中新增檔案 api.js,先來模組化原本的檔案。

api.js 中加入這兩個 function

export function getComments(apiUrl, siteKey, before, cb) {
  let url = `${apiUrl}/api_comments.php?site_key=` + siteKey
  if (before) {
    url += '&before=' + before
  }
  $.ajax({
  url,
  }).done(function(data) {
    cb(data)
  })
}

export function addComments(apiUrl, siteKey, data, cb) {
  $.ajax({
    type: 'POST',
    url: `${apiUrl}/api_add_comments.php`,
    data
  }).done(function(data) {
    cb(data)
  })
}

在 index.js 中引入這兩個函式,又因為 getComments 撞名,所以將原本的 getComments 取名為 getNewComments

import {getComments, addComments} from './api'

jQuery 也要引入、另外將常用的函式放到 utils.js、固定引入的變數放入 templates.js,用 export 的方式輸出。

另外,index.html 要放打包好的 js

<script src="./dist/main.js"></script>

確定可以跑後,優化初始化 code

這一段程式碼,是我們想要移到外面變成 plugin 形式。

$(document).ready( () => {
  init({
    siteKey: 'angela',
    apiUrl: 'http://mentor-program.co/mtr04group3/s103071049/week12/hw1',
    containerSelector: '.comments-area'
  })
})
  output: {
    filename: 'main.js',
    path: path.resolve(__dirname, 'dist'),
    library: 'commentPlugin', // 加這個,就會把 library build 成一個 global 變數
  },

修正細節

撞名問題

透過加 prefix 改善。首先,將 template 寫死的 classname 改成 function 形式。

export function getLoadMoreButton(className) {
  return `<button type="submit" class="${className} btn btn-primary">載入更多</button>`
}
// prefix 不同,className 就會不一樣

將 index.js 相對應的地方換掉。

  lastId = comments[length-1].id
  const lodaMoreButtonHTML = getLoadMoreButton(siteKey)
  $('.comments__list').append(lodaMoreButtonHTML)

找出哪些地方有衝突,調整那些地方。

.init 做了兩次,但因為參數放在 module 裡面會被共用,

<script>
    $(document).ready( () => {
      commentPlugin.init({
        siteKey: 'angela',
        apiUrl: 'http://mentor-program.co/mtr04group3/s103071049/week12/hw1',
        containerSelector: '.comments-area'
      })
    })
    $(document).ready( () => {
      commentPlugin.init({
        siteKey: 'angela2',
        apiUrl: 'http://mentor-program.co/mtr04group3/s103071049/week12/hw1',
        containerSelector: '.comments-area2'
      })
    })
</script>

#作業筆記、留言板-plugin







Related Posts

所有的函式都是閉包:談 JS 中的作用域與 Closure

所有的函式都是閉包:談 JS 中的作用域與 Closure

元件介紹-Day02 #註冊元件的手法

元件介紹-Day02 #註冊元件的手法

How to Launch an Amazon EC2 Instance

How to Launch an Amazon EC2 Instance


Comments