2022年4月28日 星期四

vue3繼承實作

在使用物件導向的程式語言 

class繼承一直是很常使用的架構


在vue2 透過extends vue元件做到做元件繼承

最到類似class繼承後許多方便的功能

使用繼承的目的是

1.定義好通用的props,data,computed 繼承者都可直接使用

2.定義好通用的methods

  如果繼承者有定義相同method會覆蓋掉底層的

3.生命周期

  在底層的會被執行,繼承者有定義相同的也會被執行

透過維護底層元件讓繼承者都可得到對應的功能


vue3 如果使用option api寫還是一樣保有使用extens的功能

但若採用新的composition api則extends就變的無效

以下紀錄在composition api做到類似原來繼承的功能


使用範例

底層元件vAsset.ts

// 設定props資料,繼承者需取這來產生props

export const propsData = {

  parentUid: {

    type: String,

    default: null

  }

}

// 用來產生props

export const injectProps = () => (propsData)

export function vAsset () {

  return {

    ....所有定義好要給外部使用的功能

  }

}

繼承元件vObj.ts

import {vAsset, propsData as myPropsData} from './vAsset'

// 建立包含繼承的prop與自己新增的props資料

export const propsData = {

  ...myPropsData,

  title: {

    type: String,

    default: 'title'

  }

}

// 產生真正提供使用來inject props的function

export const injectProps = () => (propsData)

export function vObj () {

  const oz = vAsset()

  onMounted(() => {

    // 使用到上層元件的功能可以用oz.xx取用有開放的部份

    oz.on('Modal.CMD.Show', (id:string, boolean:boolean, myopenerId = '') => {

      ...

    })

  })

  // 在這裡建立要使用的data或method...

  let modalData = reactive({})

  // export 出去同時包含要繼承進來的所有功能

  return {

      // data

      modalData,

      ...oz

  }

}



在vue元件上使用繼承功能myinstance.vue

<script setup lang='ts'>

import { vObj, injectProps } from 'src/core/vObj'

const {uid, attrs, isVisible} = vObj()

// 定義props, 除了自己本身的還要inject繼承進來的部份

const props = defineProps({

  ...injectProps(),

  host: {

    type: String,

    default: ''

  }

})

onMounted(()=>{

  console.log(`onMounted id=${attrs.id} uid=${uid.value} parent=${props.parentUid}`)

})

</script>

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是 前端頁面拿到的設定變數

2022年4月9日 星期六

墾丁

 去年夏天 妹妹國小畢業

原本計畫好 要一起騎車環島 因為疫情不能出發

上禮拜騎車去東港 就跟妹妹說好

有機會我們騎車去墾丁



看著今天的好天氣 也過了連續假期

不會有太多的人車 往墾丁

選定今天 我們就要出發


早上8點半出門 去康是美給妹妹買了防曬

這次我們走一號省道 沿著88底下走

才剛往大寮的路上 停紅綠燈 就聽到音樂聲

跟妹妹觀察著是哪台摩托車在放音樂


到了下一個紅綠燈 聽到了是旁邊的一個阿伯在放音樂

馬路很吵雜 我們很用力的要聽出是什麼音樂

妹妹很厲害 這樣吵雜的路上還能聽出

是草蜢的寶貝對不起


過了大寮 過了萬丹 88走到底就是潮州

繞出市區回到一號省道 往南就是墾丁的方向


過了南州 過了佳冬 那條筆直寬廣的路 是戰備跑道

知道 要到枋寮了

先在佳冬的全家停下來休息 吃個冰 再出發



枋山的7-11海豚灣門市 是預定的休息點

去年規劃的機車環島行程 是把這當作第一個休息站

海豚灣是很熱門的中繼點

許多單車或重機 都會停在這裡休息

從這開始

路旁開始可以看到海

也開始看到有一些咖啡車 就在路邊


妹妹看到海 好興奮這是他比較懂事後

這麼近的來到海邊

路邊隨意一停 就可以拿出相機拍照



一路上妹妹唱著歌

11點多 進了恆春

走中山路恆春老街 在西門停了下來

這裡是海角七號裡 開場小巴士過不了的那個城門

穿過了城門再往前 就到了南門

沒有要吃飯 我們就再繼續往墾丁的方向前進



中午 墾丁大街沒什麼人

路邊看到麥當勞 看起來比印象中舊了許多

還以為已經不營業了 以前假日這裡可是超多人潮聚集的地方

今天幾乎都沒什麼人

妹妹餓了 我們就到麥當勞吃午餐

休息吹冷氣 到1點半多 就要離開

繼續出發到鵝鑾鼻 這是今天的目的地

讓妹妹看到這台灣的最南端

鵝鑾鼻的燈塔 還有地標 都是小時候爸媽帶我們來

還有大學後跟同學來時拍照的地點

看著時間不早 妹妹想去沙灘玩沙

就離開鵝鑾鼻 回程



才騎出不久 路邊就看到了可以下到沙灘的地方

停好車 帶妹妹下去玩

看妹妹玩的超開心的 還把褲子都弄濕了

3點半多離開沙灘 再騎回到麥當勞 讓妹換好褲子

就一路回高雄 還有125公里的路程

感覺妹累了 趴在我的背上 繼續唱著歌

他說 他的曲庫快翻完了

還是一路唱歌回到高雄

