JavaScript-提升(Hoisting)

javascript的執行環境分為兩階段,會先經歷創建階段(creation),之後才正式進入程式碼執行階段(exection)

在創建階段中會將函式及變數先設置在記憶體中,而這個動作稱作「提升(hoisting)」,另外細分解釋函式提升變數提升

函式提升

在執行任何程式碼前,JavaScript 會把「函式宣告初始化」放進記憶體裡面,意思是函式{}的內容都會在創建階段放在記憶體中。

變數提升

在創建階段,電腦的記憶體為a空出記憶體,可是他還不知道他的值為何,會先給予一個undefine的值,等到執行階段賦值時,才會將a的值放進記憶體中。也因此下方案例,印出a並不會出錯,只是它的值為undefine。

程式實際執行程序

  1. 首先在creation創建階段,會做:

    • 函式提升-在記憶體中創建函式b(){…}
    • 變數提升-在記憶體中創建出變數a,並給予預設值undefined
  2. 接著開始進入exection執行階段,由上而下一行一行編譯讀取程式碼

    • 印出b的值(將b函式內容印出來)
    • 呼叫b()
    • 印出a的值(此時的值仍為預設值undefined)
    • 設定a的值為’I am a’
    • 印出a的值(此時的值為’I am a’)
1
2
3
4
5
6
7
8
console.log(b); 
function b(){
console.log('called b.');
}
b();
console.log(a);
var a = 'I am a';
console.log(a);

完整執行結果如下

JavaScript-全域環境與全域變數

不論何時執行JavaScript程式, 程式碼都是在執行環境(execution context)裡面建立和執行。

(執行環境:一個wrapper,把正在執行的程式碼包在執行環境裡面。)

然而相較於執行環境,另外有一個基礎執行環境(base execution context),又稱做全域執行環境

全域(Global)

‘Global’ means ‘not inside a function’
簡而言之,當程式碼或變數不再函式中,就是全域的。

全域環境

在全域執行環境中,JavaScript會自動創造兩個東西:

  • Global Object:全域物件
  • this:一個特殊的變數

    全域物件

    「全域物件」,可以在任何地方被取用。

this變數

在沒有寫任何程式碼的情況之下,啟用window瀏覽器執行,這時候全域執行環境中會自動產生一個全域物件-window物件,以及this這個特殊變數。

而在瀏覽器的全域的情況之下,this即為window物件。

同一個瀏覽器,開啟另一個分頁,就會創建另外一個全域執行環境,也會獨立產生一個全域物件及this變數。

若用不同的瀏覽器、伺服器(例:firefox),也會產生一個全域物件-firefox,而this變數則為這個全域物件-firefox。

JavaScript-name/value及物件概念

name/value 組合

在JavaScript中,要先知道「name/value」組合,在同個作用域中,name(名稱)不能被重複使用,同樣的name只能有一個,而每一個name(名稱)會對應到唯一的value(值)。

1
2
//這是一個簡單的「name/value」組合
address:'1 Main St.';

JavaScript物件

JavaScript中的物件,是由「name/value」組合定義而成的。
雖然說一個name會對應到唯一的value,可是這個value卻又可以是一到多個「name/value」組合而成的。

1
2
3
4
5
6
7
8
9
//這個address物件的value是由多個「name/value」組合而成的
address:{
street:'main',
number:100,
apartment:{
floor:3;
number:301;
}
}

資料來源

克服JS奇怪的部分

JavaScript-語法解析器、執行環境、詞彙環境

語法解析器(syntax parser)

包含直譯器、編譯器,會一個字一個字讀取並辨識程式碼是否有效,再將之轉換成為電腦可以解讀的指令

詞彙環境(lexical environment)

程式碼在程式中實際的所在位置,對於某些程式語言非常重要,例:JavaScript。

因為當systax parser在解讀並轉換程式碼時, 會考量該變數、函式的lexical environment,而影響到它實際在記憶體中的位置或是跟其他變數、函式作用的關係。

1
2
3
function hello(){
var a = 'Hello';
}

上述程式碼為例,變數a的lexical environment就是hello()這個函式。

執行環境(execution context)

一個程式碼中有多個lexical environment,因此execution context負責協助管理正在執行的程式,如同一個wrapper,包含我們撰寫的程式碼,以及syntax parser執行轉換的程式碼。

