透過Vue實現限制數入字數

我們都知道,平常在社群網站上會限制使用者輸入的字數。最具代表性的網站就是Twitter,Twitter限制一般使用者每次發表文章的字數在140字以內。讓使用者用最簡短的文字來表達想法。對於優化使用者體驗比較好的方式是,當使用者在輸入的同時,提示使用者還有多少字可以輸入,當使用這輸入的字數達到限制時,及時地停止使用者繼續輸入。 像這樣子限制使用者輸入字數的機制要如何來實現呢? 有兩的點需要注意: 如何計算使用者輸入了多少字? 當使用這輸入的字數達到限制時,該如何停止繼續輸入? 今天我們就要透過Vue.js來製作一個可以幫我們控制輸入字數的程式。首先,我們先準備好需要的HTML檔案。 <!DOCTYPE html> <html lang=“zh-TW”> <head> <meta charset=“UTF-8” /> <meta name=“viewport” content=“width=device-width, initial-scale=1.0” /> <meta http-equiv=“X-UA-Compatible” content=“ie=edge” /> <link rel=“stylesheet” href=“https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/css/bootstrap.min.css” integrity=“sha384-MCw98/SFnGE8fJT3GXwEOngsV7Zt27NXFoaoApmYm81iuXoPkFOJwJ8ERdknLPMO” crossorigin=“anonymous” /> <title>Start</title> </head> <body> <div id=“app” class=“container”> <div class=“row”> <div class=“col”> <textarea cols=“30”

Vue元件實作,將HTML網頁Vue元件化

將HTML網頁Vue元件化

前一篇簡單的介紹了元件的基本常識。這篇我們要來試試看,實際上如何做出元件化的網頁。
第一個例子,我們要透過bootstrap網站上面的html範例,逐步將它改成Vue元件的頁面。
今天我們要練習的畫面,大家可以在這裡取得,下載為html檔案。下載html的方法這裡就不贅述。
https://getbootstrap.com/docs/4.1/examples/



分析頁面

首先,我們先分析一下這個bootstrap的html範例




有頁首、頁尾、且中間主畫面可以分成兩個區塊。








下面區塊可以再分成更細的區塊,總共有六個區塊構成。
我們可以把分析的結果畫成下面的圖表。
網頁可以分割成Header、Footer、主要內容三段。主要內容的部分可以分上下,上面是bigBoard下面是一個個Item組成,總共有六個Item。








再回來對應下載的html原始碼。我們發現:
Header 區塊,從<header>開始到</header>結束。
Footer 區塊,從<footer class="text-muted">開始到</footer>結束。
主要內容區塊,從 <main role="main"> 開始到</main>結束。
主要內容區塊,又可以分成兩段,上半段從<section class="jumbotron text-center">開始,到 </section>結束; 下半段從<div class="album py-5 bg-light">開始,到</div>結束,裡面有六個Item,每個Item都從。<div class="col-md-4">開始,到</div>結束。

建立Vue

依照上面的分割方式,我們可以將整個網站分成幾個Vue元件。在分割之前,我們先在頁面上安裝Vue.js。一樣,我們先插入下面兩個部分。
  1. Vue.js的CDN檔案連結
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
  1. 建立一個Vue 實例,連結Html上的<div id="app"> </div>
<script>
        var app = new Vue({
            el: "#app",
        })
</script>
當這一切都設定好之後,我們就要來註冊Vue元件了。
依照上面的分析,我們需要建立Head 、Footer、bigBoard、cardCom等元件。

Head 、Footer元件

先從Head 開始,註冊全域元件pageHeader,樣板採用x-template方式,名稱為#header。
 Vue.component('pageHeader', {
      template: "#header",
      data: function () {
            return {
               title: "ABC",
               about: "關於這個網站",
               contact: "聯絡我們"
            }
      }
  });
因此,先建立一個x-template 的 script,並且賦予一個header的id。
<script type="text/x-template" id="header">
   //樣板