妹妹想吃焗烤 在地圖上找到大明路就有一家

滿足的吃飽 結束我們開心的一天

騎車 是我們最喜歡的旅遊方式

希望有機會 可以實現我們還沒完成的環島




2022年4月6日 星期三

ansible 檢查檔案是否存在

在ansible內需要檢查檔案是否存在

以當作條件決定後續工作是否執行

檢查遠端主機檔案跟執行local端檔案

是有差異的


檢查要控制的遠端主機檔案(被ansible控制的主機)

- name: check the nginx template config exist

  stat:

    path: '{{遠端檔案路徑}}'

  register: stat_result


檢查主控主機上的檔案(也就是執行ansible的主機)

- name: check the nginx template config exist

  delegate_to: localhost

  stat:

    path: '{{本機檔案路徑}}'

  register: stat_result

作檔案檢查要特別注意不要使用become:true

以root權限執行

2022年4月5日 星期二

ansible 以ssh clone bitbucket git repository

以ansible git module 要git clone 一個repository

過去都會以https方式去 直接綁定帳密去clone最為簡單

- name: clone myrepo

  git:

    repo: 'https://{{git_user}}:{{git_password}}@bitbucket.org/myacc/myrepo.git'

    dest: '{{target_path}}'

    version: 'master'

    clone: true

但因為安全性考量bitbucket在2022/3/1後就不支援這樣直接綁帳密方式取得

改用ssh方式取

作業之前需先把要操作的主機的ssh設定到bitbuket的repo設定上

在要操作的主機

1.建立ssh key

  ~/.ssh ssh-keygen

2.複製public key內容

  cat id_rsa.pub

  複製內容

3.到bitbucket repo設定加入access_keys

  bitbuckey/myrepo/access_keys 加入

在ansible host上執行腳本

- name: clone myrepo

  git:

    repo: 'git@bitbucket.org:{{myacc}}/myrepo.git'

    dest: '{{target_path}}'

    version: 'master'

    clone: true

    accept_hostkey: yes

注意這裡多加上了accept_hostkey的設定

2022年4月3日 星期日

騎車去東港

爸爸: 妹妹這裡左轉一直騎就可以到東港了

妹妹: 好啊 好久沒去了 我們去東港


清明連假4天 掃墓是最後一天

待在家幾天也無聊了 中午過後

想說沒事去夢時代晃晃

沿著凱旋路騎 在中山路口等紅綠燈

臨時又很隨性的改往東港出發



沿著中山路 接沿海路 這裡大車多

總想快快騎過這段

小港,林園,新園過去就是東港

沿著光復路 再轉往中正路市場

帶妹來沙蝦肉圓 難得他可以把整份吃完

再往大鵬灣去

遊客服務中心 拍拍照

再往華僑市場 買了旗魚黑輪 就要回家了

妹妹喜歡坐摩托車 吹風唱歌

出來 去哪 不是重點 騎車唱歌才是目的 




2022年4月1日 星期五

ansible 在使用loop或with_items時加入條件when判斷

目前有一個使用情境

在管理多台主機的nginx設定時

要寫一個更新nginx config設定檔的腳本

因為是要套用在多台主機上

因為設定檔 都會以j2樣板方式寫好再套用各主機資料產生config檔案

所以會先準備好多個樣板

ex:

api.conf.j2 設定api相關

web.conf.j2 設定web相關

service.conf.j2 設定其他各式服務

socket.conf.js 設定 socket服務


但也因為各主機屬性不一樣

並不是所有的主機都會同時有這些設定檔案


因此在寫ansible控制腳本時就會需要使用迴圈

判斷如果樣板檔案存在就使用樣板產生設定檔案的功能


- name: check the nginx template config exist
  with_items:
    - src: '../../files/nginx/default.conf.j2'
      dest: '/etc/nginx/sites-available/default.conf'
    - src: '../../files/nginx/conf/web.conf.j2'
      dest: '/etc/nginx/sites-available/conf/web.conf'
    - src: '../../files/nginx/conf/api.conf.j2'
      dest: '/etc/nginx/sites-available/conf/api.conf'
  delegate_to: localhost
  stat:
    path: '{{item.src}}'
  register: stat_result
- name: build the nginx template config
  become: true
  with_items: '{{stat_result.results}}'
  template:
    src: '{{item.item.src}}'
    dest: '{{item.item.dest}}'
  when: item.stat.exists
- name: restart nginx
  service:
    name: nginx
    state: restarted

說明
以兩段工作來執行
第1段是檢查所有檔案是否存在
第2段是以上面檢查的結果判斷是否執行樣板render
第1段以stat來檢查檔案得到的回應stat_result
取得的 stat_result.results 為loop結果
{
  item: 即為with_items的一項,
  stat: {
    exists: true|false 是否存在
  }
}
第2段就可以以stat_result.results當作迴圈的內容
以when判斷是否執行
這樣 就不會因為檔案不存在由造成loop有錯誤

另外當執行loop發生錯誤
loop 內其他的正常項目還是都會作完
但下一段動作會因為錯誤而不執行
如同sample code內 如果loop出錯
那下一個重啟nginx的動作將不會被執行

這裡有一個特別注意的地方是
要檢查本機上的檔案是否存在
需要加上delegate_to: localhost
而且不可以使用root
也就是不可使用become:true