Webpack-環境安裝與基礎運用

開發環境

Webpack是在Node.js環境下去執行的自動化工具,因此若要使用Webpack,首先電腦中必須安裝有Node.js開發環境

安裝Node.js,請參考文章:NVM-安裝及控管Node.js的版本

專案建立

  • 先新增一個空的資料夾,並使用vsCode編譯器打開該資料夾
  • 在資料夾中新增一個檔案,命名為webpack.config.js

正式安裝Webpack

接著正式安裝,可以先到Webpack getting staretd頁面,參考官方說明,執行後續載入webpack的流程

  • 首先建構初始化專案

    1
    npm init -y
  • 初始化建構執行完畢後,會看到專案中新增了一個package.json檔案,這個檔案中紀錄整個前端專案中用了哪些套件、指令。非常重要!不可刪除!

  • 接著安裝webpack
    1
    npm install webpack --save-dev

  • Webpack4之後的版本都需要額外再安裝webpack-cli
    1
    npm install webpack-cli --save-dev

  • 上述安裝完畢後,會發現專案中有幾處變更,如下圖
    • 專案中多了一個node.modules的資料夾,裡面存放webpack在執行時,會依賴的其他第三方套件。
    • 在可以在package.json檔案會發現多紀錄該專案使用多webpack、webpack-cli版本

webpack檔案建置

  • 新增src資料夾,其中包含index.js檔案,在檔案中寫一些ES6程式碼
  • 參考官網的範例程式碼,複製、貼上到檔案中

    • path:path主要負責路徑處理的轉換,這裡做的事情,就是從node.js的模組抓進webpack中使用
    • entry:高版本的Javascript
    • output:輸出的版本,(檔案命名可以修正為index.bundle.js)
      1
      2
      3
      4
      5
      6
      7
      8
      9
      const path = require('path');

      module.exports = {
      entry: './src/index.js',
      output: {
      path: path.resolve(__dirname, 'dist'),
      filename: 'bundle.js'
      }
      };
  • package.json檔案的script部分加入 “build”: “webpack”

    啟用Webpack

  • 在vscode的terminal輸入指令,啟動webpack
    1
    npm run build

  • 自動將原先高版本的JS檔案-index.js,轉變為在dist資料夾中的index.bundle.js內容,可以看到轉換後仍是ES6語法,因為還差掛載loader作轉換

使用Babel-loader轉換語法

為了讓webpack識別原先的ES6程式碼內容,因此需要掛載Babel-loader

進到github開源頁面,依照提示安裝Babel-loader

  • 將下方指令貼到vscode terminal中,”-D”會自動寫入package.json中

    1
    npm install -D babel-loader @babel/core @babel/preset-env webpack
  • 接著來編輯webpack.config.js,將程式碼複製貼上

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    module: {
    rules: [
    {
    test: /\.m?js$/,
    exclude: /(node_modules|bower_components)/,
    use: {
    loader: 'babel-loader',
    options: {
    presets: ['@babel/preset-env']
    }
    }
    }
    ]
    }
  • 最後再執行一次webpack指令

    1
    npm run build

可以看到右邊是重新編譯後的內容,將原先左邊高版本ES6的箭頭函示,編譯為JS基本的function語法

在HTML中引入

最後,在HTML中引入js檔時,僅需引入一隻webpack bundle處理後的JS檔案

執行不同版本的webpack編譯

package.json中的scripts中新增不同的簡化指令內容(命名可以不受限,但最好是大家有共識的命名方式)

  • watch:監看
  • start:開發版本
  • deploy:發行版本,會進行壓縮
    1
    2
    3
    4
    5
    6
    7
    "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1",
    "build": "webpack",
    "watch": "webpack --mode development --watch",
    "start": "webpack --mode development",
    "deploy": "webpack --mode production"
    },

參考來源

YouTube影片:Webpack 前端自動化開發超入門

Webpack-前端建置工具的發展背景及入門介紹

Webpack是當下流行的「前端建置工具」之一。

首先了解建置工具

建置工具出現的來龍去脈?

過去:
早期前端工程師寫網頁,僅透過前端三大元素「JavaScript、CSS、HTML」開發web應用。

