文章目錄
Vue
因爲之前曾接觸過小程序的開發,所以 入手 Vue 相對爽了一些,因爲思想都是數據綁定,Vue是華人尤雨溪開發的,這可是個大佬,B站上有個關於大佬的紀律片,是 Up主:魚C-小甲魚 翻譯的,有興趣的話可以看看。
https://www.bilibili.com/video/BV1dT4y1V7Dn
M V VM
-
他是一種架構方式、開發思想
-
M:Model 數據模型 (操作數據的類)
-
V:View 視圖界面 (HTML)
-
VM:ViewModel 視圖模型
Vue 的思想
Vue是比較重要的是用數據來驅動頁面,下面是一個簡單的用Vue實現的頁面
<body>
<div id="app">{{message}}</div>
</body>
<script src="js/vue.js"></script>
<script>
var app = new Vue({
el:"#app",
data:{
message:"hello world"
}
})
</script>
生命週期函數
需要記得有
- beforeCreate
- create
- beforeMount
- mounted
- beforeUpdata
- updated
- beforeDestroy
- destroyed
其實有規律可循,創造-掛載-更新-銷燬
Vue實例中的選項
el
- 獲取元素,你可以用
#id
、.類名
,類似JQuery的選擇器等等,也可以用document.querySelectAll()
之類的
data
- 實例中的數據都放在這裏
computed 計算屬性
- 計算屬性的結果是放在緩存裏的
常見API的使用
v-if 條件
<body>
<!-- 條件語句必須if/else緊跟着 -->
<div id="app">
{{message}}
<div v-if="message == 'hello world'">if</div>
<div v-else-if="message == 'hello world1'">else-if</div>
<div v-else>else</div>
</div>
</body>
<script src="js/vue.js"></script>
<script>
var app = new Vue({
el:"#app",
data:{
message:"hello world"
}
})
</script>
v-show
v-show
不能搭配template
,即使條件不對也會顯示到頁面上
<template v-show="1 == 2">
<h1>我是個標題</h1>
</template>
- 如果
v-show
裏面的條件不對的話,頁面渲染的時候會使用display:none
把他隱藏掉
<div v-show="1 == 2">
<h1>我是個標題</h1>
</div>
v-for 循環
- 比方說我要循環一個名字叫
li
的數組
<body>
<div id="app">
<!-- 這裏也可以寫成 (each,index) of li,借用了ES6的語法-->
<div v-for="(each,index) in li">
each:{{each}}-----index:{{index}}
</div>
</div>
</body>
<script src="../js/vue.js"></script>
<script>
var app = new Vue({
el:"#app",
data:{
li:['one','two','three','four','five']
}
})
</script>
v-cloak 取消抖動
用Vue渲染頁面的時候,你刷新頁面,會有頁面沒有加載數據就渲染出來的情況,一閃而過(嘗試截取動圖但是截不到),但是爲了美,這種缺點怎麼可能忍呢!!!
只需兩步輕鬆解決
- 在標籤裏寫上
v-cloak
- 在樣式裏寫
[v-cloak]{ display: none; }
舉個小例子
<style>
[v-cloak]{
display: none;
}
</style>
<body>
<div id="app" v-cloak></div>
</body>
v-once
首次渲染之後,頁面不再隨着數據的變化而變化
<body>
<div id="app">
<div v-once>
<!--可以在控制檯上改變數值 app.message = 'nihao' -->
{{message}}
</div>
</div>
</body>
<script src="js/vue.js"></script>
<script>
var app = new Vue({
el:"#app",
data:{
message:"hello world"
}
})
</script>
v-bind 綁定屬性 **
v-bind可以簡略寫成:
,v-bind:後面接標籤的屬性,用來綁定標籤的屬性。
<body>
<div id="app">
<!-- 下面兩個div的綁定類是一樣的,都是name1 -->
<div v-bind:class="className"> v-bind:class="className"</div>
<div :class="className">:class</div>
</div>
</body>
<script src="js/vue.js"></script>
<script>
var app = new Vue({
el:"#app",
data:{
className:"name1"
}
})
</script>
v-on 綁定事件
v-on
也可以寫成@
- 可以傳遞參數,如果向添加事件因子,可以
@click="函數名($event)
這樣傳遞
<!-- 下面兩個div都綁定了click點擊事件,效果一樣 -->
<div v-on:click=""></div>
<div @click=""></div>
<button @click="hand2(10,$event)">btn2---$event</button>
修飾符
.
這個點就是修飾符,能修飾什麼呢?下面就是例子
冒泡與捕獲
- 阻止冒泡:
.stop
<div @click="fa">fa
<div @click.stop="son">son</div>
<!-- 這樣,點擊son,就不會出發fa的點擊事件了 -->
</div>
- 捕獲:
.capture
<div @click.capture="fa">fa
<div @click="son">son</div>
</div>
<!-- 這樣,點擊son,就會先觸發fa,然後son -->
按鍵觸發事件
- 37是鍵盤上的左方向鍵
- 如果向要組合按鍵,觸發連招的話,可以連着修飾符寫,如下
<input type="text" @keydown.37="key1Handler">
<input type="text" @keydown.space="key1Handler1" placeholder="space">
<!-- 組合按鍵 -->
<input type="text" @keydown.shift.83="key1Handler2" placeholder="shift+S">
v-html 編譯 & v-pre 跳過
注意 v-html
的一些細節
<body>
<div id="app">
<span v-html="tar">span1</span>
<span v-pre="tar1">span2</span>
</div>
</body>
<script src="js/vue.js"></script>
<script>
// v-html 轉化成html
// 注意轉化後的頁面格式,是插入此標籤內了,標籤內原有的內容將被覆蓋
// v-pre 跳過這個元素和它的子元素的編譯過程。
// 可以用來顯示原始 Mustache 標籤。跳過大量沒有指令的節點會加快編譯。
var app = new Vue({
el:'#app',
data:{
tar:"<a href='#'>11</a>",
tar1:"<a href='#'>11</a>"
}
})
</script>
圖片展示
v-model 綁定輸入
v-model
可以綁定input
和textarea
的文本
<body>
<div id="app" v-cloak>
<input type="text" v-model="message">
{{message}}
<textarea rows="" cols="" v-model="message">
</textarea>
</div>
</body>
<script src="../js/vue.js"></script>
<script>
var app = new Vue({
el:"#app",
data:{
message:"hello world"
}
})
</script>
- input失焦時在改變data,把輸入框中的值變爲number、去掉輸入框中值的首尾空格
<body>
<div id="app">
<!-- .lazy 是change事件,當失去焦點的時候會改變 -->
<input type="text" v-model.lazy="mes">
<!-- .number 把輸入數據變成類型爲number -->
<input type="text" v-model.number="mes">
<!-- .trim 去首和尾空格 -->
<input type="text" v-model.trim="mes">
<h1>{{mes}}</h1>
</div>
</body>
<script src="../js/vue.js"></script>
<script>
var app = new Vue({
el:"#app",
data:{
mes:"hello world"
}
})
</script>
單選框、複選框、下拉框
- 都是通過
v-model
來分組,相當於校服,不同學校相當於不同的組。校服一樣說明是一個學校的 - 單選框
<body>
<div id="app">
<!-- 單選:多個互斥 -->
<input type="radio" v-model="pick" value="male"> <label>男</label>
<input type="radio" v-model="pick" value="female"> <label>女</label>
<input type="radio" v-model="pick" value="???"> <label>男女男</label>
</div>
</body>
<script src="../js/vue.js"></script>
<script>
// 單選框
// 頁面上選擇哪一項,pick的值就是哪一個value值
var app = new Vue({
el:"#app",
data:{
pick:"male"
}
})
</script>
- 多選框
<body>
<div id="app">
<!-- 複選框多選 -->
<input type="checkbox" v-model="check" value="checkBox1"> <label>複選框1</label>
<input type="checkbox" v-model="check" value="checkBox2"> <label>複選框2</label>
</div>
</body>
<script src="../js/vue.js"></script>
<script>
var app = new Vue({
el:"#app",
data:{
// check裏存儲誰被選中了
check:[]
}
})
</script>
- 下拉框
<body>
<div id="app">
<!-- select如果想添加多個屬性,加multiple -->
<select v-model="select">
<!-- 默認是個option中的文本進行匹配
如果用了value的話優先value
-->
<option>1</option>
<option>2</option>
<option value='你好'>3</option>
</select>
</div>
</body>
<script src="../js/vue.js"></script>
<script>
var app = new Vue({
el:"#app",
data:{
select:"你好"
}
})
</script>
組件
組件命名要求
- 短橫線分隔命名
- 首字母大寫命名
全局/局部組件定義
顧名思義,組件的使用範圍不一樣
- 需要注意的是,全局組件要在實例化對象之前就要註冊,說人話,就是
- 爲什麼要先註冊在實例化呢?反過來行不行呢?我反過來會報如下的錯誤
[Vue warn]: Unknown custom element: <card> -
did you register the component correctly?
For recursive components, make sure to provide the "name" option.
報錯信息提示說:不知道的元素card
,是否正確註冊組件?,看一下生命週期那張流程圖:創建完Vue實例之後就已經渲染完template
了,這時候在註冊帶有template
的組件的話,Vue是不認識的
<body>
<div id="app">
{{message}}
<else-name></else-name>
</div>
</body>
<script src="../js/vue.js"></script>
<script>
// 全局組件:
// else-name 是我自定義的標籤名稱
// 命名規範:不能用駝峯命名,推薦都用小寫
Vue.component('else-name',{
template:'<div>這是組件中</div>'
})
</script>
局部的組件,這裏寫了兩種寫法
- 直接把模板放到組件裏
- 把模板放到外邊:方便修改
// 局部:只在當前vue中有效
var child = {
template:'<div>這是組件局部,內部中2</div>'
}
var app = new Vue({
el:"#app",
data:{
message:'hello world'
},
components:{
'demo1':{
template:'<div>這是組件局部,內部中1</div>'
},
'demo2':child
}
})
組件中的模板
- 模板裏只能由只能有一個根元素,不能有兩個以上的根元素
意思是說可以這樣:<div> <div></div> </div>
不可以<div></div> <div></div>
,
前者兩個div
是父子關係,後者兩個div
是同級的哥們關係
組件中的變量
組件中的變量可以這樣定義和使用
Vue.component('else-name',{
template:'<div>這是組件全局-外部中{{mess1}} {{mess2}}</div>',
data:function(){
return {
mess1:'<<這是組件中的data1>>',
mess2:'<<這是組件中的data2>>'
}
}
})
組件的通信
-
先來個簡單的,Vue的實例對象和組件的通信
-
假如我設Vue實例是爸爸,實例中的組件是兒子,兒子裏又有個組件叫孫子,那麼,爸爸和孫子之間怎麼交流?
<body>
<div id="app">
<son :msgson=msgfa></son>
</div>
</body>
<script src="../js/vue.js"></script>
<script>
// props單項傳遞,父向子傳
var app = new Vue({
el: '#app',
data: {
msgfa: '我是你爸爸'
},
components:{
'son': {
props:["msgson"],
template:`<div>
介紹:{{msgson}}
<grandson :msggrandson='sonData'></grandson>
</div>`,
components:{
'grandson':{
props:['msggrandson'],
template:`<div>{{msggrandson}}</div>`
}
},
data:function(){
return {
sonData:'兒子'
}
}
}
}
})
</script>
- 兒子如何向爸爸傳遞信息呢,也就是子向父傳遞,這時候用到了自定義函數
<body>
<div id="app">
<show @myevent="showVal"></show>
</div>
</body>
<script src="../js/vue.js"></script>
<script>
// 子向父親 $emit()觸發事件,只是爲了傳值 v-on
Vue.component('show', {
data: function(){
return {
str: '我是組件中的string'
}
},
methods: {
sendMsgToFa: function(){
// 這裏的this指向組件
// 自定義事件
this.$emit('myevent',this.str);
}
},
template: `<button @click="sendMsgToFa">點擊彈出組件傳遞的數據</button>`
})
var app = new Vue({
el:"#app",
data:{
message:"hello world"
},
methods:{
showVal: function(a){
alert(a)
}
}
})
</script>
- 如果我的孫子向給兒子傳遞信息呢?(就是組件中的組件 向 組件 傳遞信息)
<body>
<div id="app">
我有三個階級關係,分別是父親--兒子--孫子
<son :msgson=msgfa></son>
</div>
</body>
<script src="../js/vue.js"></script>
<script>
// props單項傳遞,父向子傳
var app = new Vue({
el: '#app',
data: {
msgfa: '我是你爸爸'
},
components:{
'son': {
props:["msgson"],
template:`<div>
介紹:{{msgson}}
<grandson :msggrandson='sonData' @myevent='showVal'></grandson>
</div>`,
components:{
'grandson':{
props:['msggrandson'],
template:`<div>
{{msggrandson}}
<button @click="sendMsgToFa">孫子給兒子傳值</button>
</div>`,
methods:{
sendMsgToFa: function(){
// 傳值不是自發的,而是事件驅動的,所以需要個綁定事件
// 自定義事件確定了,父親的接收函數名,和想要傳遞給父親的數據,
this.$emit('myevent','我是孫子裏面的消息')
}
}
}
},
data:function(){
return {
sonData:'兒子'
}
},
methods:{
showVal: function(val){
console.log(val);
}
}
}
}
})
</script>
中央事件總線bus:數據的中介
如果我現在還是有三層關係,分別是父親,兒子,和孫子,父親是Vue實例,兒子是實例中的組件,孫子是組件中的組件
如果這三個人,兩兩之間可以互相通信,那麼就不向上面那樣麻煩了,如何做到呢?
我們需要藉助一箇中介:中央事件總線
父鏈/子鏈
- 子組件可以通過父鏈拿到父組件的所有,也可以修改父組件的數據
- 取父組件中的數據可以,但是如果是修改的話,那麼父子組件的關係就會更緊,這是解耦合的操作,不太推薦(組件之間的關係應該儘量獨立,不要太過親暱)
給組件起名字,並通過名字獲得組件
- 給組件起名字
ref
- 取值的話通過
this.$refs.組件名字
組件的插槽
- 插槽的作用在於內容的分發
<body>
<!-- 編譯的作用域 -->
<!-- 父組件的模板的內容實在父組件的作用域編譯 -->
<!-- 插槽 -->
<div id="app">
<comp>
<p>父親模板的內容</p>
</comp>
</div>
</body>
<script src="../js/vue.js"></script>
<script>
// slot是插槽
Vue.component('comp',{
template:`<div>
<slot>如果父模板沒有內容,就顯示我</slot>
</div>`
})
var app = new Vue({
el:"#app",
data:{
message:"hello world"
}
})
</script>
- 指定插槽的內容分發,我們可以給每個插槽起個名字
<body>
<!-- 插槽: 具名的插槽分發-->
<div id="app">
<comp>
<!-- 注意這裏不是v-slot -->
<p slot="top">top</p>
<p slot="foot">foot</p>
<p>我沒有名字1</p>
<p>我沒有名字2</p>
</comp>
</div>
</body>
<script src="../js/vue.js"></script>
<script>
// slot是插槽
Vue.component('comp',{
template:`<div>
<slot name="top"></slot>
<slot name="foot"></slot>
<div>
<slot></slot>
</div>
</div>`
})
var app = new Vue({
el:"#app",
data:{
message:"hello world"
}
})
</script>
動態切換組件
- 在
component
標籤上有個屬性is
,裏面填寫組件的名字
路由
簡單路由
<script src="./node_modules/vue/dist/vue.js"></script>
<script src="./node_modules/vue-router/dist/vue-router.js"></script>
<body>
<div id="app">
<router-link to="/shangcheng">商城</router-link>
<router-link to="/shuma">數碼</router-link>
<router-link to="/jiaju">傢俱</router-link>
<router-view></router-view>
</div>
</body>
<script>
var sc = { template:`<h1>商城組件</h1>` }
var sm = { template:`<h1>數碼組件</h1>` }
var jj = { template:`<h1>傢俱組件</h1>` }
var router = new VueRouter({
routes:[
// redirect 重定向
{ path: '/',redirect: '/shuma' },
{ path: '/shangcheng',component: sc},
{ path: '/shuma',component: sm},
{ path: '/jiaju',component: jj}
]
})
var app = new Vue({
el:"#app",
router,
})
</script>
動態路由
- 動態路由可以
<body>
<div id="app">
<router-link to="hello/65">點擊</router-link>
<router-view></router-view>
</div>
</body>
<script>
// 動態路由
var Hello = {
template: `<h1>你好 {{$route.params.id}} </h1>`
}
var router = new VueRouter({
routes:[
{ path:'/hello/:id', component: Hello }
]
})
var app = new Vue({
el:"#app",
router
})
</script>
路由前進/後退
<body>
<div id="app">
<router-link to="hello">點擊</router-link>
<router-view></router-view>
<button v-on:click="back">後退</button>
<button v-on:click="go">前進</button>
</div>
</body>
<script>
// 組件
var Hello = {
template: `<h1>名字{{name}},年齡{{age}} </h1>`,
props:['name', 'age']
}
// 路由傳參
var router = new VueRouter({
routes:[
{
path: '/hello',
component: Hello ,
props: { name:'張三', age:11 }
}
]
})
var app = new Vue({
el:"#app",
router,
methods:{
// 路由的前進和後退
go(){
this.$router.go(1)
},
back(){
this.$router.go(-1)
}
}
})
</script>
監聽路由
- 我想點擊登錄的時候在右上角更改信息,就是把原先的登錄註冊按鈕改成用戶名和註銷
- 然而我的登錄寫成了組件,在組件中更改App.vue的一個data信息,奈何學術不精,百度了好久,想到通過監聽路由來出發事件
- 主要的是
watch()
這個API,只要路由變化就會觸發,但是瀏覽器的後退是不會觸發的
export default{
data:function(){
return{
isLogin: false,
userName:''
}
},
methods:{
zhuxiao(){
window.sessionStorage.setItem('isLogin', false)
this.isLogin = false
this.$router.push({
path: `/login`
})
}
},
watch:{
$route(to){
if(to.path === '/view'){
this.isLogin = true
this.userName = window.sessionStorage.getItem('userName')
}
}
}
}