</script>
接著將,Header 區塊(從<header>開始到</header>結束)貼近去。結果如下:
<script type="text/x-template" id="header">
        <header>
            <div class="collapse bg-dark" id="navbarHeader">
                <div class="container">
                    <div class="row">
                        <div class="col-sm-8 col-md-7 py-4">
                            <h4 class="text-white">{{about}}</h4>
                            <p class="text-muted">Add some information about the album below, the author, or any other
                        background context. Make it a few sentences long so folks can pick up some informative
                        tidbits.
                        Then, link them off to some social networking sites or contact information.</p>
                        </div>
                    <div class="col-sm-4 offset-md-1 py-4">
                    <h4 class="text-white">{{contact}}</h4>
                    <ul class="list-unstyled">
                        <li><a href="#" class="text-white">Follow on Twitter</a></li>
                        <li><a href="#" class="text-white">Like on Facebook</a></li>
                        <li><a href="#" class="text-white">Email me</a></li>
                    </ul>
                </div>
            </div>
        </div>
    </div>
    <div class="navbar navbar-dark bg-dark shadow-sm">
        <div class="container d-flex justify-content-between">
            <a href="#" class="navbar-brand d-flex align-items-center">
                <svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" fill="none" stroke="currentColor"
                    stroke-linecap="round" stroke-linejoin="round" stroke-width="2" aria-hidden="true" class="mr-2"
                    viewBox="0 0 24 24" focusable="false">
                    <path d="M23 19a2 2 0 0 1-2 2H3a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h4l2-3h6l2 3h4a2 2 0 0 1 2 2z" />
                    <circle cx="12" cy="13" r="4" /></svg>
                <strong>{{title}}</strong>
            </a>
            <button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarHeader"
                aria-controls="navbarHeader" aria-expanded="false" aria-label="Toggle navigation">
                <span class="navbar-toggler-icon"></span>
            </button>
        </div>
    </div>
  </header>
</script>
最後,在Html上的<div id="app"> </div>中間,放入
<page-header></page-header>
注意,雖然元件命名為pageHeader(有大小寫),由於在Html中無法分辨大小寫,於是呼叫元件時必須採用<page-header>的方式,也就是 page與header需要小寫,且兩者中間需要一個橫槓(-)才行。
接著,就可以測試看看header是否正常出現在頁面上。
如果沒問題的話,接著就用同樣的方式製作Footer的部分。
註冊Vue元件pageFooter。
 Vue.component('pageFooter', {
      template: "#footer"
  })
建立一個x-template,並且貼上樣板。
<script type="text/x-template" id="footer">
        <footer class="text-muted">
            <div class="container">
                <p class="float-right">
                    <a href="#">Back to top</a>
                </p>
                 <p>Album example is &copy; Bootstrap, but please download and customize it for yourself!</p>
                <p>New to Bootstrap? <a href="https://getbootstrap.com/">Visit the homepage</a> or read our <a href="/docs/4.3/getting-started/introduction/">getting
                started guide</a>.</p>
            </div>
        </footer>
</script>
在Html上的呼叫pageFooter元件。
<page-footer></page-footer>

中間區塊元件

前面Header、Footer部分已經改成Vue元件,我們可以看一下目前的頁面的結構。
<div id="app">  
    
   <page-header></page-header>

       <!--component pageMain -->
       <main role="main">
         <!-- component jumbo --><!-- //component jumbo -->
         <!-- component container --><!-- //component container -->
        </main>
        <!--// component pageMain -->

        <page-footer></page-footer>

    </div>
<main role="main"></main> 中間的部分,我們分兩部分,上半部要放在<!-- component jumbo --><!-- //component jumbo -->裡面,下半部則需要放在<!-- component container --><!-- //component container -->中間。
上半部跟前面的Header、Footer區塊一樣,先註冊Vue元件jumboCom。
Vue.component('jumboCom', {
            template: "#jumbo"
 })
接著建立一個x-template,並且貼上樣板。
<script type="text/x-template" id="jumbo">
  <section class="jumbotron text-center">
     <div class="container">
        <h1 class="jumbotron-heading">Album example</h1>
         <p class="lead text-muted">Something short and leading about the collection below—its contents, the
            creator, etc. Make it short and sweet, but not too short so folks don’t simply skip over it
            entirely.</p>
         <p>
         <a href="#" class="btn btn-primary my-2">Main call to action</a>
         <a href="#" class="btn btn-secondary my-2">Secondary action</a>
         </p>
     </div>
  </section>    
