腳手架搭建:
# install vue-cli
$ npm install -g vue-cli //全局安裝,將vue變成一個(gè)命令行中的命令
# create a new project using the "webpack" boilerplate
$ vue init webpack my-project
# install dependencies and go!
$ cd my-project
$ cnpm install //每次你去下載一整個(gè)的應(yīng)用都要去下載相對應(yīng)的依賴,每個(gè)應(yīng)用應(yīng)該有幾十個(gè)依賴,這些依賴的信息在package.json中都有說明,直接npm install 就能直接將所有需要的依賴安裝,我已經(jīng)把npm 設(shè)置成了淘寶的鏡像
$ npm run dev// 這樣就運(yùn)行起來了,其實(shí)這里的dev這些設(shè)置也是 已經(jīng)提前在package.json里面設(shè)置好了劫恒,要注意在你的項(xiàng)目路徑下面運(yùn)行,不然會(huì)找不到package.json文件的轿腺。
在這里先拋出一個(gè)問題两嘴,為什么在命令行輸入npm run dev就可以運(yùn)行了?
解析vue-cli中的頁面結(jié)構(gòu)
為什么需要vue-cli?
因?yàn)槿绻谴笮晚?xiàng)目的話族壳,我們需要項(xiàng)目部署憔辫,構(gòu)建,熱加載等仿荆,利用腳手架可以快速構(gòu)建項(xiàng)目應(yīng)用贰您。
可能第一次用vue-cli看到下面這么多的文件有點(diǎn)多有點(diǎn)復(fù)雜,但是別怕拢操,咱們來一一了解
|-- build // 項(xiàng)目構(gòu)建(webpack)相關(guān)代碼
| |-- build.js // 生產(chǎn)環(huán)境構(gòu)建代碼
| |-- check-version.js // 檢查node锦亦、npm等版本
| |-- utils.js // 構(gòu)建工具相關(guān)
| |-- vue-loader.conf.js // webpack loader配置
| |-- webpack.base.conf.js // webpack基礎(chǔ)配置
| |-- webpack.dev.conf.js // webpack開發(fā)環(huán)境配置,構(gòu)建開發(fā)本地服務(wù)器
| |-- webpack.prod.conf.js // webpack生產(chǎn)環(huán)境配置
|-- config // 項(xiàng)目開發(fā)環(huán)境配置
| |-- dev.env.js // 開發(fā)環(huán)境變量
| |-- index.js // 項(xiàng)目一些配置變量
| |-- prod.env.js // 生產(chǎn)環(huán)境變量
| |-- test.env.js // 測試腳本的配置
|-- src // 源碼目錄
| |-- components // vue所有組件
| |-- router // vue的路由管理
| |-- App.vue // 頁面入口文件
| |-- main.js // 程序入口文件,加載各種公共組件
|-- static // 靜態(tài)文件令境,比如一些圖片杠园,json數(shù)據(jù)等
|-- test // 測試文件
| |-- e2e // e2e 測試
| |-- unit // 單元測試
|-- .babelrc // ES6語法編譯配置
|-- .editorconfig // 定義代碼格式
|-- .eslintignore // eslint檢測代碼忽略的文件(夾)
|-- .eslintrc.js // 定義eslint的plugins,extends,rules
|-- .gitignore // git上傳需要忽略的文件格式
|-- .postcsssrc // postcss配置文件
|-- README.md // 項(xiàng)目說明,markdown文檔
|-- index.html // 訪問的頁面
|-- package.json // 項(xiàng)目基本信息,包依賴信息等
- main.js 程序入口文件舔庶,加載各種公共組件
第一部分(import)導(dǎo)入要用到的組件
第二部分新建了一個(gè)Vue對象抛蚁,組件里面寫的是App,也就是說導(dǎo)入 App.vue,在入口的時(shí)候?qū)pp的東西都顯示出來惕橙。
-
看看App.vue里面寫的是什么東西
App.vue
這里引入了一個(gè)組件 componentsA瞧甩,直接以標(biāo)簽的形式加在html里面。
要在下面的export default里面的components進(jìn)行注冊吕漂,不然是用不了的亲配。
對于組件的理解:組件是可以復(fù)用的Vue實(shí)例尘应,帶有名字惶凝,也可以說是一個(gè)自定義元素吼虎。是頁面的一部分,就是可能其他地方也要用到苍鲜,所以就封裝起來思灰,所以要用的時(shí)候進(jìn)行導(dǎo)入。 -
關(guān)于路由
我們看一下router這個(gè)東西里面寫了什么
image.png
設(shè)置了Helloworld這個(gè)組件的path為/
要注意混滔,這個(gè)路由的出口就是在html中的<router-view></router-view>
image.png
helloworld這個(gè)組件最后顯示的應(yīng)該就是‘welcome to your Vue,js App'
我們在App.vue里面的html的最下面定義了路由出口
image.png
看看網(wǎng)頁
image.png
成功
router對于構(gòu)建大型單頁應(yīng)用還是有很大優(yōu)勢的洒疚,嵌套路由,視圖切換動(dòng)畫坯屿,具名路徑。
其他
-
每個(gè)Vue應(yīng)用都是用Vue函數(shù)創(chuàng)建一個(gè)新的實(shí)例開始的
var vm = new Vue({ //選項(xiàng) })
在我的理解领跛,Vue就是一個(gè)構(gòu)造函數(shù),所以我們這個(gè)實(shí)例化的對象vm也繼承了Vue的特點(diǎn)吠昭。
-
在App.vue中
new Vue({ el: '#app', data: { message:'hello Vue.js' } })
el指定掛載的位置,掛載到id為app的元素上
- 響應(yīng)式系統(tǒng)中加入了所有data對象中所含有的屬性矢棚,也就是當(dāng)這些屬性的值發(fā)生改變時(shí)郑什,視圖中這些屬性的值也會(huì)相應(yīng)的改變蒲肋。這也是一個(gè)很重要的特點(diǎn)蘑拯。
來一個(gè)最最簡單的例子
<p div = "app">庫存:{{a}}</p>//html
var vm = new Vue({
el:"#app",
data:{
a:100
}
method:{
function(){ }
}
}) //script
data代表vue對象的數(shù)據(jù)兜粘,data這里聲明强胰,數(shù)據(jù)要在method代表vue對象的方法,所以function要在methods這里聲明。
可以看到<p></p>之間的{{a}}就是用了我們下面定義的id為“app"的vm這個(gè)對象里面的data對象的a屬性的值妹沙。
在控制臺(tái)輸入 vm.a = 190 回車之后我們看到
這里的庫存也改變了,這也是Vue的一個(gè)特點(diǎn):響應(yīng)式(relative)
可以想象接入后端數(shù)據(jù)庫之后處理也是特別方便的玄窝。
- 除了數(shù)據(jù)屬性悍引,還有一些實(shí)例屬性和方法,他們都有前綴$,以便與用戶定義的屬性區(qū)分開來趣斤。
相關(guān)api參考
https://cn.vuejs.org/v2/api/#%E5%AE%9E%E4%BE%8B%E5%B1%9E%E6%80%A7
為什么組件中的data一定要用reurn 返回
data(){
return {}
}
- 為什么要做成組件,因?yàn)榭梢远啻问褂茫容^方便势腮。
- 如果多個(gè)地方同時(shí)用到一個(gè)組件漫仆,一旦其中一個(gè)地方的data改變,用return返回的話就不會(huì)影響到其他組件中data的值盲厌,因?yàn)椴皇且弥担ㄒ弥稻褪遣挥胷eturn 直接 f:1,d:2這樣,而且數(shù)據(jù)只有一份建芙,一旦更改懂扼,其他地方的這個(gè)組件也會(huì)更改)
數(shù)組方法中的concat(),slice(),filter()微王,直接復(fù)制,或者改變數(shù)組長度的這些方法不會(huì)觸發(fā)視圖的更新钧大。
一些 Vue獨(dú)有的函數(shù)及其用法:
v-if
1.1 基本用法
<div id="app_2">
<p v-if="seen">你現(xiàn)在可以看到我</p>
</div> //html
var app2 = new Vue({
el:"#app_2",
data:{
seen:true
}
}) //script
v-if是類似于一個(gè)if的函數(shù)罩旋,進(jìn)行判斷并操作啊央,也就是說如果seen這個(gè)屬性是true的話,就會(huì)顯示文字涨醋,如果這個(gè)屬性是false的話,就不會(huì)顯示文字乓土,所以如果你在控制臺(tái)輸入app2.seen=false的話溯警,"你現(xiàn)在可以看到我"這行文字是不會(huì)出現(xiàn)的。
1.2 <template> 元素
因?yàn)関-if是一個(gè)指令食磕,所以必須綁定在一個(gè)上喳挑,如果要切換多個(gè)元素滔悉,此時(shí)可以把一個(gè) <template> 元素當(dāng)做不可見的包裹元素单绑,并在上面使用 v-if。最終的渲染結(jié)果將不包含 <template> 元素询张。也就是用一個(gè)<template>把那些元素包含起來浙炼。'
<div id = "app">
<template v-if="ok">
<p>Paragraph 1</p>
<p>Paragraph 2</p>
</template>
</div> //html
var vm = new Vue({
el:"#app",
data:{
ok:true
}
})
1.3 if else的用法
<div v-if="Math.random() > 0.5">
Now you see me
</div>
<div v-else>
Now you don't
</div>
1.4 另外一個(gè)根據(jù)條件來渲染元素的選項(xiàng)的v-show指令
v-if 是“真正”的條件渲染弯屈,因?yàn)樗鼤?huì)確保在切換過程中條件塊內(nèi)的事件監(jiān)聽器和子組件適當(dāng)?shù)乇讳N毀和重建。
相比之下资厉,v-show 就簡單得多——不管初始條件是什么,元素總是會(huì)被渲染湘捎,并且只是簡單地基于 CSS 進(jìn)行切換窄刘。如果需要非常頻繁地切換,則使用 v-show 較好娩践;如果在運(yùn)行時(shí)條件很少改變翻伺,則使用 v-if 較好。
v-for
2.1 對一個(gè)列表進(jìn)行渲染
v-for 指令需要使用 "item in items "形式的特殊語法吨岭,
items 是源數(shù)據(jù)數(shù)組并且 item 是數(shù)組元素迭代的別名。
也就是說我們原來實(shí)例化的對象的data對象中的數(shù)組的名字是復(fù)數(shù)的(例如是products)然后在html中用<li v-for = "product in products"></li>來實(shí)現(xiàn)我們的遍歷簿废。
當(dāng)然你用item in products也是沒問題的络它,用取到的item.text...進(jìn)行操作,數(shù)組有index代表索引化戳,對象有key代表索引(key,value)
<div id="app_3">
<ol>
<li v-for = "(todo,index) in todos">
{{ todo.text }} {{index}}
</li>
</ol>
</div> //有索引值的情況
<div id="app_3">
<ol>
<li v-for = "todo in todos">
{{ todo.text }}
</li>
</ol>
</div>//html
var app3 = new Vue({
el: '#app_3',
data: {
todos: [
{ text: '學(xué)習(xí) JavaScript' },
{ text: '學(xué)習(xí) Vue' },
{ text: '整個(gè)牛項(xiàng)目' }
]
}
})
得到的結(jié)果是:
index從0開始
v-on
3.1 基本用法
可以用 v-on 指令監(jiān)聽 DOM 事件,并在觸發(fā)時(shí)運(yùn)行一些 JavaScript 代碼白对。
看代碼:
<div id="app_4">
<button v-on:click = "count = count+1">add</button>
<p>您已經(jīng)點(diǎn)擊{{count}}次</p>
</div> //html
var app4 = new Vue({
el:"#app_4",
data:{
count:0
}
})//script
3.2 v-on可以用來接收一個(gè)方法换怖,我們應(yīng)該在實(shí)例化對象的method中定義方法。
v-model
在表單 <input> 及 <textarea> 元素上創(chuàng)建雙向數(shù)據(jù)綁定条摸≈耄可以監(jiān)聽用戶的數(shù)據(jù)并且更新。
<div id="app_5">
<input v-model="message"placeholder="edit">
<p>您輸入的信息是:{{message}}</p>
<!-- 文本框的雙向數(shù)據(jù)綁定 -->
</div>//html
var app5 = new Vue({
el:"#app_5",
data:{
message:''
}
})//script
<textarea>也一樣不過就是多行文本輸入
v-bind
綁定class,href...
同一個(gè)標(biāo)簽不管用v-bind還是直接<a class="xxx">所綁定的類是不會(huì)沖突的顷啼。
<div id="app_7">
<a v-bind:href="link" v-bind:class="classA">to success</a>
</div>
var app7 = new Vue({
el:"#app_7",
data:{
link:"https://www.baidu.com",
classA:'red-fonts'
}
})
classA也是我們在data中的參數(shù)昌屉,可以在classA中指定。
還可以給classA加個(gè)屬性躬厌,為true時(shí)就在這個(gè)類中蜻牢,為false時(shí)就不在這個(gè)類中。
<a v-on:click.stop="aaa"></a>
.stop表示冒泡抢呆。.XXX是事件修改器抱虐。
小小總結(jié)
- v-on,@,methods事件綁定
- v-on修飾符可以指定鍵盤事件
- v-model表單數(shù)據(jù)模型雙向綁定
子組件向父組件通信
- 新建的組件最好就放在我們的components目錄下面
- 組件名字如果是駝峰形式,例如helloWorld恳邀,作為標(biāo)簽直接導(dǎo)入時(shí)就應(yīng)該是hello-world(這是vue的特點(diǎn),vue自動(dòng)為你轉(zhuǎn)化了)
-
要在父組件里面的components里面進(jìn)行注冊才能用
image.png
這個(gè)就是因?yàn)闆]有注冊我們的組件的提醒刷钢。請注意:我們的組件都是在components下面注冊的乳附,components是和data伴澄,methods同一級的阱缓。
image.png
在html套用的時(shí)候要將駝峰形式改成用連接符連接的形式,例如helloWorld敞嗡,作為標(biāo)簽直接導(dǎo)入時(shí)就應(yīng)該是hello-world(這是vue的特點(diǎn)航背,vue自動(dòng)為你轉(zhuǎn)化了)
子組件通過$emit向父組件發(fā)送信息,觸發(fā)事件沃粗,具體步驟如下:
在子組件中進(jìn)行< content @click=”close”>事件的綁定
在子組件中的methods對這個(gè)close進(jìn)行定義
methods:{ close(){ this.emit(‘on-close’) } }
在父組件中的子組件標(biāo)簽中綁定on-close這個(gè)事件
<dialog :on-close=”beClose”>
-
在父組件的methods定義這個(gè)事件
methods{ beClose(){ console.log(10) } }
父組件向子組件通信
父組件向子組件傳遞信息時(shí)最盅,要在子組件的props里面進(jìn)行定義
父組件中向子組件傳number=5;
需要在子組件里面的props進(jìn)行聲明起惕,
props中多個(gè)單詞之間要用連接符不要用駝峰方式
如果要實(shí)現(xiàn)動(dòng)態(tài)綁定也十分簡單,注意要綁定问词,用v-bind或者:
用于一些幻燈片組件的使用啊,具體的數(shù)據(jù)在父組件那里的時(shí)候
父組件向子組件傳遞信息的另外一個(gè)方式是插槽<slot></slot>
結(jié)果是:并沒有顯示出來
我們應(yīng)該在子組件中相對應(yīng)的要顯示的地方加上<slot>標(biāo)簽垄分。
小小的總結(jié):
父組件向內(nèi)傳遞屬性-動(dòng)態(tài)屬性
子組件向外發(fā)布事件
slot插槽傳遞模板-具名slot
關(guān)于vue-router
// 0. 如果使用模塊化機(jī)制編程偷卧,導(dǎo)入Vue和VueRouter,要調(diào)用 Vue.use(VueRouter)
// 1. 定義 (路由) 組件听诸。
// 可以從其他文件 import 進(jìn)來
const Foo = { template: '<div>foo</div>' }
const Bar = { template: '<div>bar</div>' }
// 2. 定義路由
// 每個(gè)路由應(yīng)該映射一個(gè)組件。 其中"component" 可以是
// 通過 Vue.extend() 創(chuàng)建的組件構(gòu)造器桥嗤,
// 或者,只是一個(gè)組件配置對象砸逊。
// 我們晚點(diǎn)再討論嵌套路由。
const routes = [
{ path: '/foo', component: Foo },
{ path: '/bar', component: Bar }
]
// 3. 創(chuàng)建 router 實(shí)例司倚,然后傳 `routes` 配置
// 你還可以傳別的配置參數(shù), 不過先這么簡單著吧篓像。
const router = new VueRouter({
routes // (縮寫) 相當(dāng)于 routes: routes
})
在html中,我們就可以用<router-link>來進(jìn)行導(dǎo)航
<router-view/>是渲染出口
<div id="app">
<h1>Hello App!</h1>
<p>
<!-- 使用 router-link 組件來導(dǎo)航. -->
<!-- 通過傳入 `to` 屬性指定鏈接. -->
<!-- <router-link> 默認(rèn)會(huì)被渲染成一個(gè) `<a>` 標(biāo)簽 -->
<router-link to="/foo">Go to Foo</router-link>
<router-link to="/bar">Go to Bar</router-link>
</p>
<!-- 路由出口 -->
<!-- 路由匹配到的組件將渲染在這里 -->
<router-view></router-view>
</div>
在實(shí)例化的時(shí)候员辩, mode: 'history',可以后退。
前端路由參數(shù)
在映射表中進(jìn)行設(shè)置
color會(huì)被做為參數(shù)注入到$route.params里面
Vuex
Vuex 的狀態(tài)存儲(chǔ)是響應(yīng)式的。當(dāng) Vue 組件從 store 中讀取狀態(tài)的時(shí)候宋税,若 store 中的狀態(tài)發(fā)生變化,那么相應(yīng)的組件也會(huì)相應(yīng)地得到高效更新呢簸。
你不能直接改變 store 中的狀態(tài)乏屯。改變 store 中的狀態(tài)的唯一途徑就是顯式地提交 (commit) mutation。這樣使得我們可以方便地跟蹤每一個(gè)狀態(tài)的變化辰晕,從而讓我們能夠?qū)崿F(xiàn)一些工具幫助我們更好地了解我們的應(yīng)用。
再次強(qiáng)調(diào)忘苛,我們通過提交 mutation 的方式唱较,而非直接改變 store.state.count,是因?yàn)槲覀兿胍鞔_地追蹤到狀態(tài)的變化南缓。這個(gè)簡單的約定能夠讓你的意圖更加明顯,這樣你在閱讀代碼的時(shí)候能更容易地解讀應(yīng)用內(nèi)部的狀態(tài)改變汉形。此外倍阐,這樣也讓我們有機(jī)會(huì)去實(shí)現(xiàn)一些能記錄每次狀態(tài)改變逗威,保存狀態(tài)快照的調(diào)試工具。有了它概耻,我們甚至可以實(shí)現(xiàn)如時(shí)間穿梭般的調(diào)試體驗(yàn)罐呼。
注意事項(xiàng)
- 記得注冊store!!!!!不然commit,mutation這些它是識(shí)別不出來的啊嫉柴!state也是重點(diǎn)來著
image.png
子組件.png
Vuex 通過 store 選項(xiàng)计螺,提供了一種機(jī)制將狀態(tài)從根組件“注入”到每一個(gè)子組件中(需調(diào)用 Vue.use(Vuex)):
同步邏輯放在mutation中
異步邏輯放在action中
然后就可以去調(diào)用store里面的屬性。
https://github.com/vuejs/vuex/tree/dev/examples/shopping-cart
優(yōu)雅的使用v-for 危尿、computed
注意綁定啊啊啊啊
沒有:就直接將isShowDialog作為值傳遞進(jìn)去,這是不行的
雙向數(shù)據(jù)綁定
實(shí)例中演示了 input 和 textarea 元素中使用 v-model 實(shí)現(xiàn)雙向數(shù)據(jù)綁定
另一種方式實(shí)現(xiàn) Vue 的響應(yīng)式原理
眾所周知半等,vue是通過Object.defineProperty 追蹤依賴呐萨,從而實(shí)現(xiàn)響應(yīng)式的。
有兩個(gè)不足之處:
- 不能檢測到增加或刪除的屬性谬擦。
- 數(shù)組方面的變動(dòng),如根據(jù)索引改變元素谜悟,以及直接改變數(shù)組長度時(shí)的變化,不能被檢測到葡幸。
原因差不多,無非就是沒有被 getter/setter 是钥。
第一個(gè)比較容易理解缅叠,為什么數(shù)組長度不能被 getter/setter ?
在知乎上找了一個(gè)答案:如果你知道數(shù)組的長度肤粱,理論上是可以預(yù)先給所有的索引設(shè)置 getter/setter 的。但是一來很多場景下你不知道數(shù)組的長度鸥鹉,二來庶骄,如果是很大的數(shù)組毁渗,預(yù)先加 getter/setter 性能負(fù)擔(dān)較大单刁。
現(xiàn)在有一個(gè)替代的方案 Proxy,但這東西兼容性不好肺樟,遲早要上的逻淌。
Proxy,在目標(biāo)對象之前架設(shè)一層攔截卡儒。具體,可以參考 http://es6.ruanyifeng.com/#docs/reference
Vue3.0就用的proxy
vue打包有時(shí)候會(huì)找不到圖片硬爆,主要是打包路徑的問題
https://www.cnblogs.com/diantao/p/7776523.html
更新一下對于computed的認(rèn)識(shí)
其實(shí)主要還是為了簡便計(jì)算
例如我們有一個(gè)這樣的需求: 將輸入兩個(gè)文本框的姓氏和名字一起顯示出來锦募。
<input type="text"
v-model="firstName" />
<input type="text"
v-model="lastName" />
<p>{{name}}</p>
data () {
return {
msg: 'Welcome to Your Vue.js App',
firstName: '',
lastName: ''
}
},
computed: {
name () {
return this.firstName + this.lastName
}
}
只要我們在computed里面定義的這個(gè)name函數(shù)已經(jīng)將firstName和lastName一起拼合起來就好了,然后就可以在標(biāo)簽里面直接用name了。
Vue生命周期
我們先來說說幾個(gè)最經(jīng)常用到的准验。
- created
實(shí)例(APP)已經(jīng)創(chuàng)建廷没,變量還未渲染到模板
此時(shí)修改變量還是能起作用的 - mounted
變量已經(jīng)掛載到模板上面了,此時(shí)修改變量也還是能起作用的 - updated
實(shí)例更新 - destoryed
實(shí)例銷毀
面試題:為什么要使用VUEJS
實(shí)現(xiàn)項(xiàng)目的模塊化颠黎,組件化。
實(shí)現(xiàn)數(shù)據(jù)渲染夭坪。
提供路由过椎,ajax,數(shù)據(jù)流等其他功能。