組件(Component)是自定義封裝的功能。在前端開發過程當中,常常出現多個網頁的功能是重複的,並且不少不一樣的網站之間,也存在一樣的功能。javascript
而在網頁中實現一個功能,須要使用html定義功能的內容結構,使用css聲明功能的外觀樣式,還要使用js來定義功能的特效,所以就產生了把一個功能相關的[HTML、css和javascript]代碼封裝在一塊兒組成一個總體的代碼塊封裝模式,咱們稱之爲「組件」。css
因此,組件就是一個html網頁中的功能,通常就是一個標籤,標籤中有本身的html內容結構,css樣式和js特效。html
這樣,前端人員就能夠在開發時,只須要書寫一次代碼,隨處引入便可使用。前端
組件有兩種:默認組件[全局組件] 和 單文件組件vue
<div id="app"> <addnum></addnum> <addnum></addnum> <addnum></addnum> <addnum></addnum> <addnum></addnum> </div> <script> Vue.component("addnum",{ template:'<div><input type="text" v-model="num"><button @click="num+=1">點擊</button></div>', data: function(){ // 寫在這裏的數據只有當前組件可使用 return { num:1, } } }); var vm = new Vue({ el:"#app", // 這裏寫的數據是全局公用的,整個文件共享 data:{ } }) </script>
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <script src="js/vue.js"></script> <style> .header{ width: 100%; height: 40px; } .header ul{ list-style:none; padding:0; margin: 0; overflow: hidden; } .header ul li{ width: 120px; height: 40px; line-height: 40px; text-align: center; color: #fff; background-color: blue; float: left; margin-right: 10px; } </style> </head> <body> <div id="app"> <!-- 頭部 --> <Tou></Tou> <!-- 腳部--> </div> <script> // Vue.component("組件名稱",組件的相關參數[html,css,js代碼]); Vue.component("Tou",{ template:`<div class="header"> <ul> <li @click="indexHander">{{index}}</li> <li>{{list}}</li> </ul> </div>`, data:function(){ return { index: "首頁", list:"列表頁" } }, methods:{ indexHander(){ alert("跳轉到首頁"); } } }); let vm = new Vue({ el:"#app", data:{} }) </script> </body> </html>
前面學習了普通組件之後,接下來咱們繼續學習單文件組件則須要提早先安裝準備一些組件開發工具。不然沒法使用和學習單文件組件。java
通常狀況下,單文件組件,咱們運行在 自動化工具vue-CLI中,能夠幫咱們編譯單文件組件。因此咱們須要在系統中先搭建vue-CLI工具,node
官網:https://cli.vuejs.org/zh/python
Vue CLI 須要 Node.js 8.9 或更高版本 (推薦 8.11.0+)。你可使用 nvm 或 nvm-windows在同一臺電腦中管理多個 Node 版本。(至關於Python虛擬化管理工具)webpack
nvm工具的下載和安裝: https://www.jianshu.com/p/d0e0935b150a windows版本的ios
https://www.jianshu.com/p/622ad36ee020
安裝記錄:
打開: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(長線支持版本):
下載地址: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自動化工具能夠快速搭建單頁應用項目目錄。
該工具爲現代化的前端開發工做流提供了開箱即用的構建配置。只需幾分鐘便可建立並啓動一個帶熱重載、保存時靜態檢查以及可用於生產環境的構建配置的項目:
// 生成一個基於 webpack 模板的新項目
vue init webpack 項目名
例如:
vue init webpack myproject
// 啓動開發服務器 ctrl+c 中止服務
cd myproject
npm run dev # 運行這個命令就能夠啓動node提供的測試http服務器
運行了上面代碼之後,終端下會出現如下效果提示:
├── build/
├── config/
├── index.html
├── node_modules/ # 項目運行的依賴庫存儲目錄[很是大]
├── package.json # 項目運行須要的依賴庫記錄配置
├── src/
│ ├── App.vue # 父級組件
│ ├── assets/ # 靜態資源目錄,圖片存放在這裏
│ ├── components/ # 單文件組件保存目錄
│ └── main.js
└── static/ # 靜態資源目錄,全部的css,js等文件放在這個目錄
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"。
在組件中編輯三個標籤,編寫視圖template、vm對象script標籤和css樣式代碼style。
<template> <div id="Home"> <div class="header"> 頁面頭部 </div> <div class="main"> 頁面主題內容 </div> <div class="footer"> 頁面腳步內容 </div> </div> </template>
<script> export default { name:"Home", // 組件名稱,用於之後路由跳轉 data(){ // 當前組件中須要使用的數據 return { num:0, } }, } </script>
// scoped 表示當前style的樣式只做用於當前組件的template代碼中,其餘地方不會被影響 <style scoped> .header{ height: 100px; line-height: 100px; background-color: #eee; text-align: center; } </style>
建立保存子組件的目錄common
在common目錄下建立Header.vue
把Home.vue的style標籤的頭部樣式放置到Header.vue
<template> <div id="Header" class="header"> {{message}} </div> </template> <script> export default { name:"Header", // 組件名稱,用於之後路由跳轉 props:["num"], data(){ // 當前組件中須要使用的數據 return { message:"頁面頭部", } }, } </script> // scoped 表示當前style的樣式只做用於當前組件的template代碼中,其餘地方不會被影響 <style scoped> .header{ height: 100px; line-height: 100px; background-color: #eee; text-align: center; } </style>
<template> <div id="Home"> <!--使用子組件 將父組件的值傳入子組件--> <Header :num="num"/> <div class="main"> 頁面主題內容 </div> <div class="footer"> 頁面腳步內容 </div> </div> </template> <script> // 導入子組件 import Header from "./common/Header" export default { name:"Home", // 組件名稱,用於之後路由跳轉 data(){ // 當前組件中須要使用的數據 return { num:0, } }, // 註冊子組件 components:{ Header, } } </script> // scoped 表示當前style的樣式只做用於當前組件的template代碼中,其餘地方不會被影響 <style scoped> /*.header{*/ /*height: 100px;*/ /*line-height: 100px;*/ /*background-color: #eee;*/ /*text-align: center;*/ /*}*/ </style>
<template> <div id="app"> <!--原來的代碼--> <!--<img src="./assets/logo.png">--> <!--<HelloWorld/>--> <!-- 3. 使用組件 --> <HomeCom/> </div> </template> <script> // 原來的代碼 // import HelloWorld from './components/HelloWorld' // 1. 導入組件 import HomeCom from './components/Home' export default { name: 'App', // 2. 註冊組件 components: { HomeCom } // 原來的代碼 // components: { // HelloWorld // } } </script> <style> /*#app {*/ /*font-family: 'Avenir', Helvetica, Arial, sans-serif;*/ /*-webkit-font-smoothing: antialiased;*/ /*-moz-osx-font-smoothing: grayscale;*/ /*text-align: center;*/ /*color: #2c3e50;*/ /*margin-top: 60px;*/ /*}*/ /* 有時候能夠編寫整個項目中的公共代碼,例如重置樣式的代碼 */ body{ margin:0; } </style>
在Home.vue的主體部分裏面直接編寫代碼了
<template> <div id="Home"> <Header/> <div class="main"> <p>加減數字的功能</p> <div class="box"> <button @click="num++">+</button> <input type="text" v-model="num"> <button @click="num--">-</button> </div> </div> <div class="footer"> 頁面腳步內容 </div> </div> </template> <script> import Header from "./common/Header" export default { name:"Home", // 組件名稱,用於之後路由跳轉 data(){ // 當前組件中須要使用的數據 return { num:0, } }, components:{ Header, } } </script> // scoped 表示當前style的樣式只做用於當前組件的template代碼中,其餘地方不會被影響 <style scoped> .header{ height: 100px; line-height: 100px; background-color: #eee; text-align: center; } </style>
效果:
如下全代碼:
<template> <div id="app"> <!--原來的代碼--> <!--<img src="./assets/logo.png">--> <!--<HelloWorld/>--> <!-- 3. 使用組件 --> <HomeCom/> </div> </template> <script> // 原來的代碼 // import HelloWorld from './components/HelloWorld' // 1. 導入組件 import HomeCom from './components/Home' export default { name: 'App', // 2. 註冊組件 components: { HomeCom } // 原來的代碼 // components: { // HelloWorld // } } </script> <style> /*#app {*/ /*font-family: 'Avenir', Helvetica, Arial, sans-serif;*/ /*-webkit-font-smoothing: antialiased;*/ /*-moz-osx-font-smoothing: grayscale;*/ /*text-align: center;*/ /*color: #2c3e50;*/ /*margin-top: 60px;*/ /*}*/ /* 有時候能夠編寫整個項目中的公共代碼,例如重置樣式的代碼 */ body{ margin:0; } </style>
<template> <div id="Home"> <!--使用子組件 將父組件的值傳入子組件--> <Header :num="num"/> <div class="main"> <p>加減數字的功能</p> <div class="box"> <button @click="num++">+</button> <input type="text" v-model="num"> <button @click="num--">-</button> </div> </div> <div class="footer"> 頁面腳步內容 </div> </div> </template> <script> // 導入子組件 import Header from "./common/Header" export default { name:"Home", // 組件名稱,用於之後路由跳轉 data(){ // 當前組件中須要使用的數據 return { num:0, } }, // 註冊子組件 components:{ Header, } } </script> // scoped 表示當前style的樣式只做用於當前組件的template代碼中,其餘地方不會被影響 <style scoped> .header{ height: 100px; line-height: 100px; background-color: #eee; text-align: center; } </style>
<template> <div id="Header" class="header"> {{message}} <p>num: <input type="text" v-model="num"></p> </div> </template> <script> export default { name:"Header", // 組件名稱,用於之後路由跳轉 props:["num"], data(){ // 當前組件中須要使用的數據 return { message:"頁面頭部", } }, } </script> // scoped 表示當前style的樣式只做用於當前組件的template代碼中,其餘地方不會被影響 <style scoped> .header{ height: 100px; line-height: 100px; background-color: #eee; text-align: center; } </style>
有時候開發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調用.就能夠看到頁面效果.
效果:
例如,咱們但願把父組件Home.vue的數據傳遞給子組件,例如Header.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>
效果:
步驟流程:
使用父組件傳遞數據給子組件時, 注意一下幾點:
傳遞數據是變量,則須要在屬性左邊添加冒號.
傳遞數據是變量,這種數據稱之爲"動態數據傳遞"
傳遞數據不是變量,而是數值或者字符串,這種數據稱之爲"靜態數據傳遞"
父組件中修改了數據,在子組件中會被同步修改,可是,子組件中的數據修改了,是不會影響到父組件中的數據.
這種狀況,在開發時,也被稱爲"單向數據流"
事實上,咱們若是要在子組件中把數據傳遞給父組件,也能夠完成的。
經過事件冒泡的方式,進行數據傳遞
在vue中提供的this.$emit()方法進行給咱們傳遞數據
默認狀況下,咱們的項目中並無對axios包的支持,因此咱們須要下載安裝。
在項目根目錄中使用 npm安裝包在命令行下執行安裝包的命令:
npm install axios
接着在main.js文件中,導入axios並把axios對象 掛載到vue屬性中多爲一個子對象,這樣咱們才能在組件中使用。
// The Vue build version to load with the `import` command // (runtime-only or standalone) has been set in webpack.base.conf with an alias. import Vue from 'vue' import App from './App' // 這裏表示從別的目錄下導入 單文件組件 import axios from 'axios'; // 從node_modules目錄中導入包 Vue.config.productionTip = false Vue.prototype.$axios = axios; // 把對象掛載vue中 /* eslint-disable no-new */ new Vue({ el: '#app', components: { App }, template: '<App/>' });
代碼編寫在Heaer.vue子組件中
<template> <div id="Header" class="header"> {{message}} <p>num: <input type="text" v-model="num"></p> <p>深圳的天氣狀況: {{weather_info}}</p> </div> </template> <script> export default { name:"Header", // 組件名稱,用於之後路由跳轉 props:["num"], data(){ // 當前組件中須要使用的數據 return { message:"頁面頭部", weather_info:"", } }, // 鉤子方法,在頁面中vue掛在data數據之後,自動執行 created() { // 使用axios發送請求獲取數據 this.$http.get("http://wthrcdn.etouch.cn/weather_mini?city=深圳").then(response=>{ console.log(response.data); console.log(response.data.data.ganmao); this.weather_info = response.data.data.ganmao; }).catch(error=>{ }); } } </script> // scoped 表示當前style的樣式只做用於當前組件的template代碼中,其餘地方不會被影響 <style scoped> .header{ height: 100px; line-height: 100px; background-color: #eee; text-align: center; } </style>
<template> <div id="Home"> <Header :num="num"/> <div class="main"> <p>加減數字的功能</p> <div class="box"> <button @click="num++">+</button> <input type="text" v-model="num"> <button @click="num--">-</button> </div> </div> <div class="footer"> 頁面腳步內容 </div> </div> </template> <script> import Header from "./common/Header" export default { name:"Home", // 組件名稱,用於之後路由跳轉 data(){ // 當前組件中須要使用的數據 return { num:0, } }, components:{ Header, } } </script> // scoped 表示當前style的樣式只做用於當前組件的template代碼中,其餘地方不會被影響 <style scoped> .header{ height: 100px; line-height: 100px; background-color: #eee; text-align: center; } </style>
<template> <div id="app"> <!--原來的代碼--> <!--<img src="./assets/logo.png">--> <!--<HelloWorld/>--> <!-- 3. 使用組件 --> <HomeCom/> </div> </template> <script> // 原來的代碼 // import HelloWorld from './components/HelloWorld' // 1. 導入組件 import HomeCom from './components/Home' export default { name: 'App', // 2. 註冊組件 components: { HomeCom } // 原來的代碼 // components: { // HelloWorld // } } </script> <style> /*#app {*/ /*font-family: 'Avenir', Helvetica, Arial, sans-serif;*/ /*-webkit-font-smoothing: antialiased;*/ /*-moz-osx-font-smoothing: grayscale;*/ /*text-align: center;*/ /*color: #2c3e50;*/ /*margin-top: 60px;*/ /*}*/ /* 有時候能夠編寫整個項目中的公共代碼,例如重置樣式的代碼 */ body{ margin:0; } </style>
使用的時候,由於本質上來講,咱們仍是原來的axios,因此也會收到同源策略的影響。
後面開發項目的時候,咱們會使用cors來解決跨域的問題。