現今:
近年前端發展出許多新思維,出現了「模組化」的概念、「新框架」的出現、「新語言」的誕生,讓傳統的作法不再流行,各種可以加強開發效率的新工具出現。

  • 模組化:模組化是將一個複雜的系統,分解為多個模組以方便程式開發。例:ES6模組化是國際標準組織ECMA提出的JavaScript模組化標準,他在語言層面上實現模組化,成為瀏覽器和伺服器通用的模組化解決方案。
  • 新框架:在web應用變的龐大時,直接操作DOM會使程式變得複雜難以維護,因此出現React、Vue、Augular前端框架。
  • 新語言:ES6、TypeScript、Flow、SCSS…

然而,前端技術發展之快,卻有一個共同點:這些工具的原始碼無法直接執行,必須透過「轉換」才可以正常執行,因此,「建置工具」就誕生了。

建置工具實際做了什麼?

「建置」就是將原始程式碼,轉換成可以執行的JavaScript、CSS、HTML。

  • 程式轉換:將TypeScript編譯為JavaScript,將SCSS編譯為CSS。
  • 檔案最佳化:壓縮JavaScript、CSS、HTML程式,壓縮合併圖片。
  • 程式分割:分析首頁不需要執行的部分程式,讓其非同步載入。
  • 模組合併:採用模組化建置的專案中的有多個模組、檔案,透過建置功能,將模組合併為一個檔案。
  • 自動更新:監聽本機端程式碼的變動,自動重新建置、更新瀏覽器。
  • 程式驗證:在程式被傳送到倉庫前,需要驗證程式是否符合標準,以及單元測試是否通過。
  • 自動發布:更新程式後,自動建置出現上發布程式,並傳輸給發布系統。

「建置」的目的最主要就是工程化、自動化。

常見的「建置工具」

按誕生的時間排序

  • Npm Script:Node.js附帶的套件管理員
  • Grunt:自動化執行依賴的工作
  • Gulp:以串流為基礎的自動化建置工
  • Fis3:整合各種Web開發需要的建置功能
  • Webpack:包裝模組化JavaScript的工具
  • Rollup:專注於ES6的模組包裝工具

時空背景:

  • 在Npm Script和Grunt時代,Web開發要做的事情變多、流程變複雜,自動化的思維興起,用於簡化流程。
  • 在Gulp時代,新語言出現,流式處理思想出現是為了簡化檔案轉換的流程。
  • 在Webpack的時代,由於單頁應用的流行,網頁的功能和實現程式變得複雜、龐大,因此Web開發相模組化改進。

    Webpack究竟是什麼?

    專注於建構模組化的專案

    在Webpack裡的所有檔案皆被視為模組,透過Loader轉換檔案,透過Plugin植入鉤子,最後輸出為一個由「多個模組合成的檔案」。

    所以一個專案中的所有檔案,包含JavaScript、CSS、SCSS、圖片、範本,在經過Webpack的處理,最後會輸出為瀏覽器可以使用的靜態資源。

使用方法如下:

1
2
3
4
5
6
7
8
module.expert={
//所有模組的入口,Webpack從入口開始遞迴解析出所有依賴的模組
entry: './app/js',
output:{
//將入口所依賴的所有模組包裝成一個檔案bundle.js輸出
filename: 'bundle.js'
}
}

參考資料來源

  • JS高手昇華之路Webpack是唯一的路徑-吳浩麟 著

Vue-(十)表單綁定

10-1.文字輸入:text input與textarea (影片)

單行文字綁定,用input

  • 大括號雙向綁定
    1
    2
    3
    4
    <div id="app">
    <input type="text" v-model="msg"></input>
    <h1>{{msg}}</h1>
    </div>
1
2
3
4
5
6
new Vue({
el:"#app",
data:{
msg:'',
},
})
  • input事件偵聽
    該元素的value用動態綁定,當input事件發生時,執行change函式
    1
    2
    3
    4
    <div id="app">
    <input type="text" :value="msg" @input="change"></input>
    <h1>{{msg}}</h1>
    </div>

event.target找到事件發生的元素,其value則是user剛剛輸入的資料

1
2
3
4
5
6
7
8
9
10
11
new Vue({
el:"#app",
data:{
msg:'',
},
methods:{
change(event){
this.msg = event.target.value;
}
}
})

