Vue.js 官方示例初探

感謝做者 @尤小右 大大邊寫的超級帶感的 Vue.js 前端框架,贈送的幾個小例子都頗有表明性,代碼邏輯清晰簡明,不由想抄上一抄嗯。html

官方的示例都是 ES5直接編寫運行,並無使用ES6以及構建工具,考慮到之後開發大一些的項目以及官方出品的 vue-cli腳手架,決定此次學習之旅採用二者結合寫寫官方的示例。前端

初探步驟:vue

  1. 觀摩示例的 result
  2. 思考組件模板和邏輯實現思路
  3. 遇到問題先搜一下 api 和官方教程(好像看過一遍仍是記不住什麼。。。結合實踐重要嗯)
  4. 仍是不會就看例子的代碼吧(不出意外的話都會走到這步哈哈)
  5. 整理一下代碼和總結

markdown Editor

一個極簡的 markdown 編輯器,用了 marked 這個工具。react

  • 新建一個 Marked 組件就 ok。看起來很簡單,textarea 標籤做爲輸入編輯器,另外一個 div 標籤經過 marked 這個 markdown工具 轉碼。
  • npm i marked --save 來安裝好 marked,import 後經過定義過濾器實現。
  • textarea 設置了 debounce指令。debounce 設置一個最小的延時,在每次敲擊以後延時同步輸入框的值與數據。若是每次更新都要進行高耗操做(例如在輸入提示中 Ajax 請求),它較爲有用。
    <template>
      <div id="marked">
        <textarea v-model="input" debounce=500></textarea>
        <div v-html="input|marked"></div>
      </div>
    </template>
    
    <script>
      import marked from 'marked'
      export default {
        data () {
          return {
            // note: changing this line won't causes changes
            // with hot-reload because the reloaded component
            // preserves its current state and we are modifying
            // its initial state.
            input: '# Helzzz World!'
          }
        },
        filters: {
          marked: marked
        }
      }
    </script>

    github commits

    編寫一個小組件,異步獲取 github 的兩條 branch的數據。git

    • created:生命週期的鉤子,在實例建立後同步調用。此時實例已經結束解析選項,意味着已經創建了數據綁定,計算屬性,方法,watcher/事件回調。可是尚未開始 DOM 編譯,$el 還不存在。github

    • watch:一個對象,鍵是觀察表達式,值是對應回調。值也能夠是方法名,或者是對象,包含選項。在實例化時爲每一個鍵調用 $watch() 。vue-cli

    • 遇到的問題:eslint 老是提示 new XMLHttpRequest() 錯誤,not defined,並不知道爲啥會這樣,看到了不少代碼也並沒出錯啊,暫時在 eslint 的配置文件把 no-undef 設爲0忽略它了,若是有知道的童鞋能夠指點一二。npm

      <template>
        <div id="commits">
          <p>Latest vue.js Commits</p>
          <template v-for="branch in branches">
            <label :for="branch">
              <input type="radio"
                     name="branch"
                     :id="branch"
                     :value="branch"
                     v-model="currentBranch">
              {{branch}}</label>
          </template>
          <p>vuejs/vue@{{currentBranch}}</p>
          <ul>
            <li v-for="record in commits">
              <a :href="record.html_url" target="_blank">dd</a>
              - <span>{{record.commit.message}}</span>
              by <span>{{record.commit.author.name}}</span>
              at <span>{{record.commit.author.date}}</span>
            </li>
          </ul>
        </div>
      </template>
      
      <script>
        export default {
          data () {
            return {
              branches: ['master', 'dev'],
              currentBranch: 'master',
              commits: null,
              apiURL: 'https://api.github.com/repos/vuejs/vue/commits?per_page=3&sha='
            }
          },
          created () { // 生命週期 created,獲取數據
            this.fetchData()
          },
          watch: {  // 觀測變化,能夠是值也能夠是方法
            currentBranch: 'fetchData'
          },
          methods: {
            fetchData () {
              let xhr = new XMLHttpRequest()
              const self = this  // 下面的 onload事件中 this 再也不指向實例,因此要變量存一下
              xhr.open('GET', this.apiURL + this.currentBranch)
              xhr.onload = function () {
                self.commits = JSON.parse(xhr.responseText)
              }
              xhr.send()
            }
          }
        }
      </script>

      Validation+Firebase

      firebase 實時後端雲簡單摟了一眼,號稱無後端數據存儲加實時通訊仍是很帶感的,不過本身寫的時候老是報錯,只好本身在本地 mock 一下了。之後寫能夠使用 wilddog,國內的後端

      • 計算屬性:因爲模板中只能夠用表達式,相對複雜的邏輯並不適合放在模板中,因此計算屬性就派上用場了,簡單易用。計算屬性默認只是 getter 函數,不過也能夠自定義 getter 和 setter函數。api

      • transition 過渡:這個過渡系統聽勾股大大說很值得學習,因此暫時放下之後看源碼先。

      • mock 數據對象之後比較蛋疼,會把 newUser這個對象直接 push 進 userRef 中,致使之後對 newUser 的操做都會被雙向綁定顯示到列表中。。。因此只好深拷貝一下數據 push 進去,這個留坑之後填。

      • !!:雙歎號強制類型轉換爲布爾值。

        <template>
          <ul>
            <li class="user" v-for="user in userRef" transition>
              <span>{{user.name}} - {{user.email}}</span>
              <button @click="removeUser(user)">X</button>
            </li>
          </ul>
          <form @submit.prevent="addUser">
            <input type="text" v-model="newUser.name">
            <input type="text" v-model="newUser.email">
            <input type="submit" value="Add User">
          </form>
          <p v-show="!validation.name">Name can not be empty</p>
          <p v-show="!validation.email">email is not validated</p>
        </template>
        <script type="text/babel">
          const emailRE = /^(([^<>()[\]\\.,;:\s@"]+(\.[^<>()[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/
        
          export default {
            data () {
              return {
                newUser: {
                  name: '',
                  email: ''
                },
                userRef: [
                  {
                    name: 'hh',
                    email: '10218085@qq.com'
                  },
                  {
                    name: 'heheihe',
                    email: 'weirweoi@qq.com'
                  }
                ]
              }
            },
            computed: {
              validation () {
                return {
                  name: !!this.newUser.name.trim(),
                  email: emailRE.test(this.newUser.email)
                }
              },
              isValid () {
                const validation = this.validation
                return Object.keys(validation).every(key => validation[key])
              }
            },
            methods: {
              addUser () {
                if (this.isValid) {
                  let temp = JSON.parse(JSON.stringify(this.newUser))
                  this.userRef.push(temp)
                  this.newUser.name = ''
                  this.newUser.email = ''
                }
              },
              removeUser (user) {
                
              }
            }
          }
        </script>

        樹狀視圖

        這個例子實現了樹狀視圖,主要演示如何遞歸調用組件。

        • 遞歸組件:組件在自身的模板內能夠遞歸調用本身,可是要有 name 選項才能夠,在這上面花了好長時間又去查了教程才發現。。。官方示例代碼用 Vue.component()註冊了全局組件,會把 id 自動註冊爲name 屬性,因此沒有手動寫 name 屬性。我在 cli 裏寫的時候一直沒注意,致使遞歸老是不顯示嗯。

        • Vue.set:全局 API,設置對象的屬性。若是對象是響應的,將觸發視圖更新。這個方法主要用於解決不能檢測到屬性添加的限制。

        • open = !open:這是用來 toggle 布爾值,又學了一招~

        • @click和@dblclick分別表明單擊和雙擊事件綁定。後一個還真是沒注意過。

        • 動態 props:能夠綁定 props,這樣父組件數據變化後,也會傳遞給子組件。

          <template>
            <li>
              <div @click="toggle" @dblclick="changeType">
                {{model.name}}
                <span v-if="isFolder">[ {{open ? '-' : '+'}} ]</span>
              </div>
              <ul v-show="open">
                <Item :model="model" v-for="model in model.children">
                </Item>
                <li @click="addChild">+</li>
              </ul>
            </li>
          </template>
          <script type="text/babel">
            import Vue from 'vue'
            export default {
              name: 'item',
              data () {
                return {
                  open: false
                }
              },
              props: {
                model: Object
              },
              computed: {
                isFolder () {
                  return this.model.children && this.model.children.length
                }
              },
              methods: {
                toggle () {
                  if (this.isFolder) {
                    this.open = !this.open
                  }
                },
                changeType () {
                  if (!this.isFolder) {
                    Vue.set(this.model, 'children', [])
                    this.addChild()
                    this.open = true
                  }
                },
                addChild () {
                  this.model.children.push({name: 'new staff'})
                }
          
              }
            }

          模態組件

          一個彈出層,用到了組件、props、slot內容分發、過渡。

          • slot:內容分發的一個東東,我的理解好像電腦主機的 pci 插槽,接口標準一致,能夠插入不一樣的板子,好比 pci 網卡或者 pci聲卡,根據 name 不一樣能夠實現具名 slot,有需求的話別忘了設置 default的默認 slot嗯。

          • Props:寫 react 的時候就接觸過了,父組件能夠經過 props 向下傳遞數據,這裏又踩了坑,子組件必定要顯式聲明 props 屬性!!!!折騰了很久纔去查 api 和教程,真是浪費時間。。

          •  

            <template>    // 父組件
              <div id="app">
                <button @click="showModal = true">show modal</button>
                <modal :show.sync="showModal">
                  <h3 slot="header">heaaaaaader</h3>  具名 slot 傳入
                </modal>
              </div>
            </template>
            
            <template> // 子組件
              <div v-show="show" class="modal-mask" transition="modal">
                <div class="modal-wrapper">
                  <div class="modal-container" transition="modal">
            
                    <div class="modal-header">
                      <slot name="header">default header</slot>
                    </div>
            
                    <div class="modal-body">
                      <slot name="body">default body {{show}}</slot>
                    </div>
            
                    <div class="modal-footer">
                      <slot name="footer">default footer</slot>
                      <button @click="show = false" class="modal-default-button">OK</button>
                    </div>
            
                  </div>
                </div>
              </div>
            </template>
            <script type="text/babel">
              export default {
                props: {        //子組件必定別忘了聲明 props
                  show: Boolean
                }
              }
            </script>
相關文章
相關標籤/搜索