組件(Component)是自定義封裝代碼的功能。在前端開發過程當中,常常出現多個網頁的功能是重複的,並且不少不一樣的頁面之間,也存在一樣的功能。javascript
而在網頁中實現一個功能,須要使用html定義功能的內容結構,使用css聲明功能的外觀樣式,還要使用js來定義功能的特效,所以就產生了把一個功能相關的[HTML、css和javascript]代碼封裝在一塊兒組成一個總體的代碼塊封裝模式,咱們稱之爲「組件」。css
因此,組件就是一個html網頁中的功能,通常就是一個標籤,標籤中有本身的html內容結構,css樣式和js特效。html
這樣,前端人員就能夠在組件化開發時,只須要書寫一次代碼,隨處引入便可使用。前端
vue的組件有兩種:默認組件[全局組件] 和 單文件組件vue
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <script src="vue.js"></script> <style> #nav input[type=text]{ width: 100px; } </style> </head> <body> <div id="app"> <!-- 2. 調用組件 --> <mynav></mynav> <mynav></mynav> <mynav></mynav> <mynav></mynav> </div> <script> // 1. 經過Vue類建立組件 // 組件與組件之間的數據,方法都是獨立的,並且互相不會被影響。 Vue.component("mynav",{ template:`<div id="nav"> <button @click='sub()'>-</button> <input type='text' v-model='num'/> <button @click="add">+</button> </div>`, data(){ // 組件裏面的變量數據 return { num: 0 } }, methods:{ // 組件裏面的方法 sub(){ this.num--; }, add(){ this.num++; } }, watch:{ num(){ if(this.num<1){ this.num=0; } } } }); var vm = new Vue({ el:"#app", data:{ } }); </script> </body> </html>
前面學習了普通組件之後,接下來咱們繼續學習單文件組件則須要提早先安裝準備一些組件開發工具。不然沒法使用和學習單文件組件。java
通常狀況下,單文件組件,咱們運行在 自動化工具vue-CLI中,能夠幫咱們把單文件組件編譯成普通的js代碼。因此咱們須要在電腦先安裝搭建vue-CLI工具。node
官網:https://cli.vuejs.org/zh/python
Vue CLI 須要 Node.js 8.9 或更高版本 (推薦 8.11.0+)。你可使用 nvm 或 nvm-windows在同一臺電腦中管理多個 Node 版本。webpack
nvm工具的下載和安裝: https://www.jianshu.com/p/d0e0935b150aios
https://www.jianshu.com/p/622ad36ee020
curl -o- https://github.com/nvm-sh/nvm/v0.35.3/install.sh | bash
安裝記錄:
打開:https://github.com/coreybutler/nvm-windows/releases
安裝完成之後,先查看環境變量是否設置好了.
經常使用的nvm命令
nvm list # 列出目前在nvm裏面安裝的全部node版本
nvm install node版本號 # 安裝指定版本的node.js
nvm uninstall node版本號 # 卸載指定版本的node.js
nvm use node版本號 # 切換當前使用的node.js版本
若是使用nvm工具,則直接能夠不用本身手動下載,若是使用nvm下載安裝 node的npm比較慢的時候,能夠修改nvm的配置文件(在安裝根目錄下)
# settings.txt
root: C:\tool\nvm [這裏的目錄地址是安裝nvm時本身設置的地址,要根據實際修改]
path: C:\tool\nodejs
arch: 64
proxy: none
node_mirror: http://npm.taobao.org/mirrors/node/
npm_mirror: https://npm.taobao.org/mirrors/npm/
Node.js是一個新的後端(後臺)語言,它的語法和JavaScript相似,因此能夠說它是屬於前端的後端語言,後端語言和前端語言的區別:
運行環境:後端語言通常運行在服務器端,前端語言運行在客戶端的瀏覽器上
功能:後端語言能夠操做文件,能夠讀寫數據庫,前端語言不能操做文件,不能讀寫數據庫。
咱們通常安裝LTS(長線支持版本 Long-Time Support):
下載地址:https://nodejs.org/en/download/【上面已經安裝了nvm,那麼這裏不用手動安裝了】
node.js的版本有兩大分支:
官方發佈的node.js版本:0.xx.xx 這種版本號就是官方發佈的版本
社區發佈的node.js版本:xx.xx.x 就是社區開發的版本
Node.js若是安裝成功,能夠查看Node.js的版本,在終端輸入以下命令:
node -v
在安裝node.js完成後,在node.js中會同時幫咱們安裝一個npm包管理器npm。咱們能夠藉助npm命令來安裝node.js的包。這個工具至關於python的pip管理器。
npm install -g 包名 # 安裝模塊 -g表示全局安裝,若是沒有-g,則表示在當前項目安裝
npm list # 查看當前目錄下已安裝的node包
npm view 包名 engines # 查看包所依賴的Node的版本
npm outdated # 檢查包是否已通過時,命令會列出全部已過期的包
npm update 包名 # 更新node包
npm uninstall 包名 # 卸載node包
npm 命令 -h # 查看指定命令的幫助文檔
npm install -g vue-cli
若是安裝速度過慢,一直超時,能夠考慮切換npm鏡像源:http://npm.taobao.org/
使用vue-cli自動化工具能夠快速搭建單頁應用項目目錄。
該工具爲現代化的前端開發工做流提供了開箱即用的構建配置。只需幾分鐘便可建立並啓動一個帶熱重載、保存時靜態檢查以及可用於生產環境的構建配置的項目:
// 生成一個基於 webpack 模板的新項目
vue init webpack 項目目錄名
例如:
vue init webpack myproject
// 啓動開發服務器 ctrl+c 中止服務
cd myproject
npm run dev # 運行這個命令就能夠啓動node提供的測試http服務器
運行了上面代碼之後,終端下會出現如下效果提示:
src 主開發目錄,要開發的單文件組件所有在這個目錄下的components目錄下
static 靜態資源目錄,全部的css,js,圖片等資源文件放在這個文件夾
dist項目打包發佈文件夾,最後要上線單文件項目文件都在這個文件夾中[後面打包項目,讓項目中的vue組件通過編譯變成js 代碼之後,dist就出現了]
node_modules目錄是node的依賴包目錄
config是配置目錄,
build是項目打包時依賴的目錄
src/router 路由,後面須要咱們在使用Router路由的時候,本身聲明.
整個項目是一個主文件index.html,index.html中會引入src文件夾中的main.js,main.js中會導入頂級單文件組件App.vue,App.vue中會經過組件嵌套或者路由來引用components文件夾中的其餘單文件組件。
組件有兩種:普通組件、單文件組件
普通組件的缺點:
html代碼是做爲js的字符串進行編寫,因此組裝和開發的時候不易理解,並且沒有高亮效果。
普通組件用在小項目中很是合適,可是複雜的大項目中,若是把更多的組件放在html文件中,那麼維護成本就會變得很是昂貴。
普通組件只是整合了js和html,可是css代碼被剝離出去了。使用的時候的時候很差處理。
將一個組件相關的html結構,css樣式,以及交互的JavaScript代碼從html文件中剝離出來,合成一個文件,這種文件就是單文件組件,至關於一個組件具備告終構、表現和行爲的完整功能,方便組件之間隨意組合以及組件的重用,這種文件的擴展名爲「.vue」,好比:"Home.vue"。
在組件中編輯三個標籤,編寫視圖、vm對象和css樣式代碼。
template內部有且只能有一個子標籤,組件全部的html代碼必須被包含在這個子標籤中。
<template> <div id="Home"> <span @click="num--" class="sub">-</span> <input type="text" size="1" v-model="num"> <span @click="num++" class="add">+</span> </div> </template>
<script> export default { name:"Home", data: function(){ return { num:0, } } } </script>
<style scoped> .sub,.add{ border: 1px solid red; padding: 4px 7px; } </style>
建立Homes.vue
<template> <div class="add_num"> <span @click="num++">+</span> <input type="text" size="2" v-model="num"> <span @click="num--">-</span> </div> </template> <script> export default{ name:"AddNum", data: function(){ return { num: 0, } } } </script> <style scoped> .add_num{ font-size: 32px; } </style>
在App.vue組件中調用上面的組件
<template> <div id="Home"> <span @click="num--" class="sub">-</span> <input type="text" size="1" v-model="num"> <span @click="num++" class="add">+</span> </div> </template> <script> export default { name:"Home", data: function(){ return { num:0, } } } </script> <style scoped> .sub,.add{ border: 1px solid red; padding: 4px 7px; } </style>
在開發vue項目以前,須要手動把 App.vue的HelloWorld組件代碼以及默認的css樣式,清楚。
上面的代碼效果:
有時候開發vue項目時,頁面也能夠算是一個大組件,同時頁面也能夠分紅多個子組件.
由於,產生了父組件調用子組件的狀況.
例如,咱們能夠聲明一個組件,做爲父組件
在components/建立一個保存子組件的目錄HomeSon
在HomeSon目錄下,能夠建立當前頁面的子組件,例如,是Menu.vue
// 組件中代碼必須寫在同一個標籤中 <template> <div id="menu"> <span>{{msg}}</span> <div>hello</div> </div> </template> <script> export default { name:"Menu", data: function(){ return { msg:"這是Menu組件裏面的菜單", } } } </script>
而後,在父組件中調用上面聲明的子組件。
最後,父組件被App.vue調用.就能夠看到頁面效果.
效果:
例如,咱們但願把父組件的數據傳遞給子組件.
能夠經過props屬性來進行數據傳遞.
傳遞數據三個步驟:
一、在父組件中,調用子組件的組名處,使用屬性值的方式往下傳遞數據
<Menu :mynum="num" title="home裏面寫的數據"/> # 上面表示在父組件調用Menu子組件的時候傳遞了2個數據: 若是要傳遞變量[變量能夠各類類型的數據],屬性名左邊必須加上冒號:,同時,屬性名是自定義的,會在子組件中使用。 若是要傳遞普通字符串數據,則不須要加上冒號:
二、在子組件中接受上面父組件傳遞的數據,須要在vm組件對象中,使用props屬性類接受。
<script> export default { name:"Menu", props:["mynum","title"], data: function(){ return { msg:"這是Menu組件裏面的菜單", } } } </script> // 上面 props屬性中表示接受了兩個數據。
三、在子組件中的template中使用父組件傳遞過來的數據.
<template> <div id="menu"> <span>{{msg}},{{title}}</span> <div>hello,{{mynum}}</div> </div> </template>
效果:
步驟流程:
使用父組件傳遞數據給子組件時, 注意一下幾點:
傳遞數據是變量,則須要在屬性左邊添加冒號.
傳遞數據是變量,這種數據稱之爲"動態數據傳遞"
傳遞數據不是變量,這種數據稱之爲"靜態數據傳遞"
父組件中修改了數據,在子組件中會被同步修改,可是,子組件中的數據修改了,是否是影響到父組件中的數據.
這種狀況,在開發時,也被稱爲"單向數據流"
<template> <div> <p>Post的子組件</p> <h2>{{fnum}}</h2> <p>data={{data}}</p> <p>fnum={{fnum}}</p> <div><input type="text" v-model="fnum"></div> </div> </template> <script> export default { name: "PostSon", // 父組件傳遞數據給子組件: 1. 在父組件中調用子組件的組件名稱標籤上面聲明屬性和傳遞值,2. 在子組件中經過props進行接收 props:["data","fnum"], // 接受父組件中傳遞過來的數據 // 子組件傳遞數據給父組件[事件的方式進行傳遞]: watch:{ fnum(){ console.log(this.fnum); // this.$emit("父元素的自定義事件","要傳遞的數據"); // 經過this.$emit()方法,子組件能夠把數據傳遞給父組件 this.$emit("postparentdata",this.fnum); } } } </script> <style scoped> </style>
<template> <div> <h1>num={{num}}</h1> <Son data="我是付組件裏面的內容" :fnum="num" @postparentdata="getsondata"></Son> </div> </template>
三、父組件中,聲明一個自定義方法,在事件被調用時,執行的。
<script> import Son from "./PostSon" export default { name: "Post", data(){ return { num: 100, } }, components:{ Son:Son, }, methods:{ getsondata(message){ console.log("父組件"+message); this.num = message; } } } </script>
練習:
1. 在父組件中的data中聲明一個num1的變量,值爲10,傳遞到子組件中顯示出來。
2. 在子組件中的data中聲明一個num2的變量,值爲50,傳遞到父組件中顯示出來。
練習答案
<template> <div> <h1>我是Nav,{{parentnum}}</h1><button @click="num2++">點我</button> </div> </template> <script> export default { name: "Nav", props: ['parentnum'], data() { return { num2: 50 } }, mounted: { num2() { this.$emit('navfunc', 50) } }, // watch: { // num2(){ // this.$emit('navfunc', this.num2) // } // } } </script> <style scoped> </style>
<template> <div id="app"> <Home></Home> <input type="text" v-model="city"> <button @click="get_weather">獲取天氣</button> </div> </template> <script> import Home from './components/Home' export default { name: 'App', data() { return { city: '上海' } }, components: { Home, }, methods: { get_weather() { this.$axios.get('http://wthrcdn.etouch.cn/weather_mini?', { params: {city: this.city}, headers: {}, }).then(response => { console.log(response.data) }).catch(error => { console.log('請求失敗') }) } } } </script> <style> </style>
1. 把課堂案例選項卡封裝成組件,組件名:Card.vue
2. 把課堂案例獲取天氣封裝成組件,組件名:Weather.vue
3. 使用組件化開發,完成以前的選項卡練習功能
4. 使用組件化開發,完成以前的todolist功能
5. 使用組件化開發,完成table表格的增刪查改做業,數據使用本地存儲進行保存