多行文字綁定,用textarea

1
2
3
4
<div id="app">
<textarea v-model="msg"></textarea>
<h1>{{msg}}</h1>
</div>

但是換行字元’\n’無法被反映到h1標籤中,因此可以改用pre標籤(preserve)

1
2
3
4
<div id="app">
<textarea v-model="msg"></textarea>
<pre>{{msg}}</pre>
</div>

或是在css中定義

1
2
3
4
<div id="app">
<textarea v-model="msg"></textarea>
<h1>{{msg}}</h1>
</div>

1
2
3
h1{
white-space: pre;
}

10-2.打勾按鈕:checkbox (影片)

綁定單個屬性boolean值

1
2
3
4
5
6
7
<div id="app">
<input type="checkbox" v-model="status">Agree</input>
<br/>
<h3>{{status}}</h3>
<br/>
<button @click="submit">Submit</button>
</div>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
new Vue({
el:"#app",
data:{
status:false,
},
methods:{
submit(){
if(this.status){
alert("Success!");
}else{
alert("Please agree first!");
}
}
}
})

綁定至array中

1
2
3
4
5
6
7
8
9
10
11
<div id="app">
<h2>請選擇可以送達的時間:</h2>
<input id="optA" type="checkbox" v-model="options" value="Morning"/>
<label for="optA">Morning</label>
<input id="optB" type="checkbox" v-model="options" value="Afternoon"/>
<label for="optB">Afternoon</label>
<input id="optC" type="checkbox" v-model="options" value="Evening"/>
<label for="optC">Evening</label>
<br/>
<h3>{{options}}</h3>
</div>
1
2
3
4
5
6
new Vue({
el:"#app",
data:{
options:[],
},
})

10-3.圓點單選按鈕:radio (影片)

1
2
3
4
5
6
7
8
9
<div id="app">
<input id="female" type="radio" v-model="gender" value="f"/>
<label for="female">Female</label>
<input id="male" type="radio" v-model="gender" value="m"/>
<label for="male">Male</label>
<input id="other" type="radio" v-model="gender" value="o"/>
<label for="other">Other</label>
<h2/>{{gender}}</h2>
</div>
1
2
3
4
5
6
new Vue({
el:"#app",
data:{
gender:'',
},
})

10-4.下拉選單:select與option (影片)

綁定單一個屬性

若沒有定義option中的value,會自動將option標籤中的內容當作value

1
2
3
4
5
6
7
8
9
<div id="app">
<select v-model="year">
<option disable value="">Select Year</option>
<option value="17">2017</option>
<option>2018</option>
<option>2019</option>
</select>
<h2>{{year}}</h2>
</div>

1
2
3
4
5
6
new Vue({
el:"#app",
data:{
year:'',
}
})

綁定至array中,使用multiple

1
2
3
4
5
6
7
8
9
<div id="app">
<select v-model="years" multiple>
<option disable value="">Select Year</option>
<option value="17">2017</option>
<option>2018</option>
<option>2019</option>
</select>
<h2>{{years}}</h2>
</div>
1
2
3
4
5
6
new Vue({
el:"#app",
data:{
years:[],
}
})

使用v-for綁定option

1
2
3
4
5
6
7
<div id="app">
<select v-model="selectedYear">
<option disable value="">select year</option>
<option v-for="item in years">{{item}}</option>
</select>
<h2>{{selectedYear}}</h2>
</div>
1
2
3
4
5
6
7
new Vue({
el:"#app",
data:{
years:[2017,2018,2019],
selectedYear:'',
}
})

Vue-(九)事件處理

9-1.處理事件的兩種方式 (影片)

在methods中定義函式方法

當執行內容較多時,建議定義為函式方法

1
2
3
4
<div id='app'>
<h1>{{count}}</h1>
<button @click="add">Add</button>
</div>

1
2
3
4
5
6
7
8
9
10
11
new Vue({
el:"#app",
data:{
count:0,
},
methods:{
add(){
this.count++;
}
}
})

直接改變data中的變數

當執行內容簡短時,可以直接改變屬性

1
2
3
4
<div id='app'>
<h1>{{count}}</h1>
<button @click="count++">Add</button>
</div>

