顯示具有 vuejs 標籤的文章。 顯示所有文章
顯示具有 vuejs 標籤的文章。 顯示所有文章

2022年4月28日 星期四

vue2升級vue3 composition api紀錄

將原本的vue2更新使用vue3 composition api改寫

針對原本vue2 option api使用的各個功能對應到vue3的使用

紀錄如下

1.主架構

<script setup lang="ts"></script>

所有要用的功能都由vue import

import {ref,reactive,computed,watch...} from 'vue'

只有在使用setup()才需要return

如果是以script setup則不需要return

在程式內沒有任何的this使用

2.props

設定

以 defineProps({})定義建立

ex:

  const props = defineProps({

    host: {

      type: String,

      default: ''

    }

  })

使用

ex:

  props.host


3.data3.data

以ref或reactive包裝變數

ref:一般的變數都以ref包裝,使用必須以.value讀取

ex:

  建立 const myvar = ref('') 

  使用 myvar.value

reactive: Object或Array以reactive包裝

ex:

  建立 const myvar = reactive({x,y})

  使用 myvar.x

4.computed或取自store的getters

以computed包裝 使用上以.value取值

設定建立

  const inAgent = computed(() => {

    return currentHost.value.inAgent !== undefined && currentHost.value.inAgent

  })

使用

  inAgent.value

5.attrs

  取得網頁上html上設定的attrs

  取得

  import { useAttrs} from 'vue'

  const attrs = useAttrs()

  使用 attrs.xxx 不需要value

6.生命週期

created 就直接寫在setup內其他都有對應的

ex:mounted即改為執行

  onMounted(() => {


  })


7.watch

以watch包裝

  ex:

  watch(props.host, (val, oldVal) => {

    if (val !== oldVal) console.log(`watch!! host=${val}`)

  })


8.methods

不在method內使用this

9.vuex

  使用useStore取得store操作

  import { useStore } from 'vuex'

  const store = useStore()


10.vue-router

  import { useRoute, useRouter } from 'vue-router'

  const route = useRoute()

  const router = useRouter()


2022年4月14日 星期四

vue quasar 透過process.env動態傳遞變數到web內

使用qusar建立vue網頁

可透過執行quasar dev執行或quasar build產生編譯檔案

如果希望可以

例如透過產生quasar build產生開發區或正式區的網站內容

但測試區與正式區取用資料的api是不相同的

希望可以透過

stage=master quasar build 建立正式區網頁

stage=develop quasar build 建立測試測網頁

在指令列上設定的環境變數stage

要如何讀取並轉換成在網頁上可讀取到?

在執行quasar cli 也就是nodejs

會載入quasar.conf.js

在這裡可以使用process.env.stage拿到在cli上設定的stage值

只要帶到 build的env下即可以在web內使用

ex

quasar.conf.js

