2019年5月24日 星期五

[Vue.js] 如何在component自訂v-model


v-model 通常用在HTML的 input,根據輸入的內容會跟著改變這個參數的內容,建立專案時會將一些基礎元件(如:input)定義成一個component,方便在各個頁面引入使用。

其實 v-model 是結合了 propsemit ,可以先參考『[Vue.js] 父子元件的雙向溝通,簡單的props和emit使用範例』,比較能理解下面的內容。

舉例常見的用法來看:
<input v-model="username" />
v-model其實綁定了名為 valuepropsinputemit事件,因此所謂的 v-model 就是一個父子元件的雙向溝通,可以拆寫成:
<input :value="username"
       @input="(value)=>(username=value)" />
跟使用 v-model 達到的效果相同。


定義元件的v-model和使用

1. 定義子元件
input.vue
<template>
    <input ref="input"
        class="my-input"
        type="text"
        :placeholder="placeholder"
        :value="value"
        @input="updateValue" />
</template>

<script>
export default {
  props: {
    value: String,
    placeholder: {
      type: String
     }
  },
  methods: {
    updateValue: function() {
      this.$emit('input', this.$refs.input.value);
    }
  }
}
</script>

<style scoped>
.my-input {
    color: #3b3b3b;
    font-size: 1rem;
    line-height: 1.5;
    border: 1px solid #003377;
    padding: 4px;
}
</style>

2. 在父元件使用
<template>
  <div style="text-align: center">
    <h1>coustom v-model</h1>
    <my-input v-model="username" />
    <p>My name is {{ username }}</p>

    <h1>coustom v-model with placeholder</h1>
    <my-input v-model="email" placeholder="input your email" />
    <p>My email is {{ email }}</p>
  </div>
</template>

<script>
import MyInput from './input.vue'
export default {
  data: function() {
    return {
      username: "",
      eamil: ""
    }
  },
  components: {
    MyInput
  }
}
</script>

頁面預覽:


上述只有把 placehodler 加到 props 裡,其他像是typedisabledreadonly等等常用的attr可以依照這個方式加進你的元件裡。另外除了 inputcheckboxradio這些表格常用的也可以一一寫成元件來使用。


自訂props的預設值和監聽事件

預設情況下,v-model 是綁定的 propsvalueinputemit事件,若要自訂名稱請參考:
export default {
  prop: ['keyword'],
  model: {
    prop: 'keyword',
    event: 'transfer'
  }
  methods: {
    updateValue: function() {
      this.$emit('transfer', this.$refs.input.value)
    }
  }
}
在上面的例子裡,propskeyword,綁定的事件則是trasfer,也就是說這邊的 v-model 應該理解成:
<input :keyword="username"
       @transfer="(value)=>(username=value)" />


參考資料:
https://scotch.io/tutorials/add-v-model-support-to-custom-vuejs-component


2019年5月19日 星期日

[Vue.js] 預覽上傳照片的原始碼分享(single/multiple file)


選擇照片上傳前如何實作預覽的功能,下面拆解成3個部分說明:
1. 上傳檔案
首先需要一個上傳檔案的HTML
<input type="file" accept="image/*" @change="previewImage">
根據上面的程式碼,我們需要一個 previewImage 的function來處理選擇的圖片檔。

2. 實作previewImage
接下來是js的程式部分,我們定義了兩個變數 previewimage,前者是存放預覽圖片,後者則是實際檔案。
new Vue({
  data: function() {
    return {
      preview: null,
      image: null
    };
  },
  methods: {
    previewImage: function(event) {
      var input = event.target;
      if (input.files) {
        var reader = new FileReader();
        reader.onload = (e) => {
          this.preview = e.target.result;
        }
        this.image=input.files[0];
        reader.readAsDataURL(input.files[0]);
      }
    }
  }
});

3. 顯示預覽
previewImage 儲存的結果顯示出來
<template v-if="preview">
  <img :src="preview" />
  <p>file name: {{ image.name }}</p>
  <p>size: {{ image.size/1024 }}KB</p>