1
2
3
4
5
6
new Vue({
el:"#app",
data:{
count:0,
},
})

9-2.偵聽滑鼠事件 (影片)

v-on綁定事件

v-on:click=""簡寫為@:click=""

其他滑鼠事件

  • mouseover:滑鼠經過
  • mouseout:滑鼠移出
  • mousedown:滑鼠點下
  • mouseup:滑鼠點下後‘放開’
  • mousemove:滑鼠在其上方移動時

9-3.偵聽圖片的load事件 (影片)

偵聽圖片loading前後,回傳不同的class樣式

1
2
3
4
5
6
7
8
<div id='app'>
<h2 v-if="loading">loading</h2>
<h2 v-else>complete</h2>
<image
:class='imgClass'
@load="loading=false"
src="https://loremflickr.com/g/320/240/paris"></image>
</div>

1
2
3
4
5
6
7
8
.image{
transition: all 1s;

}
.image.hide{
opacity:0;
transform: scale(3) rotate(180deg);
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
new Vue({
el:"#app",
data:{
loading:true,
},
computed:{
imgClass(){
if(this.loading){
return 'image hide';
}else{
return 'image'
}
}
}
})

示範練習 (codepen)


9-4.偵聽按鍵事件 (影片)

鍵盤事件

  • keydown:按鍵被‘按下’時
  • keyup:按鍵被按下後‘彈起’時

    修飾符 定義按鍵

  • v-on:keydown.enter
    (當「enter」按鍵被按下時)

    修飾符 防止按鍵內容被輸入

  • v-on:keydown.a.prevent
    (當「a」按鍵被按下時,但a的內容不會被放入input中)
    1
    2
    3
    4
    5
    6
    <div id="app">
    <input v-model="input" v-on:keyup.enter="add"/>
    <ul>
    <li v-for="item in todo">{{item}}
    </ul>
    </div>
1
2
3
4
5
6
7
8
9
10
11
12
13
new Vue({
el:"#app",
data:{
input:'',
todo:[],
},
methods:{
add(){
this.todo.push(this.input);
this.input = '';
}
}
})

示範練習 (codepen)


9-5.便利的修飾符語法 (影片)

.prevent:不執行預設效果

1
2
3
4
5
6
7
<div id="app">
<a
href="https://www.google.com"
target="_blank"
@click="linkClick">
google</a>
</div>
1
2
3
4
5
6
7
8
9
new Vue({
el:"#app",
methods:{
linkClick(event){
event.preventDefault();
alert("Don't do it!");
}
}
})

改用修飾符.prevent的便利寫法

1
2
3
4
5
6
7
<div id="app">
<a
href="https://www.google.com"
target="_blank"
@click.prevent="linkClick">
google</a>
</div>

1
2
3
4
5
6
7
8
new Vue({
el:"#app",
methods:{
linkClick(){
alert("Don't do it!");
}
}
})

.stop:不讓event傳到外層

1
2
3
4
5
6
7
8
9
<div id="app">
<div class="box" @click="clickA">
<div class="box" @click="clickB">
<div class="box" @click="clickC">
</div>
</div>
</div>
<h1>{{msg}}</h1>
</div>
1
2
3
4
5
6
7
.box{
border:2px solid blue;
min-width:30px;
min-height:30px;
padding:10px;
margin:10px;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
new Vue({
el:"#app",
data:{
msg:'null',
},
methods:{
clickA(event){
event.stopPropagation();
this.msg = 'A';
},
clickB(event){
event.stopPropagation();
this.msg = 'B';
},
clickC(event){
event.stopPropagation();
this.msg = 'C';
}
}
})

改用修飾符.stop的便利寫法

1
2
3
4
5
6
7
8
9
<div id="app">
<div class="box" @click.stop="msg='A'">
<div class="box" @click.stop="msg='B'">
<div class="box" @click.stop="msg='C'">
</div>
</div>
</div>
<h1>{{msg}}</h1>
</div>

.self:只執行自己發出的event

1
2
3
4
5
6
7
8
9
<div id="app">
<div class="box" @click.self="msg='A'">
<div class="box" @click.self="msg='B'">
<div class="box" @click.self="msg='C'">
</div>
</div>
</div>
<h1>{{msg}}</h1>
</div>

.once:只執行一次

1
2
3
4
<div id="app">
<h1>{{num}}</h1>
<button @click.once="num+=1">+Add </button>
</div>
1
2
3
4
5
6
new Vue({
el:"#app",
data:{
num:0,
},
})

更多修飾符,參考(Vue文件)

Vue-(八)列表渲染

8-1.用v-for把陣列轉換為一組元素 (影片)

v-for項目基本語法

1
2
3
4
5
<div id="app">
<ol>
<li v-for="item in colors">{{item}}</li>
</ol>
</div>
1
2
3
4
5
6
new Vue({
el:'#app',
data:{
colors:['學習javascrip','學會vue框架','做作品','準備面試']
},
})

補充:HTML ul 與 ol 差異==

將item拿出來當作屬性

1
2
3
4
5
6
7
<div id="app">
<ol>
<li v-for="item in todo" v-bind:class='item.key'>
{{item.date}} {{item.content}}
</li>
</ol>
</div>
1
2
3
4
5
6
.first{
color:red;
}
.second{
color:green;
}
1
2
3
4
5
6
7
8
9
new Vue({
el:'#app',
data:{
todo:[{key:'first',date:'3/9',content:'學習javascrip'},
{key:'second',date:'3/10',content:'學會vue框架'},
{key:'second',date:'3/11',content:'做作品'},
{key:'second',date:'3/12',content:'準備面試'}]
},
})

用index綁定value

1
2
3
4
5
<div id="app">
<select >
<option v-for="(item,index) in monthes" :value="index">{{item}}</option>
</select>
</div>
1
2
3
4
5
6
new Vue({
el:'#app',
data:{
monthes:['1月','2月','3月','4月','5月','6月','7月','8月','9月','10月','11月','12月'],
},
})

8-2.用v-for把物件轉換為一組元素 (影片)

注意
v-forrender出來的順序不一定會跟物件中的順序一樣,所以如果是需要遵從順序的情況,盡可能使用陣列

1
2
3
<div id="app">
<span v-for="(value,key) in me">{{key}}-{{value}}<br/></span>
</div>

1
2
3
4
5
6
7
8
9
10
new Vue({
el:'#app',
data:{
me:{
name:'Leah',
age:26,
gender:"Female",
}
}
})

8-3.修改陣列或物件的注意事項 (影片)

陣列新增、刪減、排列基本語法

  • push(ew item)從陣列後面新增
  • pop()從陣列後面刪減
  • unshift(new item)從陣列前面新增
  • shift()從陣列前面刪減
1
2
3
4
5
6
7
8
9
<div id="app">
<ul>
<li v-for="item in steps">{{item}}</li>
</ul>
<button @click="push">Push</button>
<button @click="pop">Pop</button>
<button @click="shift">Shift</button>
<button @click="unshift">Unshift</button>
</div>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
new Vue({
el:'#app',
data:{
steps:[1,2,3,4,5],
},
methods:{
push(){
this.steps.push(this.steps.length+1);
},
pop(){
this.steps.pop();
},
shift(){
this.steps.shift();
},
unshift(){
this.steps.unshift(0);
},

}
})
  • splice(index,length)從陣列中切割
    第一個參數index代表陣列中要開始被切割的元素索引,第二個length參數代表要被切割掉的長度(元素數量)

    1
    2
    3
    splice(){//切除陣列中倒數第二個元素
    this.steps.splice(this.steps.length-2,1);
    }
  • splice(index,length,...)從陣列中切除,並添加新的元素

    1
    2
    3
    splice(){//從steps[1]開始切除0個,並從該位置添加元素'new1','new2','new3'
    this.steps.splice(1,0,'new1','new2','new3');
    }
  • slice(from,to)從陣列中取出部分元素,並重組出一個新的陣列
    ==slice()不會改變原先的陣列,會產出一個新的陣列==

    1
    2
    3
    4
    5
    6
    7
    8
    9
    slice(){
    this.steps = this.steps.slice(1,4);
    },
    ```
    * `sort()`從陣列中的元素從小到大排列
    ```javascript=
    sort(){
    this.steps.sort();
    }
  • reverse()從陣列中的元素反過來從後面到前面排列

    1
    2
    3
    reverse(){
    this.steps.reverse();
    }
  • filter()從陣列中的過濾符合條件的元素,並重組出一個陣列

    1
    2
    3
    4
    5
    6
    7
    //將steps中的每個元素一個個檢查
    //若符合(item%2===0),則會被放入新陣列中
    //最後將新的陣列作為filter()的回傳值
    //並重新assign給this.steps
    filter(){
    this.steps = this.steps.filter(item => item%2 === 0);
    }

注意!!!!

  • this.steps[0]=10, 不會修改陣列元素的值,應用splice()達到此目的
  • this.steps.length=0, 沒辦法清空陣列中的元素,應用splice(),或是slice()達到此目的。
  • this.obj.z=30, 沒有辦法達到新增物件屬性的功能
    1
    2
    3
    4
    <div id="app">
    <h4 v-for="(value,key) in obj">{{key}}={{value}}</h4>
    <button @click="addZ">Add Z</button>
    </div>

this代表Vue實例,Vue實例中有個方法$set(),第一個參數是設定的目標物件,第二個參數代表新增的key,第三個參數代表新增的value

1
2
3
4
addZ(){
// this.obj.z = 300;//無效
this.$set(this.obj,'z',300);
}

或是,這樣寫

1
2
3
addZ(){
Vue.set(this.obj,'z',300);
}

注意:
this.$set()Vue.set()用於物件原先沒有該屬性的情況;若情況是要修改物件本來就存在的屬性值,直接改寫就可以


8-4.列表的過濾與排序 (影片)

1
2
3
4
5
6
7
8
<div id="app">
<ul>
<li v-for="item in nums">{{item}}</li>
</ul>
<button @click="initiate">Initiate</button>
<button @click="filter">Filter</button>
<button @click="sort">Sort</button>
</div>

sort()會改變原先的this.num陣列;又因為data中nums=orgNums,所以最外面的orgNums也被改變了

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
const orgNums = [5,6,1,2,4,3,8,7,9];
new Vue({
el:'#app',
data:{
nums:orgNums,

},
methods:{
initiate(){
this.nums = orgNums;
},
filter(){
this.nums = this.nums.filter(item =>item%2===0);
},
sort(){
this.nums.sort();
},
}
})

因此,若要避免原先的陣列被改動而喚不回初始值,可以利用slice()語法,先複製一個新的陣列

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
const orgNums = [5,6,1,2,4,3,8,7,9];
new Vue({
el:'#app',
data:{
nums:orgNums,

},
methods:{
initiate(){
this.nums = orgNums;
},
filter(){
this.nums = this.nums.filter(item =>item%2===0);
},
sort(){
this.nums = this.nums.slice().sort();
},
}
})


8-5.用v-for渲染templete [(影片)]

(https://hiskio.com/courses/145/lectures/5382)

  • 每次迴圈需要被render出來的不只一個元素,而是包含多個標籤元素,可以使用<templete></templete>,並將v-for指令放在templete標籤中。
    1
    2
    3
    4
    5
    6
    <div id="app">
    <template v-for='item in header'>
    <h1>{{item}}</h1>
    <hr/>
    </template>
    </div>
1
2
3
4
5
6
7
8
9
new Vue({
el:'#app',
data:{
header:['Home','About','Product','Contact']
},
methods:{

}
})

8-6.實作:從JSON資料渲染課程列表 [(影片)]

(https://hiskio.com/courses/145/lectures/5383)

mounted()階段引入JSON格式資料

  • 用原生的fetch()

    1
    2
    3
    4
    5
    mounted(){
    fetch('./data.json')
    .then(res => res.json())
    .then(lessons => this.lessons = lessons);
    },
  • 引入jquery寫法

    1
    2
    $.getJSON('./data.json')
    .then(lessons => this.lessons = lessons);
  • axios寫法

    1
    axios.get('./data.json').then(res =>this.lessons = res.data);

結果呈現

補充
vscode 擴充套件 - Live Server:可以快速地建造一個本地端的server

8-7.片尾彩蛋:認識JSON格式 [(影片)]

(https://hiskio.com/courses/145/lectures/5470)

「JSON格式」本身是一個「字串」

JSON格式的限制

  • JSON格式的key一定要有雙引號””
  • 最後一個value不能有,結尾
  • value不能是函式(不過可以把它存成字串,之後再轉為函式執行)

    格式轉換

  • javascript物件轉為JSON格式:JSON.stringify();
1
2
3
4
5
6
7
8
const data = {
name:"point",
x:100,
y:200
}

const dataJSON = JSON.stringify(data);
console.log(dataJSON);

印出結果,用“”代表是一個字串(JSON格式字串)

  • JSON格式轉為javascript物件:JSON.parse();
1
2
const dataObj = JSON.parse(dataJSON);
console.log(dataObj);

印出結果,是一個物件

replacer:重建JSON資料

將物件轉換為JSON格式時,只取其中部分的key值。
作法:在stringify()的第二個參數放上key字串組成的陣列[‘x’,’y’];若放null,則代表曲全部的資料

1
2
3
4
5
6
7
8
9
console.clear();
const data = {
name:"point",
x:100,
y:200
}

const dataJSON = JSON.stringify(data,['x','y']);
console.log(dataJSON);

印出結果,產出的JSON格式資料中,只有出’x’,’y’

提高JSON格式易讀性

為了易讀性,讓JSON格式排列整齊,每個key值前面補上空格
作法:在stringify()的第三個參數空格數量

1
2
const dataJSON = JSON.stringify(data,null,2);
console.log(dataJSON);

格式JSON搭配try,catch()

因為不能保證每次能成功將JSON格式轉換為物件,為了避免城市卡住,通常會搭配try,catch(err)處理錯誤

1
2
3
4
5
try{
const data = JSON.parse(dataJSON);
}catch(err){
const data = {};
}

Vue-(七)條件判斷

7-1.v-if (影片)

補充:
本身並非元素,只是用來包著許多元素的模板

1
2
3
4
5
6
7
8
<div id="app">
<input type="checkbox" v-model="show"/>勾選秀出內容
<templete v-if="show">
<h1>{{message}}</h1>
<h2>{{message}}</h2>
<h3>{{message}}</h3>
</templete>
</div>

1
2
3
4
5
6
7
new Vue({
el:'#app',
data:{
message:'跳樓大拍賣',
show:false,
},
})

7-2.v-else (影片)

v-else一定要依附在v-if之後,且是同一層的東西

1
2
3
4
5
6
7
8
9
10
<div id="app">
<input type="checkbox" v-model="show"/>
<span v-if='show'>隱藏內容</span>
<span v-else>秀出內容</span>
<templete v-if="show">
<h1>{{message}}</h1>
<h2>{{message}}</h2>
<h3>{{message}}</h3>
</templete>
</div>

==如果中間有其他東西,v-else會無效

1
2
3
4
5
6
7
8
9
10
11
<div id="app">
<input type="checkbox" v-model="show"/>
<span v-if='show'>隱藏內容</span>
<br/>//錯誤:不得再v-if/v-else插入其他東西,會出錯
<span v-else>秀出內容</span>
<templete v-if="show">
<h1>{{message}}</h1>
<h2>{{message}}</h2>
<h3>{{message}}</h3>
</templete>
</div>


7-3.v-else-if (影片)

v-if若有成立,就不會render下面的v-else-ifv-else

1
2
3
4
5
6
7
8
9
<div id="app">
<input type="checkbox" v-model="showRed"/>red
<input type="checkbox" v-model="showGreen"/>green
<input type="checkbox" v-model="showBlue"/>blue
<h1 v-if="showRed">I'm Red.</h1>
<h1 v-else-if="showGreen">I'm Green.</h1>
<h1 v-else-if="showBlue">I'm Blue.</h1>
<h1 v-else>Non</h1>
</div>

1
2
3
4
5
6
7
8
new Vue({
el:'#app',
data:{
showRed:false,
showGreen:false,
showBlue:false,
},
})

7-4.v-show (影片)

  • v-if是讓程式判斷是否被render出來
  • v-show是用css控制是否在畫面中顯示(意即套用display: none),所以該元素在原始碼中有被render出來,只是不在畫面顯示
  • 可以搭配v-if使用,代表裡面的東西是否render出來;但是不能用v-show,因為本身並非一個元素,只是一個模板,無法被顯示處理
© 2020 Leah's Blog All Rights Reserved. 本站访客数人次 本站总访问量
Theme by hiero