module.exports = configure(function (ctx) {

  return {

    ..

    build: {

      env: {

        stage: process.env.stage

      },

      ..

    }

  }

在vue頁面或前端的js內

可以用process.env.stage

這邊要注意

quasar.conf.js

內的process.env是nodejs的環境變數

vue內的

process.env是 前端頁面拿到的設定變數

2021年4月16日 星期五

vue建立動態watch

當建立一個vue物件

如果data內容是由變數動態產生

要watch這些動態data值 可以透過this$watch建立


 const dataObj = {  
  x:'',  
  y:''  
 }  
 建立vue物件  
 {  
  data() {  
   return dataObj  
  },  
  created() {  
   for(const prop in dataObj) {  
    this.$watch(prop, function(newValue, oldValue) {  
     // .. do something  
    });  
   }  
  }  
 }  

2021年3月12日 星期五

quasar 為內定emit handler加入更多的傳遞參數

在handler加入要另外傳遞的參數

例如當要接收checkbox的input event

handler能接收到的只有val 與evt這兩個參數

<q-checkbox v-model="selected" :val="item.id" @input="inputHandler">

inputHandler(val, evt){


}


但如果需要再多傳遞參數到handler

可以改寫為以下

就可以傳遞更多的自訂參數給handler

<q-checkbox v-model="selected" :val="item.id" @input="(val, evt) => inputHandler(val, evt, my_var)">


inputHandler(val, evt, myvar){


}

2020年9月15日 星期二

quasar q-table未顯示全部資料

使用案例在使用q-table顯示一個明細的列表

不做分頁 但資料卻只顯示部份

需要加上設定

:rows-per-page-options="[0]"

ex:

<q-table

  ...

  :rows-per-page-options="[0]"

>

2020年7月9日 星期四

quasar table在不同尺寸device 顯示不同欄位

不同於RWD操作div的顯示
如果資料以table呈現 但需要在小尺寸顯示比較少的欄位
可以用到 visible columns
標準以columns設定所有的顯示欄位
visible-columns的內容則是欄位名稱的array
如果有設定visible-columns prop
則真正顯示的欄位會是
columns內設定required:true的欄位+visibleColumns設定的欄位
要讓不同尺寸的device去顯示不同的欄位
只要在檢查尺寸的時候改變visible-columns的值即可

以下範例
在小尺寸的device上只會顯示 M_DAY(required:true所有的尺寸都必要顯示的)
與M_SMALL(來自visbleColumns設定的)

<template>
 <q-table
    :data="items"
    :columns="columns"
    :visible-columns="visibleColumns"
    ...
</template>
<script>
..
data () {
  return {
    items: [],
    columns: [ // 欄位宣告
      { name: 'M_DAY',
        required: true,
        label: '交易日期',
        field: 'T_DAY',
        
      },
      { name: 'M_TIME',
        label: '交易時間',
        field: 'T_TIME',
        format: (val, row) => moment(val, 'hhmm').format('hh:mm')
      },
      { name: 'M_SMALL',
        label: '交易時間',
        field: 'T_TIME',
        format: (val, row) => moment(val, 'hhmm').format('hh:mm')
      },...
    },
    visibleColumns: ['M_SMALL']
  }
}
created () {
  if (this.$q.screen.lt.sm) {
    this.visibleColumns = ['M_TIME']
  }
}
</script>

2020年4月10日 星期五

nightwatch chromeDriver版本問題

vue-cli 預設的e2e測試為nightwatch
使用vue-cli預設不用設定即可跑起e2e測試
如果遇到以下錯誤訊息
Error: An error occurred while retrieving a new session: “session not created: This version of ChromeDriver only supports Chrome version 77”

來自測試安裝的chromeDriver與現在自己機器上的Chrome版本不相符
vue-cli預設安裝nightwatch帶的chromeDriver為77
查一下機器上跑的Chrome版本為80.x
只要重新安裝
npm install chromeDriver@80 --save-dev
即可正常運作

2020年4月2日 星期四

quasar table 取server資料 分頁使用

1.元件設定
  1.rows-per-page-options:設定option供選擇每頁顯示幾筆(對應rowsPerPage)
  2.pagination: 對應分頁設定
  3.@request:當在分頁物件上按上下頁或是切換每頁顯示幾筆都會被觸發的handler
    handler接收到的參數props並非現在物件上的pagination設定值
    而是要變成的pagination
<q-table
  :data="items"
  :rows-per-page-options="[50,100]"
  :pagination.sync="pagination"
  @request="onRequest"
>
2.script
  1.設定pagination物件
    page: 目前第幾頁 要操作載下一頁 需要將第幾頁更新回這裡
    rowsPerPage: 每頁幾筆,當在元件操作切換要顯示的數量,要寫回這裡
    rowsNumber: 總筆數,這要由server取得的資料來更新
  2.doQuery真正執行server查詢的function
    在執行真正查詢所需要的分頁參數 ex取第二頁資料
    這些值都是由pagination設定值拿來當作參數
    pagination設定值會因為元件的操作而動態變化
  3.設定的onRequest handler
    當在分頁物件上按上下頁或是切換每頁顯示幾筆都會被觸發的handler
    handler接收到的參數props並非現在物件上的pagination設定值
    而是要變成的pagination
    要將取得的資料寫回pagination 再執行查詢
    執行查詢的doQuery會去讀取pagination內的資料來執行
data() {
  return {
    pagination: {
      items: [], // table要顯示的資料
      page: 1, // 目前第幾頁
      rowsPerPage: 50, // 每頁幾筆
      rowsNumber: 20 // 總筆數
    }
  }
}
methods: {
  async onRequest (props) {
    const { page, rowsPerPage } = props.pagination
    this.pagination.page = page
    this.pagination.rowsPerPage = rowsPerPage
    await this.doQuery()
  },
  async doQuery () {
    // 將pagination內的分頁資料 設定到api所需要吃的參數
    const queryParams = {
      countPerPage: this.pagination.rowsPerPage
      currentPage: this.pagination.page
    }
    // 假設呼叫api 吃queryParams參數執行server query
    const response = await doAPIfetch(queryParams)
    // 假設api回傳 data(查詢結果) 與meta(包含分頁資料)
    this.items = response.data
    this.meta = response.meta
    // 將分頁資訊取得的資料總量寫回pagination.rowsNumber
    this.pagination.rowsNumber = this.meta.total
  }
}

2019年11月5日 星期二

vue.config.js設定publicPath

使用vue-cli4建置新專案內
webpack的設定已經被包裝在整個架構下
大多數預設值即可符合開發需求
若需要手動執行webpack設定
則是寫在根目錄的vue.config.js內
通常會需要設定的部分包括
publicPath 預設是以/為路徑
因此產生出來的html檔案內所有的css 或js 路徑
都會是對應到根目錄的/js/xxx或 /css/xx的位置
如果你build出來的檔案是要放在web server的根目錄下
也就是http://localhost/下執行 這樣可以正常顯示

但如果是放在如http://localhost/abc/def/xxx目錄下
就會有找不到相關檔案的問題

必須將publicPath設定為'./'才會讓build出的檔案
可以放在任意目錄下執行

以下為範例

 const path = require('path')  
 module.exports = {  
  publicPath: './', // 預設為/ 所有html下的js css 連結都會是/js/xx,在輸出到web server 路徑會有問題,需用./  
  outputDir: 'www', // 輸出路徑  
  assetsDir: '', // 要輸出的asset目錄,設定hello,則會輸出成 hello/js/xxx,  
  devServer: {  
   port: 1234,  
   open: true  
  },  
  chainWebpack: config => {  
   config.module  
    .rule('yaml')  
    .test(/\.ya?ml$/)  
    .use('js-yaml-loader')  
    .loader('js-yaml-loader')  
    .end()  
   config.resolve.alias  
    .set('@@', path.resolve(__dirname)) // @@ 代替根目錄  
  }  
 }  

2019年10月4日 星期五

[Violation] Added non-passive event listener to a scroll-blocking 警告


修正方式
1.npm install default-passive-events -S
2.在進入點entry.js加上
  import 'default-passive-events'

2019年8月16日 星期五

vue-cli環境變數使用

vue-cli在執行許多的程式會需要在不同的情況(model)下
用到不同的環境變數
1.因此預設會有這3種mode
  development|test|production
2.不同mode使用的環境變數 會以下列檔名儲存
.env              # 任何mode都會載入的變數
.env.local        # 任何mode都會載入的變數,只限開發者自己使用的變數,檔案不進git
.env.[mode]       # 指定mode會載入的變數
.env.[mode].local # 指定mode會載入的變數,只限開發者自己使用的變數,檔案不進git
3.env檔案內 變數的設定方式
  以key=value方式寫
  如果是要讓client端可以拿去使用的變數名稱
  必須以VUE_APP_開頭命名
  否則都只有在node環境下才讀得到變數值
4.client端應用
  例 public/index.html本身就是一個樣板
  可用樣板語言,就可以拿client端可用的環境變數來做判斷
  使用或顯示
5.環境變數除了寫在特定的env檔案內以外
  也可以寫在vue.config.js設定檔內

2019年8月14日 星期三

vue-cli 3 webpack設定yaml讀取

目前已經將原本在框架下使用json設定檔案都改成yaml檔案
畢竟yml的結構比json要好上很多
在後端的nodejs上透過js-yaml即可讀取
前端上vue要使用
則需要透過webpack的js-yaml-loader的設定支援讀取
使用上可以很簡單的用
import data from 'js-yaml-loader!./conf/apis.yml'
這樣免設定的方式執行 但還是不太建議直接這樣用

如果是要設定到webpack的config上
使用vue-cli 3 會發現已經完全看不到webpack的設定
所有的設定已經都包裹在整個架構內
如果需要調整或增加webpack設定
可以在根目錄下建立vue.config.js檔案
用來覆寫或增加上定內容

參考vue-cli設定
https://cli.vuejs.org/guide/webpack.html#simple-configuration

以下sample code範例為
修改連線port 並加入yaml loader

module.exports = {
  devServer: {
    port: 1234
  },
  chainWebpack: config => {
    config.module
      .rule('yaml')
      .test(/\.ya?ml$/)
      .use('js-yaml-loader')
      .loader('js-yaml-loader')
      .end()
  }
}

2018年12月4日 星期二

vue自訂元件 自訂event

在vue裡自訂元件 除了最常用的props使用
也會需要自訂event 以如同@click般的使用
這部分 只要在元件內使用$emit(event-name)發送
就可以在使用元件時透過 @evnet-name來觸發handler

例 自訂子元件my-component
透過emit發送事件,並同時發送data1,data2資料
this.$emit('event-name',data1,data2)
下是三種可能的使用方式

子元件發送
this.$emit('event-name',data1,data2)

父元件接收方式
1.handler取得發送event時所帶的資料
  若只是設定myHandler 
  取得data1,data2 是來自$emit送出之參數
  <my-component @event-name="myHandler">
  myHandler(data1,data2) {}
  
2.handler取得使用者自帶的資料
  設定handler時為執行myHandler(data1,data2) 
  取得data1,data2 是來自使用時所傳遞之參數
  <my-component @event-name="myHandler(data1,data2)">
  myHandler(data1,data2) {}
  
3.handler取得event帶過來的資料,並帶使用者自訂資料
  event所帶的資料透過$event取得
  <my-component @event-name="myHandler($event,data1,data2)">
  myHandler(evt,data1,data2) {}
  拿到到evt是event帶來的資料,data1,data2是使用者帶的資料

子元件如何判斷是否被使用時設定了event handler
會需要依照 元件被使用時,是否有設定了eventHandler來做後續處理
可透過this.$listeners.[事件名稱]來確認

my-component子元件
this.emit('beforeClick')
this.emit('afterClick)
computed:{
  hasBeforeListener() {
    return this.$listeners && this.$listeners.beforeClick !== undefined
  },
  hasAfterListener() {
    return this.$listeners && this.$listeners.afterClick !== undefined
  }
}
這時候就會
this.hasBeforeListener的結果會是true
this.hasAfterListener的結果會是false

2018年7月30日 星期一

vue-loader prettier錯誤

錯誤訊息
No parser and no filepath given, using 'babylon' the parser now
將prettier升級到1.12即可
npm install prettier@~1.12.0

2018年3月1日 星期四

讓object data 下的屬性異動可以觸發 watch

data內設定了obj物件
obj下的屬性如果異動
設定在data下的各個屬性,如果發生異動 應該就會觸發watch
但若屬性為object,而object下的prop被異動要能夠觸發watch
有兩種處理方式
1.宣告data時同時把下層的屬性都宣告
例
data(){
  return {
    obj:{x:1,y:1}
  }
}
methods:{
  update(){
    this.obj.x = 2
  }
}
2.宣告data時不宣告下層
改變下層屬性 透過$set執行
例
data(){
  return {
    obj:{}
  }
}
methods:{
  update(){
    this.$set(this.obj,x,2)
  }
}
3.若要改變的屬性是 array
即使是改變arry下一個物件的一個屬性,也是要把整個物件換掉
data(){
  return{
    arr:[
      {x:1,y:2},
      {x:100,y:23}
      ]
  }
},
methods:{
  update(){
    let newObj = {x:1,y5}
    this.$set(this.arr,0,newObj)
  }
}

2017年8月14日 星期一

single file component 使用 vuelidate

validate提供了vue很方便的資料驗證功能
以下是使用在Single File Component上程序

一.在框架上載入vuelidate
import Vuelidate from 'vuelidate'
Vue.use(Vuelidate)

二.元件上使用
1.以mixin方式使用mixin加入
import { validationMixin } from 'vuelidate'
mixins:[validationMixin],
此時就可以在元件內加入validations來設定相關要驗證的規則
validations可以是物件
validations:{

}
也可以是method
validations(){
  return {}
}

這時候在元件內就可以得到this.$v來操作相關
2.import所要用到的validator,
import { required, minLength,maxLength,numeric } from 'vuelidate/lib/validators'

3.透過$v.model名稱取得該model的即時狀態
  依照取得的model狀態,來決定畫面要做如何的處置

三.Sample
<template>
  <div>
    <input type="password" v-model.trim="pwd">
    <button v-if="isActiveForSend" @click="clickSendBtn">送出</button>
    <span>這欄位所有狀態{{$v.pwd}}</span>
  </div>
</template>
<script>  
import { validationMixin } from 'vuelidate'
import { required, minLength,maxLength,numeric } from 'vuelidate/lib/validators'
export default {
  mixins:[validationMixin],
  validations(){
    return {
      pwd:{
        required,
        numeric,
        minLength: minLength(6),
        maxLength:maxLength(6)
      }
    }
  },
  computed:{
    isActiveForSend(){
      return this.$v.pwd.required&&this.$v.pwd.numeric&&this.$v.pwd.minLength&&this.$v.pwd.maxLength
    }
  },
}
</script>

2017年6月5日 星期一

讓vue 元件script預設以es2015解析

vue元件 預設並不會script 語言並非是es6
在webpack loader設定 以vue-loader載入vue元件
只是讓他可以載入.vue的檔案
但vue元件內的script並非預設就可以解析es6
即使你已經安裝了babel 可以對 es6的.js檔案做正確的解析
但對於.vue內的es6還是可能不會自動辨識解析

可以透過設定.babelrc 讓webpack以es2015解讀vue內的es6檔案

來讀取script部分
這部分可以透過設定.babel.rc來處理
.babelrc
{
  "presets": ["es2015", "stage-2"],
  "plugins": ["transform-runtime"],
  "comments": false
}

2017年5月25日 星期四

Vue v-model bind 物件或array 範例

v-model可以綁定整個結構的物件變數
並可watch到物件下任何property的異動
樣板
<tr v-for="(val,key) in tableMap">
  <td>{{key}}</td>
  <td><input type="text" :value="val" v-model="tableMap[key]" /></td>
</tr>

js
watch:{
  tableMap:{
    deep:true,
    handler:function(val,oldVal){
      console.log(this.tableMap)
      Tool.setLocal('tableMap',this.tableMap)
    }
  }
}

Vue 多層次變數監聽範例

情境
1.資料的來源為tableStr(輸入字串)
2.由tableStr,計算產生tables(桌次array)
3.由tables 計算產生tableMap(桌次對照表)

1.data 內只建立需要用的變數,不設定預設起始值
data{
  tableStr:"", //桌號字串 
  tableMap:{}, //桌次對照表
}

2.在mounted後才給預設值,才會讓相關的變數都被計算
mounted(){
  this.tableStr = "1-5" 
}

3.tables是計算產生的,在tableStr有值 就會被產生
computed{
  tables:function(){
    let tables = this.tableStr.split(",")
    return tables
  }
}

4.watch是需要有異動才會被觸發的
//所以在mounted內去設定tablStr值,造成異動,才會造成tables被重新計算
//這個watch才會被觸發,才會在這裡去改變要產生的tableMap值
watch:{
  tables:function(val){
    tableMap = {}
    for(let i=0;i<this.tables.length;i++){
      tableMap[`table_${this.tables[i]}`] = i+1
    }
    this.tableMap = tableMap
  }
}

測試結果
computed的值是可以被watch的,但watch一定要是有異動才會被觸發
所以要設定初始值,並要讓連動的相關變數都被計算
初始值要放在mounted內去設定,不要在data內去直接指定