</template>

執行上面的程式碼就可以達到預覽的效果,最後只要透過API將 image 這個物件透過API丟到後台,就能完成檔案的上傳。(用formData檔案上傳)


更進階的部分,只要在 input tag中加上multiple 就能一次選擇多個檔案。
<input type="file" accept="image/*" multiple>
除了預覽單一檔案,也能支援選擇多個檔案並預覽,有需要的話完整的原始碼已經放到codepen上,歡迎參考。



[Vue.js] 2.6版本開始使用v-slot取代slot


升級到2.6.0+後,slot的功能有一些更動,以v-slot取代slot,雖然在2.0+仍然可以使用,但確定會在Vue3之後捨棄這個用法,既然如此遲早要學會使用v-slot。

基礎使用

<!-- NavLink.vue -->
<a href="#">
  <slot>Link</slot>
</a>

你可以在模板裡面使用:
<nav-link></nav-link>
會使用 <slot> 內的內容當作預設值顯示。

如果你想要客製內容:
<nav-link>Home</nav-link>
則會取代原本的內容,得到這樣的結果。
<a href="#">
  Home
</a>

未指定 name 這個屬性的情況下,預設的名稱都是 default


即將淘汰的slot

1. 命名方式
<!-- NavLink.vue -->
<a href="#">
  <slot name="main">Link</slot>
</a>

2. 使用方式
可以用在任意的元件上,寫入內容:
<nav-link>
  <template slot="main">Home</template>
</nav-link>

<nav-link>
  <h1 slot="main">Home</h1>
</nav-link>


v-slot特性介紹

1. 命名方式
方式不變

2. 使用方式
僅能在 <template> 元件上,寫入內容:
<nav-link>
  <template v-slot:main>Home</template>
</nav-link>

3. 可以縮寫
就像是 v-on: 縮寫成 @v-bind: 縮寫成 :v-slot: 可以簡寫成 #,舉例來說,v-slot:header 等同於 #header
<nav-link>
  <template #main>Home</template>
</nav-link>

除了不能在任意元件是使用 slot ,基本上更動不大,而且更方便好用。不只是 slot 即將走入歷史, slot-scope 是另一個即將被淘汰的用法,想了解更多資訊可以參考官方文件:
https://vuejs.org/v2/guide/components-slots.html

2019年5月16日 星期四

[Vue.js] 升級vue-cli3建立Vue專案


之前安裝vue-cli2來建立vue專案 --『[Vue.js] 在ubuntu安裝 Vue.js』,有需要可以參考。

開始安裝vue-cli 3
npm install --global @vue/cli

完成安裝後可以用指令檢查版本
vue --version
// or
vue -V

vue cli3多了一個 create 功能來建專案:
vue create [APP_NAME]
你可以使用預設選項或根據需求選擇,結束後會自動幫你執行 npm install

整個專案目錄精簡了不少,少了 config/build/ 兩個目錄,然後 static/ 改為 public/
執行下面指令就可以進入開發囉
npm run serve
vue cli不再使用dev當作開發環境的指令,如果你習慣用dev,可以到 package.json 修改script。



因為移除了 config/ ,因此『[Vue.js] 開發用和正式環境的參數設定方式(.env)』的方式勢必就要調整了。
在專案的根目錄新增兩個檔案 .env.env.production,分別用在開發和正式環境。所有的參數名稱必須加上前綴 VUE_APP_ ,只有名稱 VUE_APP_* 的參數,才能在vue專案裡使用。
1. .env
VUE_APP_NODE_ENV: '"development"'
VUE_APP_ROOT_API: '"http://localhost/api"'
2. .env.production
VUE_APP_NODE_ENV: '"production"'
VUE_APP_ROOT_API: '"https://example.com/api"'

使用方式和之前相同
export default {
  mounted() {
    console.log(process.env.VUE_APP_ROOT_API);
  }
}

關於環境變量,參考下面連結了解更多。
https://cli.vuejs.org/guide/mode-and-env.html#environment-variables