Vue 的基本语法
1.Hello Vuejs
<div id="app">
<p>{{message}}</p>
<li v-for="item in movies">{{item}}</li>
<h3>当前计数:{{counter}}</h3>
<button v-on:click="add">+</button>
<button @click="sub">-</button>
</div>
<script src="../js/vue.js"></script>
<script>
const app = new Vue({
el: '#app',
data: {
message: '你好!',
movies: ['战狼2', '哪吒', '星际穿越'],
counter: 0
},
methods: {
add:function(){
this.counter++
},
sub:function(){
this.counter--
}
}
})
</script>
2.Mustache 语法
<div id="app">
<h2>{{message}}</h2>
<h2>{{firstName+lastName}}</h2>
<h2>{{firstName+' '+lastName}}</h2>
<h2>{{firstName}} {{lastName}}</h2>
<h2>{{counter*2}}</h2>
</div>
<script src="../js/vue.js"></script>
<script>
const app = new Vue({
el: '#app',
data: {
message: 'hello',
firstName: 'chen',
lastName: 'ganpin',
counter: 100
}
})
</script>
3.指令的使用
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<style>
.active {
color: red;
}
</style>
</head>
<body>
<div id="app">
<h2 v-once>{{message}}</h2>
<h2 v-text="message"></h2>
<h2 v-html="url"></h2>
<h2 v-pre>{{message}}</h2>
<hr/>
<img v-bind:src="imageUrl" alt="" width="20px">
<a v-bind:href="aHref">百度</a>
<a :href="aHref">百度</a>
<h2 class="title" :class="{active: isActive,line:isLine}">{{message}}</h2>
<h2 class="title" :class="getClass()">{{message}}</h2>
<h2 class="title" :class="[message,aHref]">{{message}}</h2>
<h2 :style="{fontSize: size}">{{message}}</h2>
<button v-on:click="btnClick">按钮</button>
</div>
<script src="../js/vue.js"></script>
<script>
const app = new Vue({
el: '#app',
data: {
message: 'hello',
url: '<a href="https://www.baidu.com">百度</a>',
imageUrl: 'https://cn.vuejs.org/images/logo.png',
aHref: 'https://www.baidu.com',
isActive: true,
isLine: true,
size: '30px'
},
methods: {
btnClick: function () {
this.isActive = !this.isActive
},
getClass: function () {
return {active: this.isActive, line: this.isLine}
}
}
})
</script>
</body>
</html>
4.计算属性的使用
<div id="app">
<h2>{{fullName}}</h2>
<h2>总价:{{totalPrice}}</h2>
</div>
<script src="../js/vue.js"></script>
<script>
const app = new Vue({
el: '#app',
data: {
firstName: 'Lebron',
lastName: 'James',
books: [
{id: 101, name: '计算机', price: 95},
{id: 102, name: '计算机大全', price: 68},
{id: 103, name: '计算机系统', price: 78}
]
},
computed: {
fullName: function () {
return this.firstName + ' ' + this.lastName
},
totalPrice: function () {
let result = 0;
for (let book of this.books) {
result += book.price;
}
return result;
}
}
})
</script>
5.事件监听
<div id="app">
<div @click="divClick">
abc
<button @click.stop="btnClick">按钮</button>
</div>
<hr/>
<form action="/baidu">
<input type="submit" value="提交" @click.prevent="submitClick">
</form>
<hr/>
<input type="text" @keyup.enter="keyUp">
<hr/>
<button @click.once="btn2Click">只点一次</button>
</div>
<script src="../js/vue.js"></script>
<script>
const app = new Vue({
el: '#app',
data: {
message: 'hello'
},
methods: {
btnClick() {
console.log("btnClick")
},
divClick() {
console.log("divClick")
},
submitClick() {
console.log("submitClick")
},
keyUp() {
console.log("keyUp")
},
btn2Click() {
console.log("btn2Click")
}
}
})
</script>
6.v-model 的原理
<div id="app">
<input type="text" :value="message" @input="message=$event.target.value">
{{message}}
</div>
<script src="../js/vue.js"></script>
<script>
const app = new Vue({
el: '#app',
data: {
message: 'hello'
},
methods: {
valueChange(event) {
this.message = event.target.value;
}
}
})
</script>
7. v-model 结合各种类型
<div id="app">
<label for="male">
<input type="radio" id="male" value="男" v-model="sex">男
</label>
<label for="female">
<input type="radio" id="female" value="女" v-model="sex">女
</label>
<h3>你选择的性别是:{{sex}}</h3>
<hr>
<label for="agree">
<input type="checkbox" id="agree" v-model="isAgree">同意协议
</label>
<button :disabled="!isAgree">下一步</button>
<hr>
<input type="checkbox" value="篮球" v-model="hobbies">篮球
<input type="checkbox" value="足球" v-model="hobbies">足球
<input type="checkbox" value="乒乓球" v-model="hobbies">乒乓球
<h3>你当前的爱好是:{{hobbies}}</h3>
<label :for="item" v-for="item in originHobbies">
<input type="checkbox" :value="item" :id="item" v-model="hobbies">{{item}}
</label>
<hr>
<select name="fruit" v-model="fruit">
<option value="苹果">苹果</option>
<option value="香蕉">香蕉</option>
<option value="雪梨">雪梨</option>
</select>
<h3>你选择的水果是:{{fruit}}</h3>
<hr>
<select name="fruits" v-model="fruits" multiple>
<option value="苹果">苹果</option>
<option value="香蕉">香蕉</option>
<option value="雪梨">雪梨</option>
<option value="榴莲">榴莲</option>
</select>
<h3>你选择的水果是:{{fruits}}</h3>
</div>
<script src="../js/vue.js"></script>
<script>
const app = new Vue({
el: '#app',
data: {
sex: '男',
isAgree: false,
hobbies: [],
originHobbies: ['篮球', '足球', '乒乓球', '羽毛球', '台球', '高尔夫球'],
fruit: '香蕉',
fruits: []
}
})
</script>
8.v-model 修饰符的使用
<div id="app">
<input type="text" v-model.lazy="message">{{message}}
<hr>
<input type="number" v-model.number="age">
<h3>{{age}} - {{typeof age}}</h3>
<hr>
<input type="text" v-model.trim="name">
<h3>名字:{{name}}</h3>
</div>
<script src="../js/vue.js"></script>
<script>
const app = new Vue({
el: '#app',
data: {
message: 'hello',
age: 0,
name: ''
}
})
</script>
Vue 格式化日期
<script src="https://cdn.bootcss.com/vue/2.6.11/vue.js"></script>
<script src="https://cdn.bootcss.com/moment.js/2.24.0/moment.js"></script>
<div id="app">
<h2>{{date|dateFormat}}</h2>
</div>
<script>
const app = new Vue({
el: '#app',
data: {
date: '2015-10-20T00:00:00',
},
filters: {
dateFormat(el) {
return moment(el).format("YYYY-MM-DD")
}
}
})
</script>
组件化
1. 组件化的基本使用
<div id="app">
<my-cpn></my-cpn>
<my-cpn></my-cpn>
</div>
<div id="app2">
<my-cpn></my-cpn>
</div>
<script src="../js/vue.js"></script>
<script>
const cpnC = Vue.extend({
template: `
<div>
<h3>我是标题</h3>
<p>我是内容</p>
<p>我是内容2</p>
</div>
`
});
Vue.component('my-cpn', cpnC);
const app = new Vue({
el: '#app',
});
const app2 = new Vue({
el: '#app2'
})
</script>
2. 父组件与子组件
<div id="app">
<cpn2></cpn2>
</div>
<script src="../js/vue.js"></script>
<script>
const cpnC1 = Vue.extend({
template: `
<div>
<h2>我是标题1</h2>
<p>我是内容1</p>
</div>
`
});
const cpnC2 = Vue.extend({
template: `
<div>
<h2>我是标题2</h2>
<p>我是内容2</p>
<cpn1></cpn1>
</div>
`,
components: {
cpn1: cpnC1
}
});
const app = new Vue({
el: '#app',
data: {
message: 'hello'
},
components: {
cpn2: cpnC2
}
})
</script>
3.组件的语法糖注册方式
<div id="app">
<cpn1></cpn1>
<cpn2></cpn2>
</div>
<script src="../js/vue.js"></script>
<script>
Vue.component('cpn1', {
template: `
<div>
<h2>我是标题</h2>
<p>我是内容</p>
</div>
`
});
const app = new Vue({
el: '#app',
components: {
cpn2: {
template: `
<div>
<h2>我是标题</h2>
<p>我是内容</p>
</div>`
}
}
})
</script>
4.组件模板的分离写法
<div id="app">
<cpn></cpn>
<cpn2></cpn2>
</div>
<script type="text/x-template" id="cpn">
<div>
<h2>我是标题</h2>
<p>我是内容</p>
</div>
</script>
<template id="cpn2">
<div>
<h2>我是标题2</h2>
<p>我是内容2</p>
</div>
</template>
<script src="../js/vue.js"></script>
<script>
Vue.component('cpn', {
template: '#cpn'
});
const app = new Vue({
el: '#app',
data: {
message: 'hello'
},
components: {
cpn2: {
template: '#cpn2'
}
}
})
</script>
5. 组件通信 - 父传子
<div id="app">
<cpn :c-info="info"></cpn>
</div>
<template id="cpn">
<h2>{{cInfo}}</h2>
</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: 'Manaphy',
age: 18,
height: 1.88
}
},
components: {
cpn
}
})
</script>
6.组件通信 - 子传父
<div id="app">
<cpn @item-click="cpnClick"></cpn>
<div>{{message}}</div>
</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: '001', name: '热门推荐'},
{id: '002', name: '手机数码'},
{id: '003', name: '家用家电'},
{id: '004', name: '电脑办公'},
]
}
},
methods: {
btnClick(item) {
this.$emit('item-click', item)
}
}
};
const app = new Vue({
el: '#app',
data: {
message: 'hello'
},
components: {
cpn
}, methods: {
cpnClick(item) {
this.message = item.name
}
}
})
</script>
7.组件通信 - 父访问子
<div id="app">
<cpn></cpn>
<cpn></cpn>
<cpn ref="chen"></cpn>
<button @click="btnClick">按钮</button>
</div>
<template id="cpn">
<div>我是子组件</div>
</template>
<script src="../js/vue.js"></script>
<script>
const app = new Vue({
el: '#app',
methods: {
btnClick() {
console.log(this.$children);
console.log(this.$children[0].name);
this.$children[0].showMessage();
console.log(this.$refs.chen.name);
this.$refs.chen.showMessage()
}
},
components: {
cpn: {
template: '#cpn',
data() {
return {
name: 'manaphy'
}
},
methods: {
showMessage() {
console.log('showMessage')
}
}
}
}
})
</script>
8.组件通信 - 子访问父
<div id="app">
<cpn></cpn>
</div>
<template id="cpn">
<div>
<div>我是子组件</div>
<button @click="btnClick">按钮</button>
</div>
</template>
<script src="../js/vue.js"></script>
<script>
const app = new Vue({
el: '#app',
data: {
message: 'hello'
},
components: {
cpn: {
template: '#cpn',
methods: {
btnClick() {
console.log(this.$parent.message);
console.log(this.$root.message);
}
}
}
}
})
</script>
9.组件化高级 - 插槽的基本使用
<div id="app">
<cpn><button>按钮</button></cpn>
<cpn><span>span</span></cpn>
<cpn><i>哈哈哈</i></cpn>
</div>
<template id="cpn">
<div>
<h3>我是子组件</h3>
<slot></slot>
</div>
</template>
<script src="../js/vue.js"></script>
<script>
const cpn = {
template: '#cpn'
};
const app = new Vue({
el: '#app',
components: {
cpn
}
})
</script>
10.组件化高级 - 具名插槽的使用
<div id="app">
<cpn>
<span slot="center">标题</span>
<button slot="center">按钮</button>
</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 cpn = {
template: '#cpn'
}
const app = new Vue({
el: '#app',
components: {
cpn
}
})
</script>
11.组件化高级 - 作用域插槽的案例
<div id="app">
<cpn></cpn>
<cpn>
<template slot-scope="slot">
<span>{{slot.data.join(' - ')}}</span>
</template>
</cpn>
</div>
<template id="cpn">
<div>
<slot :data="pLanguages">
<ul>
<li v-for="item in pLanguages">{{item}}</li>
</ul>
</slot>
</div>
</template>
<script src="../js/vue.js"></script>
<script>
const cpn = {
template: '#cpn',
data() {
return {
pLanguages: ['Java', 'Python', 'Go', 'javaScript', 'C']
}
}
};
const app = new Vue({
el: '#app',
components: {
cpn
},
})
</script>
经典案例
购物车案例
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>图书购物车</title>
<style>
table {
border: 1px solid #e9e9e9;
border-collapse: collapse;
border-spacing: 0;
}
th, td {
padding: 8px 16px;
border: 1px solid #e9e9e9;
text-align: left;
}
th {
background-color: #f7f7f7;
color: #5c6b77;
font-weight: 600;
}
</style>
</head>
<body>
<div id="app">
<div v-if="books.length">
<table>
<thead>
<tr>
<th></th>
<th>书籍名称</th>
<th>出版日期</th>
<th>价格</th>
<th>购买数量</th>
<th>操作</th>
</tr>
</thead>
<tbody>
<tr v-for="(item,index) in books">
<td>{{item.id}}</td>
<td>{{item.name}}</td>
<td>{{item.date}}</td>
<td>{{item.price|showPrice}}</td>
<td>
<button @click="decrement(index)" :disabled="item.count==1">-</button>
{{item.count}}
<button @click="increment(index)">+</button>
</td>
<td>
<button @click="remove(index)">移除</button>
</td>
</tr>
</tbody>
</table>
<h3>总价格: {{totalPrice|showPrice}}</h3>
</div>
<div v-else>
<h3>购物车为空</h3>
</div>
</div>
<script src="../js/vue.js"></script>
<script>
const app = new Vue({
el: '#app',
data: {
books: [
{
id: 1,
name: '《算法导论》',
date: '2006-9',
price: 85.00,
count: 1
},
{
id: 2,
name: '《UNIX编程艺术》',
date: '2006-2',
price: 59.00,
count: 1
},
{
id: 3,
name: '《编程珠玑》',
date: '2008-10',
price: 39.00,
count: 1
},
{
id: 4,
name: '《代码大全》',
date: '2006-3',
price: 128.00,
count: 1
},
]
},
methods: {
decrement(index) {
this.books[index].count--
},
increment(index) {
this.books[index].count++
},
remove(index) {
this.books.splice(index, 1)
}
},
computed: {
totalPrice() {
return this.books.reduce(((previousValue, book) => previousValue + book.price * book.count),0);
}
},
filters: {
showPrice(price) {
return '¥' + price.toFixed(2)
}
}
})
</script>
</body>
</html>
选项卡案例
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
<style type="text/css">
.tab ul {
overflow: hidden;
padding: 0;
margin: 0;
}
.tab ul li {
box-sizing: border-box;
padding: 0;
float: left;
width: 100px;
height: 45px;
line-height: 45px;
list-style: none;
text-align: center;
border-top: 1px solid blue;
border-right: 1px solid blue;
}
.tab ul li:first-child {
border-left: 1px solid blue;
}
.tab ul li.active {
background-color: orange;
}
.tab div {
width: 500px;
height: 300px;
display: none;
text-align: center;
font-size: 30px;
line-height: 300px;
border: 1px solid blue;
border-top: 0;
}
.tab div.current {
display: block;
}
</style>
</head>
<body>
<div id="app">
<div class="tab">
<ul>
<li @click='change(index)' :class='currentIndex==index?"active":""' v-for='(item,index) in list'>
{{item.title}}
</li>
</ul>
<div :class='currentIndex==index?"current":""' v-for='(item, index) in list'>
<img :src="item.path" alt="">
</div>
</div>
</div>
<script type="text/javascript" src="../js/vue.js"></script>
<script>
const vm = new Vue({
el: '#app',
data: {
currentIndex: 0,
list: [
{
id: 1,
title: 'apple',
path: 'img/apple.png'
},
{
id: 2,
title: 'orange',
path: 'img/orange.png'
},
{
id: 3,
title: 'lemon',
path: 'img/lemon.png'
}]
},
methods: {
change(index) {
this.currentIndex = index;
}
}
});
</script>
</body>
</html>