If you have to design a responsive design website(RWD), there is a easy class to judge with the various kinds of devices.

let breakPoints = {
points :{
phone: 320,
tablet: 768,
desktop: 1024,
},

isM: function () {…

在逛電商網站時,行銷頁常會點選商品開新視窗,導致開啟一大堆擾人,又占用瀏覽器記憶體。
為了解決這個問題,可以用以下方式解決

宣告兩個變數

flag判斷現在是否已經開新視窗了,如果是ture就更新該視窗。
oldWindows存舊的router所開的新視窗

data() {
return {
flag:false,
oldWindows: "",
}
},

使用者點選開新視窗的function

<a @click="openTab($event,{name: 'xxxx', params: {yyy: id}})">

openTab function

如果第一次開新視窗,不用將舊的視窗關閉,以this.flag作為檢查機制
this.oldWindows存下開新視窗的function
第二次開以後,皆會先關掉之前this.oldWindows開的視窗,重新開啟

如此一來,使用者就不會一直開啟一堆視窗了

openTab(e,route) {     if(this.flag==false){
var routeData =this.$router.resolve(route);
this.oldWindows = window.open(routeData.href,'_blank');
this.flags=true;
}else{
this.oldWindows.close();
var routeDataNew =this.$router.resolve(route);
this.oldWindows = window.open(routeDataNew.href,'_blank');
this.flag=true;
}
},

reload,created時將flag更新為預設的false

created() { this.flag=false;

},

第一個APP,從 main()開始

Flutter從main function開始執行runApp這個function。
runApp()會將給定的widget填滿整個螢幕畫面,一般會傳遞的一個MyApp widget物件。

void main() => runApp(MyApp());

直接執行一個widget

runApp()會將給定的widget填滿整個螢幕畫面,這裡則是直接執行一個Center widget填滿畫面。

Center是一個widget,讓child(Text widget)置中
Text,用來顯示文字,這裡需額外設定textDirection文字方向為由左至右,

import 'package:flutter/material.dart';void main() => runApp(Center(
child: Text(
'Hello Flutter',
textDirection: TextDirection.ltr,
)));

Widget

Flutter裡所有看得到的畫面元件都是Widget。
widget組成APP的樹狀結構,樹狀中有父子關係(parent Widget and children Widgets)

一個常見的樹狀結構:

圖片來源:flutter-community Widget — State — BuildContext — InheritedWidget

BuildContext

Context是Widget樹狀結構中,其中一個Widget下的一組Widge(parent Widget下有多個children Widgets)。
context作為 Widget 樹狀結構的一部分,當APP畫面呈現時,這組Widge被參照引用。

widget有兩種,StatelessWidget和StatefulWidget

StatelessWidget是一般靜態的Widget

資料依賴父節點提供,一旦建立就不會有任何變化
典型的 Widget包含Text、Row、Column 和 Container 等,只在創建時將一些參數資料傳遞給它們來創建。
參數包含尺寸、顏色、文字等等
stateless widget 只有在 loaded/built 時才會重繪一次,任何事件、使用者操作都無法改變Widget

StatefulWidget是動態更新的Widget

它有State的生命週期,可以讓Widget產生變化

例如官方範例的計數器就是個StatefulWidget
數字會根據使用者點擊按鈕而逐漸累加

在網頁前端中常作的接API>拿到資料>tableView reloadData
要在Flutter APP實現的話,就會用到StatefulWidget

State 生命週期

State關係到APP的畫面呈現(Layout)和使用者的行為操作(behavior)
藉由State的改變來Build App呈現的 Context

生命週期圖


function parsetUrlVariable(key, url)
{
let match = url.match('[?&]' + key + '=([^&]+)');
return match ? decodeURI(match[1]): null;
}
function getJsonFromUrl(url) {
if(!url) url = location.href;
var question = url.indexOf("?");
var hash = url.indexOf("#");
if(hash==-1 && question==-1) return {};
if(hash==-1) hash = url.length;
var query = question==-1 || hash==question+1 ? url.substring(hash) :
url.substring(question+1,hash);
var result = {};
query.split("&").forEach(function(part) {
if(!part) return;
part = part.split("+").join(" "); // replace every + with space, regexp-free version
var eq = part.indexOf("=");
var key = eq>-1 ? part.substr(0,eq) : part;
var val = eq>-1 ? decodeURIComponent(part.substr(eq+1)) : "";
var from = key.indexOf("[");
if(from==-1) result[decodeURIComponent(key)] = val;
else {
var to = key.indexOf("]",from);
var index = decodeURIComponent(key.substring(from+1,to));
key = decodeURIComponent(key.substring(0,from));
if(!result[key]) result[key] = [];
if(!index) result[key].push(val);
else result[key][index] = val;
}
});
return result;
}

參考資料:

https://stackoverflow.com/questions/8486099/how-do-i-parse-a-url-query-parameters-in-javascript


install

$ npm i vue-meta

use in main.js

import Vue from 'vue'
import VueMeta from 'vue-meta'
Vue.use(VueMeta)

Vue template

<template>
<div class="Home"></div>
</template>
<script>
export default {
name: 'home',
metaInfo: {
title: 'Home',
},
}
</script>

Vue template load by axios

<template>
<div class="Home"></div>
</template>
<script>
export default {
name: 'home',
data() {
return {
title: this.getMetadata(),
}
},
methods: {
async getMetadata() {
const result = await axios.get(this.GLOBAL.API_URL + 'meta_api.php', { params: { url: this.$route.params.url } });
let metadata = result.data.data[0];
this.metadata = metadata;
}
},
metaInfo() {
return {
title: this.title,
}
}
}
</script>

有一物件中存有Null時,我們希望清除並重新排序

let Obj99 = {
qq99: null,
w995: 54,
qq98: 0,
qq497: 1,
c992: 168
}

利用!判斷是否為Null,如果是的話就刪除

接著Sort by Key

function Obj_remove_Null(obj) {
for (let null_element in obj) {
if (!obj[null_element])
//delete null
console.log("null_element", null_element)
{
delete (obj[null_element])
}
return (
(
//Sort JavaScript object by key
Object.keys(obj).sort().reduce((r, k) => (r[k] = obj[k], r), {})
)
)
}
}
console.log("Obj_remove_Null",Obj_remove_Null(Obj99));

var array = [9, 8, null, 2, “”, undefined, 3,,,,,, 4,, 4,, 5,, 6,,1,2,null, undefined,3,,3,,,0,,,[],,{},,5,,6,,,,];

1.use filter()

var filtered = array.filter(function (elements) {
return elements != null;
});
console.log(filtered);

2.use push() and splice()

//clear null ,"", undefined ,0

len = array.length;

// copy
for(i = 0; i < len; i++ ){
array[i] && array.push(array[i]);
}


// cut
array.splice(0 , len);

console.log("use push() and splice()",array);

3.using ES6 and push()

//clear null ,"", undefined ,0
temp = [];

// copy to new array
for(let i of array )
i && temp.push(i);

array= temp;

console.log("use ES6",array);

需要動態載入外部JS或CSS時,我們可以直接操作document.head 來載入新的JS/CSS與移除舊的JS/CSS。

透過document.createElement(‘link’) 我們可以創造一個外部連結,接著指定它的檔案類型參照(rel)與網址,利用appendChild()來動態載入
而在Vue中,因為沒有reload,會一直連進同一頁,會重覆動態載入到同樣的檔案,因此需要在載入前,先把同樣檔名的檔案,用remove()來刪除。

可以搭配querySelectorAll或 querySelector來匹配link的href要remove的檔案。

匹配規則如下:

[id^='https://test'] 匹配https://test為開頭的所有檔案

[id$='xxx.css'] 匹配xxx.css為結尾的所有檔案

[id*='.css'] 匹配包含.css的所有檔案

參考Function:

<template>
<div>
<button @click="appendFile">Click me to add css file</button>
</div>
</template>
<script>
export default {
methods : {
appendFile(){
document.querySelectorAll('link[href$="myfile.css"]').forEach(item => item.remove());
let file = document.createElement('link');
file.rel = 'stylesheet';
file.href = 'myfile.css'
document.head.appendChild(file)
}
}
}
</script>

要在網站建立多語系版本,在vue可以使用vue-i18n來建立各個語言的語言檔來做切換

安裝npm套件

npm install vue-i18n --save

設定i18n

在src內建立一個i18n資料夾存設定檔和各語言的語言檔

檔案路徑:src\i18n\lang.js

中日文設定檔

import Vue from 'vue'
import VueI18n from 'vue-i18n'
// 使用VueI18n
Vue.use(VueI18n)
// 自訂語言檔
import ja from './ja.js'
import tw from './tw.js'
// 使用localStorage取得預設語系
const locale = localStorage.getItem('locale') || "tw";
// 建立 VueI18n …

York Chen

Cooking is an indispensable part of life. It is a taste that can’t be forgotten.

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store