1.起步
引入:
<!-- 開發環境版本,包含了有幫助的命令行警告 -->
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<!-- 生產環境版本,優化了尺寸和速度 -->
<!-- <script src="https://cdn.jsdelivr.net/npm/vue"></script> -->
創建Vue實例
var vm = new Vue({
el:"#app"
data:{},//存放數據
methods:{}//方法
});
/*
el:用於獲取需要的元素,一定是HTML中根容器元素
data:存儲數據
methods:方法
*/
2.在dom結構中渲染Vue
<!--1.插值表達式-->
<p>名字:{{name}}</p>
<P>工作:{{job}}</p>
<!--2.調用greet()方法-->
<p>{{greet(morning)}}</p>
3.Vue指令
3-1 v-bind
綁定屬性,可以用" : "代替
<a v-bind:href="website">百度</a>
可以簡略的寫爲:
<a :href="website">百度</a>
3-2 v-on
- 綁定事件,可以簡寫爲" @ "
<button v-on:click="add">加1</button>
- 鼠標移動事件v-on:mousemove
<div id="canvas" v-on:mousemove="updateXY">
{{x}},{{y}}
</div>
methods:{
updateXY:function(event){
this.x=event.offsetX;
this.y=event.offsetY;
}
}
- 使用v-on:click綁定點擊事件,使用v-on:dblclick綁定雙擊事件
3-3 v-html
插入HTML內容
<p v-html="websiteTag"></p>
<script>
new Vue({
el:'#app',
data:{
websiteTag:'<a href="http://baidu.com">跳轉百度</a>'
}
})
</script>
3-4 v-clock
防止頁面加載時出現vue.js變量名,比如"<p>{{message}}</p>",在初始化頁面時,沒能很快的拿到message在vue實例中的值,則頁面會直接顯示"{{message}}",知道message的值被渲染進來
3-5.條件渲染
3-5-1.v-if
<h1 v-if="awesome">Vue is awesome!</h1>
v-if判斷awesome是否爲true,若爲true則
若爲false則不顯示,html顯示
3-5-2 v-else
<div v-if="Math.random() > 0.5">
Now you see me
</div>
<div v-else>
Now you don't
</div>
tips:v-else
元素必須緊跟在帶 v-if
或者 v-else-if
的元素的後面,否則它將不會被識別。
3-5-3 v-else-if
3-6 v-show
v-show與v-if的區別:
v-if
是“真正”的條件渲染,因爲它會確保在切換過程中條件塊內的事件監聽器和子組件適當地被銷燬和重建。
v-if
也是惰性的:如果在初始渲染時條件爲假,則什麼也不做——直到條件第一次變爲真時,纔會開始渲染條件塊。
相比之下,v-show
就簡單得多——不管初始條件是什麼,元素總是會被渲染,並且只是簡單地基於 CSS 進行切換。
一般來說,v-if
有更高的切換開銷,而 v-show
有更高的初始渲染開銷。因此,如果需要非常頻繁地切換,則使用 v-show
較好;如果在運行時條件很少改變,則使用 v-if
較好。
3-7 v-for
3-7-1遍歷數組charcter
new Vue({
el:"#vueEvent",
data:{
character:['Mario','jack',"lucky"],
}
});
<div id="vueEvent">
<div v-for="c in character">
{{c}}
</div>
</div>
3-7-2遍歷複合數組useres
用".屬性"的方法來獲取複合數組的具體值
new Vue({
el:"#vueEvent",
data:{
useres:[
{name:'Mario',job:'java',age:30},
{name:'jack',job:'c++',age:18},
{name:'lucky',job:'php',age:20}
]
}
});
<div id="vueEvent">
<div v-for="u in useres">
{{u.name}}-{{u.job}}-{{u.age}}
</div>
</div>
3-7-3 二次遍歷
<div v-for="u in useres">
<div v-for="(val,key) in u">
{{key}}-{{val}}
</div>
</div>
問題提出,如此遍歷下的代碼產生很多空標籤
解決方法,用<tempelate></tempelate>代替div來做代碼的優化
<div v-for="u in useres">
<template v-for="(val,key) in u">
{{key}}-{{val}}
</template>
</div>
3-7 v-model
4.在vue中使用樣式
使用class樣式
- 對象語法:
<div v-bind:class="{ active: isActive, 'text-danger': hasError }"></div>
data: {
isActive: true,
hasError: false
}
- 數組語法:
<div v-bind:class="[isActive ? activeClass : '', errorClass]"></div> data: { activeClass: 'active', errorClass: 'text-danger' }
使用內聯樣式
-
直接在元素上通過
:style
的形式,書寫樣式對象<h1 :style="{color: 'red', 'font-size': '40px'}">這是一個善良的H1</h1>
-
將樣式對象,定義到
data
中,並直接引用到:style
中<h1 :style="h1StyleObj">這是一個善良的H1</h1> data:{ h1StyleObj:{ color:'red', 'font-size':'24px' } }
-
在
:style
中通過數組,引用多個data
上的樣式對象<h1 :style="[h1StyleObj, h1StyleObj2]">這是一個善良的H1</h1> data: { h1StyleObj: { color: 'red', 'font-size': '40px', 'font-weight': '200' }, h1StyleObj2: { fontStyle: 'italic' } }
5.事件修飾符
<!--stop:停止冒泡事件-->
<span v-on:mousemove.stop="">停止move</span>
<!--once:只能執行一次-->
<button v-on:click.once="">只能執行一次</button>
<!--prevent:阻止默認事件-->
<a v-on:click.prevent="" href="">點擊不跳轉到相應頁面而是隻執行click方法</a>
.stop
阻止單擊事件繼續傳播.prevent
提交事件不再重載頁面.capture 與事件冒泡的方向相反,事件捕獲從內到外
.self
只會觸發自己範圍內的事件,不包含子元素.once
只觸發一次.passive
6.鍵盤事件及鍵值修飾符
<input type="text" v-on:keyup="methods()">
<!--鍵入enter鍵之後才執行keyup事件-->
<input type="text" v-on:keyup.enter="methods()">
<!--鍵入enter鍵以及alt鍵之後才執行keyup事件-->
<input type="text" v-on:keyup.alt.enter="methods()">
7.雙向數據綁定
7-1 通過ref屬性
<div id="vueEvent">
<input type="text" ref="inputName" v-on:keyup="sysName">
<p>輸出數據:{{name}}</p>
</div>
new Vue({
el:"#vueEvent",
data:{
name:""
},
methods:{
sysName:function(){
this.name=this.$refs.inputName.value;
}
}
});
7-2 通過v-model
<div id="vueEvent">
<input type="text" v-model="name">
<p>輸出數據:{{name}}</p>
</div>
8.計算屬性computed
問題:使用計算方法時,若在methods中寫入方法,則存在每次觸發事件都會從頭到尾執行一遍所有方法的問題,如此特別耗費計算機的性能,由此引入computed,
new Vue({
el:"#elName",
data:{
a:0,
b:0
},
methods:{},
computed:{
addA:function(){
a++
}
addB:function(){
b++
}
}
});
9.vue動態綁定屬性
通過給class名賦true/false值來實現
<p v-bind:class="test:false"></p>
綁定多個屬性,可以通過computed方法裏面返回多個屬性值來實現
<button v-on:click="changeColor = !changeColor">改變顏色</button>
<div v-bind:class="compClass">
<span>測試樣式</span>
</div>
span{
background:red;
display: inline-block;
padding:10px;
color:#fff;
margin:10px 0px;
}
.changeColor span{
background:green;
}
.changeLength span:after{
content:"length";
margin-left:10px;
}
new Vue({
el:"#vueEvent",
data:{
changeColor:false,
changeLength:false
},
methods:{
},
computed:{
compClass:function(){
return {
changeColor:this.changeColor
}
}
}
});
10.vue組件
Vue.component('my-component-name', { /* ... */ })
11.vue搭建腳手架CLI
11-1 簡介
- 腳手架是通過webpack搭建的開發環境
- 使用ES6語法
- 打包和壓縮js文件爲一個文件bundle.js
- 項目文件在環境中編譯,而不是瀏覽器->速度快
- 實現頁面自動刷新
11-2 環境搭建node.js
11-2-1.npm安裝
npm安裝教程:https://www.cnblogs.com/goldlong/p/8027997.html
補充:
出現警告:npm WARN [email protected] requires a peer of ajv@^6.9.1 but none is installed.you must installed peer dependencies youselfs.
解決方法:安裝ajv@^6.9.1(根據警告內容) ,輸入 npm install ajv@^6.9.1.
12.屬性傳值
12-1 使用props從父組件到子組件傳值
12-1-1.父組件定義數據employee
export default {
name: 'App',
components:{
'Home':Home
},
data(){
return {
employee:[
{name:"henrry",job:"web engineer"},
{name:"henrry",job:"web engineer"},
{name:"henrry",job:"web engineer"},
{name:"henrry",job:"web engineer"},
{name:"henrry",job:"web engineer"},
{name:"henrry",job:"web engineer"}
],
title:"這是標題"
}
}
}
12-1-2.父組件在引用子組件標籤處通過v-bind綁定數據
<Home v-bind:test="employee"></Home>
12-1-3.子組件定義props
export default {
name: 'home',
props:{
test:{
type:Array,
require:true
}
}
}
12-2 子組件向父組件傳值
或者說調用父組件的方法
<div id="app">
<!--1. 父組件引用子組件的標籤處綁定一個func方法 -->
<mycom @func="show"></mycom>
</div>
<template id="temp1">
<div>
<h3>子組件文本</h3>
<!-- 2.子組件綁定一個click事件 -->
<input type="button" value="觸發父組件方法" v-on:click="clickEvent">
</div>
</template>
<script>
var mycom = {
template:'#temp1',
data:function(){
return{
msg:'子組件傳遞的信息'
}
},
methods:{
clickEvent(){
<!-- 3.用$emit調用父組件的方法並且傳遞參數 -->
this.$emit('func',this.msg);
}
}
};
new Vue({
el:'#app',
data:{},
methods:{
show(msg){
console.log('父組件show方法調用---打印子組件數據:'+msg);
}
},
components:{
mycom
}
});
</script>
在調用組件是用func綁定父組件的show方法,之後在子組件中用this.$emit調用show方法
13.生命週期
new vue({
el:"#app",
data:{},
methods:{
},
beforeCreate:function(){
//組件實例化前執行的函數
},
created:function(){
//組件實例化完畢,但頁面還未顯示
},
beforeMount:function(){
//組件掛載前,頁面仍未展示,但虛擬DOM已經配置
},
mounted:function(){
//組件掛載後,此方法執行後,頁面顯示
},
beforeUpdate:function(){
//組件更新前,頁面仍未更新,但虛擬DOM已經配置
},
updated:function(){
//組件更新,此方法執行後,頁面顯示
},
beforeDestory:function(){
//組件銷燬前
},
destoryed:function(){
//組件銷燬
}
});
14.vue路由與HTTP
14-1 vue路由
14-1-1 安裝路由
npm install vue-router --save
14-1-2 代碼
main.js
//1.引入路由
import VueRouter from 'vue-router'
//2.使用路由
Vue.use(VueRouter)
//3.配置路由
const router = new VueRouter({
routes:[
{path:"/",component:Home},
{path:"/helloworld",component:HelloWorld}
],
mode:"history"//區別在於localhost:8080與localhost:8080/#/的頁面是否一致
})
//4.使用路由
new Vue({
router,
el: '#app',
...
})
App.vue
<div id="App">
<router-view></router-view>
</div>
使用<router-link>標籤實現無刷新頁面,區別於a標籤實現的刷新跳轉
<div id="app">
<ul>
<li><a href="/">Home</a></li>
<li><a href="/helloworld">HelloWorld</a></li>
</ul>
<ul>
<li><router-link to="/">Home</router-link></li>
<li><router-link to="/helloworld">HelloWorld</router-link></li>
</ul>
<router-view></router-view>
</div>
14-2 vue與http
14-2-1 安裝resource
npm install vue-resource --save
14-2-2 代碼
main.js
//1.引入resource
import VueResource from 'vue-resource'
//2.使用resource
Vue.use(VueResource)
HelloWorld.vue
//3.遍歷獲取的employee
<template>
<div id="home">
<h1 v-for="u in employee">{{u.name}}</h1>
</div>
</template
//1.定義獲取數據的一個空數組employee
<script>
export default {
name: 'home',
data(){
return {
employee:[
]
}
},
//2.從http://jsonplaceholder.typicode.com/users獲取數據
created(){
this.$http.get("http://jsonplaceholder.typicode.com/users")
.then((data)=>{
// console.log(data)
this.employee=data.body;
})
}
</script>
tips:獲取到的data
15.二級路由、三級路由
15-1 二級路由
1.main.js引入路由路徑
2.找到一級路由並配置children數組
export const routes=[
{path:'/about',component:About ,children:[
{path:'/about/contack',name:"contackLink",component:Contack},
{path:'/history',name:"historyLink",component:History},
{path:'/deliver',name:"deliverLink",component:Deliver},
{path:'/orderGuide',name:"orderGuideLink",component:OrderGuide}
] }
]
15-2 三級路由同理
16.導航守衛
16-1 全局前置守衛
當一個導航觸發時,全局前置守衛按照創建順序調用。守衛是異步解析執行,此時導航在所有守衛 resolve 完之前一直處於 等待中。
main.js
//全局守衛
router.beforeEach((to,from,next) => {
//console.log(to);
if(to.path ==="/login"||to.path==="/register"){
next();
}else{
alert("還沒有登錄,請先登錄");
next("/login");
}
});
next: Function
: 一定要調用該方法來 resolve 這個鉤子。執行效果依賴 next
方法的調用參數。
next()
: 進行管道中的下一個鉤子。如果全部鉤子執行完了,則導航的狀態就是 confirmed (確認的)。next(false)
: 中斷當前的導航。如果瀏覽器的 URL 改變了 (可能是用戶手動或者瀏覽器後退按鈕),那麼 URL 地址會重置到from
路由對應的地址。next('/')
或者next({ path: '/' })
: 跳轉到一個不同的地址。當前的導航被中斷,然後進行一個新的導航。你可以向next
傳遞任意位置對象,且允許設置諸如replace: true
、name: 'home'
之類的選項以及任何用在router-link
的to
prop 或router.push
中的選項。next(error)
: (2.4.0+) 如果傳入next
的參數是一個Error
實例,則導航會被終止且該錯誤會被傳遞給router.onError()
註冊過的回調。
16-2 全局後置鉤子
和守衛不同的是,這些鉤子不會接受 next
函數也不會改變導航本身
router.afterEach((to, from) => {
// ...
})
16-3 路由獨享的守衛
1.通過配置
const router = new VueRouter({
routes: [
{
path: '/foo',
component: Foo,
beforeEnter: (to, from, next) => {
// ...
}
}
]
})
2.直接寫在path中
const routes=[
{path:'/login',component:Login,beforeEnter:(to,from,next) =>{
alert("路由獨享守衛");
}
}
]
16-4 組件內的守衛
<template>
<h1>Login</h1>
</template>
<script>
export default{
data(){
return{
name:'Henry'
}
},
beforeRouteEnter:(to,from,next) =>{
alert("Hello,"+this.name);
}
}
</script>
問題:this.name無法獲取data裏面的name值。原因是beforeRouteEnter守衛在導航確認前被調用,因此即將登場的新組件還沒被創建。
因此,通過傳一個回調給 next
來訪問組件實例。在導航被確認的時候執行回調,並且把組件實例作爲回調方法的參數.
<template>
<h1>Login</h1>
</template>
<script>
export default{
data(){
return{
name:'Henry'
}
},
beforeRouteEnter:(to,from,next) =>{
next(vm => {
alert("Hello,"+vm.name);
});
}
}
</script>