一、v-model使用和原理
1、v-model的基本使用
v-model用來實習那表單元素和數據的
雙向綁定
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<div id="app">
<input type="text" v-model="message">
<h1>{{message}}</h1>
</div>
<script src="../js/vue.js"></script>
<script>
const app = new Vue({
el: '#app',
data: {
message: 'hello,Vue'
}
})
</script>
</body>
</html>
2、v-model的原理
v-bind綁定一個value屬性
v-on指令給當前元素綁定inpu事件
(1)方式一
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<div id="app">
<input type="text" v-model="message" @input="valueChange">
<h1>{{message}}</h1>
</div>
<script src="../js/vue.js"></script>
<script>
const app = new Vue({
el: '#app',
data: {
message: 'hello,Vue'
},
methods: {
valueChange(event) {
this.message = event.target.value
}
}
})
</script>
</body>
</html>
(2)方式二
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<div id="app">
<input type="text" v-model="message" @input="message = $event.target.value">
<h1>{{message}}</h1>
</div>
<script src="../js/vue.js"></script>
<script>
const app = new Vue({
el: '#app',
data: {
message: 'hello,Vue'
}
})
</script>
</body>
</html>
3、v-model結合radio類型
這裏就不需要給2個input加相同的name,自己會互斥
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<div id="app">
<label for="male">
<input type="radio" id="male" v-model="sex" value="男">男
</label>
<label for="female">
<input type="radio" id="female" v-model="sex" value="女">女
</label>
<h1>你選擇的性別:{{sex}}</h1>
</div>
<script src="../js/vue.js"></script>
<script>
const app = new Vue({
el: '#app',
data: {
message: 'hello,Vue',
sex: '男'
}
})
</script>
</body>
</html>
4、v-model結合checkbox類型
(1)checkbox單選框
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<div id="app">
<label for="agree">
<input type="checkbox" id="agree" v-model="isAgree">同意協議
</label>
<h2>你選擇的是:{{isAgree}}</h2>
<button :disabled="!isAgree">下一步</button>
</div>
<script src="../js/vue.js"></script>
<script>
const app = new Vue({
el: '#app',
data: {
message: 'hello,Vue',
isAgree: false
}
})
</script>
</body>
</html>
(2)checkbox多選框
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<div id="app">
<input type="checkbox" v-model="habbies" value="足球">足球
<input type="checkbox" v-model="habbies" value="藍球">藍球
<input type="checkbox" v-model="habbies" value="排球">排球
<input type="checkbox" v-model="habbies" value="桌球">桌球
<h2>你的愛好是:{{habbies}}</h2>
</div>
<script src="../js/vue.js"></script>
<script>
const app = new Vue({
el: '#app',
data: {
message: 'hello,Vue',
habbies: []
}
})
</script>
</body>
</html>
5、v-model結合select類型
(1)select單選
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<div id="app">
<select name="" id="" v-model="fruit">
<option value="蘋果">蘋果</option>
<option value="香蕉">香蕉</option>
<option value="榴蓮">榴蓮</option>
<option value="葡萄">葡萄</option>
</select>
<h2>你選擇的水果是:{{fruit}}</h2>
</div>
<script src="../js/vue.js"></script>
<script>
const app = new Vue({
el: '#app',
data: {
message: 'hello,Vue',
fruit: '香蕉'
}
})
</script>
</body>
</html>
(2)select多選
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<div id="app">
<select name="" id="" v-model="fruits" multiple>
<option value="蘋果">蘋果</option>
<option value="香蕉">香蕉</option>
<option value="榴蓮">榴蓮</option>
<option value="葡萄">葡萄</option>
</select>
<h2>你選擇的水果是:{{fruits}}</h2>
</div>
<script src="../js/vue.js"></script>
<script>
const app = new Vue({
el: '#app',
data: {
message: 'hello,Vue',
fruits: []
}
})
</script>
</body>
</html>
6、input中的值綁定
通過v-bind:value動態給value綁定值
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<div id="app">
<label v-for="item in allHabbies" :for="item">
<input type="checkbox" :value="item" v-model="hobbies">{{item}}
</label>
<h2>你的愛好是: {{hobbies}}</h2>
</div>
<script src="../js/vue.js"></script>
<script>
const app = new Vue({
el: '#app',
data: {
message: 'hello,Vue',
hobbies: [],
allHabbies: ['籃球','足球', '桌球']
}
})
</script>
</body>
</html>
7、v-model修飾符的使用
(1)lazy
數據在失去焦點或者會車時纔會更新
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<div id="app">
<input type="text" v-model.lazy="message">{{message}}
</div>
<script src="../js/vue.js"></script>
<script>
const app = new Vue({
el: '#app',
data: {
message: 'hello,Vue'
}
})
</script>
</body>
</html>
(2)number
讓輸入框的的內容自動轉成數字類型
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<div id="app">
<input type="number" v-model.number="age">
<h2>{{age}}--{{typeof age}}</h2>
</div>
<script src="../js/vue.js"></script>
<script>
const app = new Vue({
el: '#app',
data: {
message: 'hello,Vue',
age: 0
}
})
</script>
</body>
</html>
(3)trim
過濾內容左右兩邊的空格
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<div id="app">
<input type="text" v-model.trim="name">
<h2>你輸入的名字:{{name}}</h2>
</div>
<script src="../js/vue.js"></script>
<script>
const app = new Vue({
el: '#app',
data: {
message: 'hello,Vue',
name: ''
}
})
</script>
</body>
</html>
二、組件
1、註冊組件的基本步驟
-
1、創建組件構造器
-
2、註冊組件
-
3、使用組件
2、組件化的基本使用
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<div id="app">
<my-cpn></my-cpn>
<my-cpn></my-cpn>
</div>
<script src="../js/vue.js"></script>
<script>
// 1、創建組件構造器對象
const cpnC = Vue.extend({
template: `
<div>
<h2>標題</h2>
<p>內容一</p>
<p>內容二</p>
</div>
`
});
// 2、註冊組件
Vue.component('my-cpn', cpnC);
const app = new Vue({
el: '#app',
data: {
message: 'hello,Vue'
}
})
</script>
</body>
</html>
3、全局組件和局部組件
(1)全局組件
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<div id="app">
<cpn></cpn>
<cpn></cpn>
</div>
<div id="app1">
<cpn></cpn>
</div>
<script src="../js/vue.js"></script>
<script>
const cpnC = Vue.extend({
template: `
<div>
<h2>標題</h2>
<p>內容一</p>
<p>內容二</p>
</div>
`
});
Vue.component('cpn', cpnC);
const app = new Vue({
el: '#app',
data: {
message: 'hello,Vue'
}
});
const app1 = new Vue({
el: '#app1',
data: {
message: 'hello,Vue'
}
})
</script>
</body>
</html>
(2)局部組件
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<div id="app">
<cpn></cpn>
<cpn></cpn>
</div>
<div id="app1">
<cpn></cpn>
</div>
<script src="../js/vue.js"></script>
<script>
const cpnC = Vue.extend({
template: `
<div>
<h2>標題</h2>
<p>內容一</p>
<p>內容二</p>
</div>
`
});
// Vue.component('cpn', cpnC);
const app = new Vue({
el: '#app',
data: {
message: 'hello,Vue'
},
components: {
cpn: cpnC
}
});
const app1 = new Vue({
el: '#app1',
data: {
message: 'hello,Vue'
}
})
</script>
</body>
</html>
4、父組件和子組件
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<div id="app">
<cpn2></cpn2>
</div>
<script src="../js/vue.js"></script>
<script>
// 1、第一個組件構造器(子組件)
const cpnC1 = Vue.extend({
template: `
<div>
<h2>標題一</h2>
<p>內容一</p>
<p>內容二</p>
</div>
`
});
// 2、第二個組件構造器(父組件)
const cpnC2 = Vue.extend({
template: `
<div>
<h2>標題二</h2>
<p>內容一</p>
<p>內容二</p>
<cpn1></cpn1>
</div>
`,
components: {
cpn1: cpnC1
}
});
const app = new Vue({
el: '#app',
data: {
message: 'hello,Vue'
},
components: {
cpn2: cpnC2
}
})
</script>
</body>
</html>
5、組件的語法糖註冊方式
省去了Vue.extend()的步驟,而是可以直接使用一個對象來替代
(1)全局註冊
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<div id="app">
<cpn1></cpn1>
</div>
<script src="../js/vue.js"></script>
<script>
Vue.component('cpn1',{
template: `
<div>
<h2>標題</h2>
<p>內容一</p>
<p>內容二</p>
</div>
`
});
const app = new Vue({
el: '#app',
data: {
message: 'hello,Vue'
}
})
</script>
</body>
</html>
(2)局部註冊
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<div id="app">
<cpn1></cpn1>
</div>
<script src="../js/vue.js"></script>
<script>
const app = new Vue({
el: '#app',
data: {
message: 'hello,Vue'
},
components: {
'cpn1': {
template: `
<div>
<h2>標題</h2>
<p>內容一</p>
<p>內容二</p>
</div>
`
}
}
})
</script>
</body>
</html>
6、組件模板的分離寫法
(1)通過script標籤
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<div id="app">
<cpn></cpn>
</div>
<script type="text/x-template" id="cpn">
<div>
<h2>標題一</h2>
<p>內容一</p>
<p>內容二</p>
</div>
</script>
<script src="../js/vue.js"></script>
<script>
Vue.component('cpn',{
template: '#cpn'
});
const app = new Vue({
el: '#app',
data: {
message: 'hello,Vue'
},
})
</script>
</body>
</html>
</body>
</html>
(2)通過template標籤
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<div id="app">
<cpn></cpn>
</div>
<template id="cpn">
<div>
<h2>標題一</h2>
<p>內容一</p>
<p>內容二</p>
</div>
</template>
<script src="../js/vue.js"></script>
<script>
Vue.component('cpn',{
template: '#cpn'
});
const app = new Vue({
el: '#app',
data: {
message: 'hello,Vue'
},
})
</script>
</body>
</html>
</body>
</html>
7、組件中的數據存放
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<div id="app">
<cpn></cpn>
</div>
<template id="cpn">
<div>
<h2>標題一{{title}}</h2>
<p>內容一</p>
<p>內容二</p>
</div>
</template>
<script src="../js/vue.js"></script>
<script>
Vue.component('cpn',{
template: '#cpn',
data() {
return {
title: 'yyy'
}
}
});
const app = new Vue({
el: '#app',
data: {
message: 'hello,Vue'
},
})
</script>
</body>
</html>
</body>
</html>
8、組件data爲什麼是函數
用函數每次都會生成新的內存對象,從而每個組件都互不關聯
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<div id="app">
<cpn></cpn>
<cpn></cpn>
</div>
<template id="cpn">
<div>
<h1>當前計數:{{counter}}</h1>
<button @click="increment">+</button>
<button @click="decrement">-</button>
</div>
</template>
<script src="../js/vue.js"></script>
<script>
Vue.component('cpn',{
template: '#cpn',
data() {
return {
counter: 0
}
},
methods: {
increment() {
this.counter++
},
decrement() {
this.counter--
}
}
});
const app = new Vue({
el: '#app',
data: {
message: 'hello,Vue'
}
})
</script>
</body>
</html>
9、父子組件的通信
(1)通信方法
-
1、通過props向子組件傳遞數據
-
2、通過事件向父組件發送消息($emit Events)
(2)父組件向子組件傳遞數據
props驗證支持的數據類型:String、Number、Boolean、Array、Object、Date、Function、Symbol
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<div id="app">
<cpn :cmovies="movies" :cmessage="message"></cpn>
</div>
<template id="cpn">
<div>
<ul>
<li v-for="item in cmovies">{{item}}</li>
</ul>
{{cmessage}}
</div>
</template>
<script src="../js/vue.js"></script>
<script>
const cpn = {
template: '#cpn',
// props: ['cmovies', 'cmessage'],
props: {
// 1、類型限制
// cmovies: Array,
// cmessage: String
// 2、提供默認值
cmessage: {
type: String,
default: 'aaaa',
required: true //必須傳
},
//類型是對象或數組時,默認值必須是一個函數
cmovies: {
type: Array,
default() {
return {}
}
}
},
data() {
return {}
}
}
const app = new Vue({
el: '#app',
data: {
message: 'hello,Vue',
movies: ['海賊王', '火影忍者','海爾兄弟']
},
components: {
cpn
}
})
</script>
</body>
</html>
(3)組件通信-父傳子(props中的駝峯標識)
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<div id="app">
<cpn :c-info="info"></cpn>
</div>
<template id="cpn">
<div>
<h1>{{cInfo}}</h1>
</div>
</template>
<script src="../js/vue.js"></script>
<script>
const cpn = {
template: '#cpn',
props: {
cInfo: {
type: Object,
default() {
return {}
}
}
}
};
const app = new Vue({
el: '#app',
data: {
info: {
name: 'yyy',
age: 18
}
},
components: {
cpn
}
})
</script>
</body>
</html>
(4)組件通信-子傳父(自定義事件)
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<!--父組件-->
<div id="app">
<cpn @itemclick="cpnClick"></cpn>
</div>
<template id="cpn">
<div>
<button v-for="item in categories" @click="btnClick(item)">{{item.name}}</button>
</div>
</template>
<script src="../js/vue.js"></script>
<script>
// 子組件
const cpn = {
template: '#cpn',
data() {
return {categories: [
{id:'a', name:'熱門推薦'},
{id:'a', name:'手機數碼'},
{id:'a', name:'電腦辦公'}
]
}},
methods: {
btnClick(item){
//發射自定義事件
this.$emit('itemclick',item)
}
}
};
const app = new Vue({
el: '#app',
data: {
},
components: {
cpn
},
methods: {
cpnClick(item) {
console.log('cpnClick',item);
}
}
})
</script>
</body>
</html>
(5)組件通信-父子通信案例
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<div id="app">
<cpn :number1="num1" :number2="num2" @num1change="num1change" @num2change="num2change"></cpn>
</div>
<template id="cpn">
<div>
<h2>props:{{number1}}</h2>
<h2>data:{{dnumber1}}</h2>
<!--<input type="text" v-model="dnumber1">-->
<input type="text" :value="dnumber1" @input="num1Input">
<h2>props:{{number2}}</h2>
<h2>data:{{dnumber2}}</h2>
<!--<input type="text" v-model="dnumber2">-->
<input type="text" :value="dnumber2" @input="num2Input">
</div>
</template>
<script src="../js/vue.js"></script>
<script>
const app = new Vue({
el: '#app',
data: {
num1: 1,
num2: 2
},
methods: {
num1change(value) {
this.num1 = parseInt(value)
},
num2change(value) {
this.num2 = parseInt(value)
}
},
components: {
cpn: {
template: '#cpn',
props: {
number1: Number,
number2: Number
},
data() {
return {
dnumber1: this.number1,
dnumber2: this.number2
}
},
methods: {
num1Input(event) {
// 1、將input中的value賦值到dnumber中
this.dnumber1 = event.target.value;
// 2、爲了讓父組件可以修改值,發出一個事件
this.$emit('num1change', this.dnumber1);
// 3、同時修改dnumber2的值
this.dnumber2 = this.dnumber1 * 100;
this.$emit('num2change', this.dnumber2)
},
num2Input(event) {
this.dnumber2 = event.target.value;
this.$emit('num2change', this.dnumber2)
//同時修改dnumber1的值
this.dnumber1 = this.dnumber2 / 100;
this.$emit('num1change', this.dnumber1)
}
}
}
}
})
</script>
</body>
</html>
(6)組件訪問-父訪問子-children-refs
一般使用refs,當需要訪問所有的時候使用children
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<div id="app">
<div>
<cpn ref="aaa"></cpn>
<button @click="btnClick">按鈕</button>
</div>
</div>
<template id="cpn">
<div>我是子組件</div>
</template>
<script src="../js/vue.js"></script>
<script>
const app = new Vue({
el: '#app',
data: {
message: 'hello,Vue'
},
methods: {
btnClick() {
console.log(this.$children);
// 1、$children
// this.$children[0].showMessage();
// 2、$refs
console.log(this.$refs.aaa.showMessage());
}
},
components: {
cpn: {
template: "#cpn",
methods: {
showMessage() {
console.log('showMessage');
}
}
}
}
})
</script>
</body>
</html>
三、組件化高級
1、slot-插槽的基本使用
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<div id="app">
<cpn></cpn>
<cpn><span>1111</span></cpn>
</div>
<template id="cpn">
<div>
<h1>我是子組件</h1>
<slot><button>按鈕</button></slot>
</div>
</template>
<script src="../js/vue.js"></script>
<script>
const app = new Vue({
el: '#app',
data: {
message: 'hello,Vue'
},
components: {
cpn: {
template: '#cpn'
}
}
})
</script>
</body>
</html>
2、slot-具名插槽的使用
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<div id="app">
<cpn><span slot="center">標題</span></cpn>
</div>
<template id="cpn">
<div>
<slot name="left"><span>左邊</span></slot>
<slot name="center"><span>中間</span></slot>
<slot name="right"><span>右邊</span></slot>
</div>
</template>
<script src="../js/vue.js"></script>
<script>
const app = new Vue({
el: '#app',
data: {
message: 'hello,Vue'
},
components: {
cpn: {
template: '#cpn'
}
}
})
</script>
</body>
</html>
3、什麼是編譯作用域
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<div id="app">
<cpn v-show="isShow"></cpn>
</div>
<template id="cpn">
<div>
<h2>我是子組件</h2>
<p>哈哈</p>
<button v-show="isShow">按鈕</button>
</div>
</template>
<script src="../js/vue.js"></script>
<script>
const app = new Vue({
el: '#app',
data: {
message: 'hello,Vue',
isShow: true
},
components: {
cpn: {
template: '#cpn',
data() {
return {
isShow: false
}
}
}
}
})
</script>
</body>
</html>
4、作用域插槽案例
父組件替換插槽的標籤,但是內容由子組件來提供
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<div id="app">
<cpn></cpn>
<cpn>
<template slot-scope="slot">
<!--<span v-for="item in slot.data">{{item}} - </span>-->
<span>{{slot.data.join(' - ')}}</span>
</template>
</cpn>
</div>
<template id="cpn">
<div>
<slot :data="pLanguages"> <!--data可以自定義修改-->
<ul>
<li v-for="item in pLanguages">{{item}}</li>
</ul>
</slot>
</div>
</template>
<script src="../js/vue.js"></script>
<script>
const app = new Vue({
el: '#app',
data: {
message: 'hello,Vue',
},
components: {
cpn: {
template: '#cpn',
data() {
return {
pLanguages: ['JavaScript', 'C++', 'Java', 'C#', 'Python']
}
}
}
}
})
</script>
</body>
</html>
四、前端模塊化
1、ES6實現模塊化
(1)index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<script src="aaa.js" type="module"></script>
<script src="bbb.js" type="module"></script>
<script src="mmm.js" type="module"></script>
</body>
</html>
(2)aaa.js
var name = '小明';
var age = 18;
var flag = true;
function sum(num1, num2) {
return num1 + num2
}
if (flag) {
console.log(sum(20, 30));
}
// 1、到處方式一
export {
flag,sum
}
// 2、導出方式二
export var height = 1.88
//3、到處函數/類
export function mul(num1, num2) {
return num1 + num2
}
(3)bbb.js
var name = '小紅';
var flag = false;
(4)mmm.js
import {flag, sum} from './aaa.js';
if (flag) {
console.log('小明');
console.log(sum(20, 30));
}
import addr from './aaa.js';
console.log(addr);
// 統一導入
// import * as aaa from './aaa.js'
// console.log(aaa.flag);