可以任意增加或刪減想要比較的股票
完成動態的股票績效圖
// [id].vue
const stockChart2Api = `https://financialmodelingprep.com/api/v3/historical-price-full/meta?timeseries=365&apikey=${fmp}`
const stockChart3Api = `https://financialmodelingprep.com/api/v3/historical-price-full/googl?timeseries=365&apikey=${fmp}`
const getDataApi=()=>{
// ...略
const getSecondChart = axios.get(stockChart2Api)
const getThirdChart = axios.get(stockChart3Api)
}
const stockChart2 = ref()
const stockChart3 = ref()
const stockChart2Rev = computed(() =>
stockChart2.value ? stockChart2.value.reverse() : []
)
const stockChart3Rev = computed(() =>
stockChart3.value ? stockChart3.value.reverse() : []
)
const stockChartFix2 = computed(() => {
return fix(stockChart2Rev.value)
})
const stockChartFix3 = computed(() => {
return fix(stockChart3Rev.value)
})
先移除昨天示範用固定的股票線圖
// [id].vue
<ClientOnly>
//增加股票
<div class="flex items-center ">
<font-awesome-icon
:icon="['fas', 'circle-plus']"
size="xl"
style="color: #157d7f"
@click="searchAdd = !searchAdd"
class="mb-2"
/>
<vue3-simple-typeahead
id="typeahead_add"
placeholder="搜尋股票..."
v-if="searchAdd"
class="w-[300px] m-4 p-1 bg-white rounded shadow :active:border-white"
:items="checkData"
:minInputLength="1"
v-model="searchAddStock"
@onInput="onInputEventHandler"
@keydown.native.enter="changeChart('add')"
@selectItem="selecAddtItem"
>
<template #list-item-text="slot">
<div class="">
<span
class="inline-block w-[300px] bg-white rounded shadow ms-4 mb-1"
v-html="slot.boldMatchText(slot.itemProjection(slot.item))"
></span>
</div>
</template>
</vue3-simple-typeahead>
</div>
// 減少股票
<div class="flex items-center">
<font-awesome-icon
:icon="['fas', 'circle-minus']"
size="xl"
style="color: #157d7f"
class="inline-block"
@click="searchRemove = !searchRemove"
/>
<vue3-simple-typeahead
id="typeahead_remove"
placeholder="搜尋股票..."
v-if="searchRemove"
class="w-[300px] m-4 p-1 bg-white rounded shadow :active:border-white"
:items="checkData"
:minInputLength="1"
v-model="searchRemoveStock"
@onInput="onInputEventHandler"
@keydown.native.enter="changeChart('remove')"
@selectItem="selectRemoveItem"
>
<template #list-item-text="slot">
<div class="">
<span
class="inline-block w-[300px] bg-white rounded shadow ms-4 mb-1"
v-html="slot.boldMatchText(slot.itemProjection(slot.item))"
></span>
</div>
</template>
</vue3-simple-typeahead>
</div>
</ClientOnly>
<script setup>
const route = useRoute()
const id = route.params.id
// key
const fmp = import.meta.env.VITE_KEY_FMP
// API
const stockChartApi = `https://financialmodelingprep.com/api/v3/historical-price-full/${id}?timeseries=365&apikey=${fmp}`
const getDataApi=()=>{
const getFirstChart = axios.get(stockChartApi)
return [getFirstChart]
}
// 股票圖表資料
const stockChart = ref()
const stockChartRev = computed(() =>
stockChart.value ? stockChart.value.reverse() : []
)
// 增加&刪減股票
const searchAdd = ref(false)
const searchRemove = ref(false)
const checkData = ref([])
const searchAddStock = ref('')
const searchRemoveStock = ref('')
const MultiChart = ref([])
watchEffect(() => {
MultiChart.value = stockChartFix
? [
{
name: `${id}`,
data: stockChartFix.value,
},
]
: []
})
// 輸入關鍵字時找出相關名稱股票
const searchApi = computed(() => {
return `https://financialmodelingprep.com/api/v3/search?query=${searchAddStock.value}&limit=10&exchange=NASDAQ&apikey=${fmp}`
})
// 增加該筆股票的過去一年股價
const addChartApi = computed(() => {
return `https://financialmodelingprep.com/api/v3/historical-price-full/${searchAddStock.value}?timeseries=365&apikey=${fmp}`
})
// item是這個callback的預設參數 就是input的值
const selecAddtItem = (item) => {
searchAddStock.value = item
}
const selectRemoveItem = (item) => {
searchRemoveStock.value = item
}
const onInputEventHandler = () => {
axios.get(searchApi.value).then((res) => {
checkData.value = res.data.map((v) => v.symbol)
})
}
const changeChart = async (change) => {
if (change === 'add'){
let newChart = []
await axios
.get(addChartApi.value)
.then((res) => {
newChart = res.data.historical
})
.catch((rej) => {
console.log(rej)
})
newChart = newChart.reverse().map((v) => {
const dateTimeString = v.date // 日期
let milliseconds // 換算後的時間
const dateObject = new Date(dateTimeString)
milliseconds = dateObject.getTime()
return [milliseconds, v.close]
})
MultiChart.value.push({ name: searchAddStock.value, data: newChart })
}else if(change === 'remove') {
MultiChart.value = MultiChart.value.filter(item => item.name !== searchRemoveStock.value)
}
}
const chartOptionsMulti = computed(() => {
return {
//... 略
series: MultiChart.value,
}
})
<script>
在<template>
先增加2個預先輸入搜尋框及2個font-awesome的圖標(+,-)
圖標只有前端有
所以外面要加一層<ClientOnly>
再來是績效圖的設定項chartOptionsMulti
裡面放資料的地方也就是series
只吃array
那在進來這個股票頁的時候只有該股票的績效
所以array一開始只有一筆資料[{name: ``${id}``,data: stockChartFix.value, }]
而這筆資料是等打完api之後才會取得
該用computed讓它自動更新該筆資料
但因為array之後還會增加或刪除元素
computed過的資料不能直接去做更改
所以改用watchEffect去操作MultiChart
這個array
保有增減資料的彈性
之後就是在預先輸入搜尋框
輸入要增加或刪減的股票名稱
再用push新增或filter過濾
就完成動態的績效比較圖了!!
小結:
搜尋框其實有個小bug
(就預先輸入框出現的時候,會推到下面的block導致其他畫面跟著移動,而不是覆蓋過去)
其他地方可能或多或少也有吧!
但重要功能先出來
還是比較重要
還是來找一天處理
主題訂為"修理這些微小又確切的bug"...嗎?