</script>
最後,在Html上的呼叫jumboCom元件。
<div id="app">

    <page-header></page-header>

      <!--component pageMain -->
        <main role="main">

         <!-- component jumbo -->
            <jumbo-com></jumbo-com>
         <!-- // component jumbo -->

        <!-- component container --><!-- //component container -->
        </main>
      <!--// component pageMain -->

        <page-footer></page-footer>

    </div>
到這裡為止,剩下最後的一塊,整個畫面就跟Bootstrap上面取得的畫面一樣了。








下半部區塊,需要放在<!-- component container --><!-- //component container -->中間。比較單純的做法是,直接在中間放入item的元件。
<!-- component container -->
   <div class="album py-5 bg-light">
     <div class="container">
        <div class="row">
               //item元件         
        </div>
     </div>
   </div>
<!-- // component container -->
先依照上面說明的方式,先註冊Vue元件cardCom,並建立一個x-template,並且貼上樣板。
Vue.component('cardCom', {
    template: "#cardcom",
});
<script type="text/x-template" id="cardcom">
   <div class="col-md-4">
      <div class="card mb-4 shadow-sm">
         <img width="100%" height="225" src="photo.img">
            <div class="card-body">
               <p class="card-text">文字</p>
               <div class="d-flex justify-content-between align-items-center">
                <div class="btn-group">
                    <button type="button" class="btn btn-sm btn-outline-secondary">View</button>
                    <button type="button" class="btn btn-sm btn-outline-secondary">Edit</button>
                </div>
                <small class="text-muted">9 mins</small>
            </div>
         </div>
      </div>
   </div>
</script>
在Html上的呼叫cardCom元件。
<!-- component container -->
  <div class="album py-5 bg-light">
     <div class="container">
       <div class="row">
           <card-com></card-com>            
        </div>
     </div>
  </div>
<!-- // component container -->

Item依照數量自動產生

到目前為止,方法都跟上面一樣,你會看到中間下面區會出現一個item。接下來,要讓 item依照資料的數量自動增加,目標是六個item。
先在Vue實體加上data選項,在postsdata 中建立一筆資料。
<script>
        var app = new Vue({
            el: "#app",
            data() {
                return {
                    postsdata: [{
                        img: "好",
                        url: "info-center.jpg",
                        context: ` Lorem ipsum dolor sit amet consectetur adipisicing elit. Magnam aliquam alias vero quas id
            voluptates assumenda illum culpa. Soluta repudiandae nemo consequatur facere quibusdam placeat sapiente
            reprehenderit quod hic in!`
                    }]
                }

            }
        })
    </script>
在cardCom元件中,加入props。(props在下一篇會說明)
 Vue.component('cardCom', {
            template: "#cardcom",
            props: ["posts"],
});
將原來的 <card-com></card-com>部分,改成下面的程式碼:
<card-com v-for="(item, key) in postsdata" :key="key" :posts="item"></card-com>
其中,:posts="item" 地方,綁定元件的資料從Vue實例的data函數中傳入。
v-for="(item, key) in postsdata" 的地方會依照data中postsdata內的資料的數量,一組一組顯示出來,目前只放了一組資料。
在x-template的部分也修改成下面程式碼。其中{{posts.context}}會將postsdata中的context顯示出來。
而在
<img width="100%" height="225" :src="posts.url" :alt="posts.img">部分則使用v-bind的方式綁定src與alt兩個 img 的屬性。
<script type="text/x-template" id="cardcom">
  <div class="col-md-4">
    <div class="card mb-4 shadow-sm">
     <img width="100%" height="225" :src="posts.url" :alt="posts.img">
       <div class="card-body">
         <p class="card-text">
          {{posts.context}}
         </p>
         <div class="d-flex justify-content-between align-items-center">
            <div class="btn-group">
               <button type="button" class="btn btn-sm btn-outline-secondary">View</button>
               <button type="button" class="btn btn-sm btn-outline-secondary">Edit</button>
            </div>
            <small class="text-muted">9 mins</small>
            </div>
        </div>
    </div>
 </div>
</script>
恭喜,第一筆資料已經出現在畫面上了。








接著,你可以再增加5筆資料,如此就大功告成了。









以下是原始碼

留言

這個網誌中的熱門文章

用Python的條件實現電影分級流程

Python基礎篇--[條件]如果發生這種狀況時,我該怎麼辦?