第2章 课程介绍
2.1 课程学习方法
1.官方文档的阅读
2.Vue实例的练习
3.实战
2.2 hello world
1.Vue不支持IE8及以下的浏览器(支持所有兼容ECMAScript5的浏览器)
2.<script>
引入js的方式进行学习(开发版本)
3.el:限制Vue处理Dom的范围 data:定义数据 {{}}:插值表达式
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>2.2节Hello World</title>
<script src="../vue.js"></script>
</head>
<body>
<div id="app">{{ content }}</div>
<script>
// 直接操作DOM写法
// var dom = document.getElementById('app');
// dom.innerHTML = 'hello Vuejs';
// setTimeout(function() {
// dom.innerHTML = 'bye Vue.js'
// }, 2000)
var app = new Vue({
el: '#app',
data: {
content: 'hello Vuejs'
}
})
setTimeout(function() {
app.$data.content = 'bye Vue.js'
}, 2000)
</script>
</body>
</html>
2.3 开发TodoList(v-model、v-for、v-on)
1.TodoList参考:www.todolist.cn
2.v-for:用来循环数据
<li v-for="item in list">{{ item }}</li>
3.v-on:click:绑定click事件
<button v-on:click="handleBtnClick">提交</button>
4.v-model:数据的双向绑定
<input type="text" v-model="inputValue">
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>2.3节TodoList-V1.0部分功能</title>
<script src="../vue.js"></script>
</head>
<body>
<div id="app">
<!-- v-model:数据的双向绑定 -->
<input type="text" v-model="inputValue">
<!-- v-on:click:绑定click事件 -->
<button v-on:click="handleBtnClick">提交</button>
<ul>
<!-- v-for:用来循环数据 -->
<li v-for="item in list">{{ item }}</li>
</ul>
</div>
<script>
var app = new Vue({
el: '#app',
data: {
list: [],
inputValue: ''
},
methods: {
handleBtnClick: function(){
this.list.push(this.inputValue)
this.inputValue = ''
}
}
})
</script>
</body>
</html>
2.4 MVVM(设计)模式
1.MVP -> 使用jQuery完成TodoList:面向DOM
View->Presenter->Model
View<-Presenter<-Model
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>2.4节TodoList-jquery部分功能</title>
<script src="../jquery.js"></script>
</head>
<body>
<div>
<input id="input" type="text">
<button id="btn">提交</button>
<ul id="list"></ul>
</div>
<script>
// MVP设计模式 M:模型层 (无);V:视图;P:控制器;
function Page() {
}
$.extend(Page.prototype, {
init: function () {
var btn = $('#btn');
btn.on('click', $.proxy(this.handleBtnClick, this))
},
handleBtnClick: function () {
var inputEle = $('#input');
var inputValue = $('#input').val();
var ulEle = $('#list');
ulEle.append('<li>' + inputValue + '</li>');
inputEle.val('');
}
})
var page = new Page();
page.init();
</script>
</body>
</html>
2.MVVM -> 通过操作数据来改变视图:面向数据
View->ViewModel->Model
View<-ViewModel<-Model
2.1 View:DOM Model:Plain JavaScript Objects ViewModel:Vue
2.5 前端组件化
1.一个整体切分为不同的部分,每个部分就是一个组件
2. 一个组件就是页面上的一个区域
2.6 使用组件改造TodoList
1.全局组件
1.1创建全局组件:
Vue.component("TodoItem", {
props: ['content'],
template: "<li>{{content}}</li>"
})
1.2使用全局组件:
<todo-item v-bind:content="item" v-for="item in list"></todo-item>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>2.6节TodoList-V2.0部分功能组件化-全局组件</title>
<script src="../vue.js"></script>
</head>
<body>
<div id="app">
<!-- v-model:数据的双向绑定 -->
<input v-model="inputValue" type="text">
<!-- v-on:click:绑定click事件 -->
<button v-on:click="handleBtnClick">提交</button>
<!-- v-for:用来循环数据 -->
<!-- v-bind:把数据绑定到组件 -->
<ul>
<!-- <li v-for="item in list">{{ item }}</li> -->
<todo-item v-bind:content="item" v-for="item in list"></todo-item>
</ul>
</div>
<script>
// component:创建全局组件
Vue.component("TodoItem", {
props: ['content'],
template: "<li>{{content}}</li>"
})
var app = new Vue({
el: '#app',
data: {
list: [],
inputValue: ''
},
methods: {
handleBtnClick: function(){
this.list.push(this.inputValue)
this.inputValue = ''
}
}
})
</script>
</body>
</html>
2. 局部组件
2.1创建局部组件:
var TodoItem = {
props: ['content'],
template: "<li>{{content}}</li>"
}
2.2注册局部组件:
components: { TodoItem },
2.2使用局部组件:
<todo-item v-bind:content="item" v-for="item in list"></todo-item>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>2.6节TodoList-V2.0部分功能组件化-局部组件</title>
<script src="../vue.js"></script>
</head>
<body>
<div id="app">
<!-- v-model:数据的双向绑定 -->
<input v-model="inputValue" type="text">
<!-- v-on:click:绑定click事件 -->
<button v-on:click="handleBtnClick">提交</button>
<!-- v-for:用来循环数据 -->
<!-- v-bind:把数据绑定到组件 -->
<ul>
<!-- <li v-for="item in list">{{ item }}</li> -->
<todo-item v-bind:content="item" v-for="item in list"></todo-item>
</ul>
</div>
<script>
var TodoItem = {
props: ['content'],
template: "<li>{{content}}</li>"
}
var app = new Vue({
el: '#app',
data: {
list: [],
inputValue: ''
},
components: {
TodoItem
},
methods: {
handleBtnClick: function(){
this.list.push(this.inputValue)
this.inputValue = ''
}
}
})
</script>
</body>
</html>
2.7 简单的组件间传值
1.父组件--->子组件
父组件:在使用子组件时使用v-bind属性
v-bind: content="item"
v-bind: index="index"
子组件:在使用子组件中使用props属性接受父组件传过来值
props:['content', 'index'],
2.子组件--->父组件
子组件:在子组件的method方法中使用$emit方法向外触发一个事件
this.$emit("delete", this.index)
子组件:在使用子组件的标签上使用v-on监听delete事件然后触发自身的handleItemDelete方法
v-on:delete="handleItemDelete"
3.简写:v-bind:---》: v-on---》@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>2.7节TodoList-V3.0完整功能</title>
<script src="../vue.js"></script>
</head>
<body>
<div id="app">
<!-- v-model:数据的双向绑定 -->
<input v-model="inputValue" type="text">
<!-- v-on:click:绑定click事件 -->
<button v-on:click="handleBtnClick">提交</button>
<!-- v-for:用来循环数据 -->
<!-- v-bind:把数据绑定到组件 -->
<ul>
<!-- <li v-for="item in list">{{ item }}</li> -->
<todo-item v-bind:content="item" v-bind:index="index" v-for="(item, index) in list"
v-on:delete="handleItemDelete"></todo-item>
</ul>
</div>
<script>
var TodoItem = {
props: ['content', 'index'],
template: "<li v-on:click='handleItemClick'>{{content}}</li>" ,
methods: {
handleItemClick: function() {
// $.emit:向父组件触发事件
this.$emit("delete", this.index)
}
}
}
var app = new Vue({
el: '#app',
data: {
list: [],
inputValue: ''
},
components: {
TodoItem
},
methods: {
handleBtnClick: function(){
this.list.push(this.inputValue);
this.inputValue = '';
},
handleItemDelete: function (index) {
this.list.splice(index, 1);
}
}
})
</script>
</body>
</html>
2.8 本章小结
Vue官网阅读‘基础’--->‘介绍’
第3章 Vue基础精讲
3.1 Vue实例
1.Vue实例的创建
var vm = new Vue({})
// 这是一个根实例
Vue.component('item', {
template: '<div>hello</div>'
})
// 组件也是一个实例
2.Vue实例的属性
el data method
可以在控制台用vm.$el
、vm.$data
、vm.$method
3.2 Vue实例的生命周期
1.生命周期函数定义:Vue实例在某一时间点会自动执行的函数(共11个)
8个常用的生命周期函数:beforeCreate ---> created ---> (判断el) ---> (判断template) ---> beforeMount ---> mounted ---> (执行vm.$destory) ---> beforeDestory ---> destoryed ---> (当data改变时) ---> beforeUpdate ---> update 3个(不常用):activated、 deactivated、 errorCaptured
2.Vue官网阅读‘Vue实例’
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Vue的生命周期</title>
<script src="../vue.js"></script>
</head>
<body>
<div id="app">{{ test }}</div>
<script>
// 生命周期函数就是Vue实例在某一个时间点自动执行的函数
var vm = new Vue({
el: '#app',
data: {
test: 'hell Vue'
},
//页面渲染时执行beforeCreate、created、beforeMount、mounted
beforeCreate: function () {
console.log("beforeCreate")
},
created: function () {
console.log("created")
},
beforeMount: function () {
console.log("beforeMount")
},
mounted: function () {
console.log("mounted")
},
//when vm.$destroy() is called
beforeDestroy: function () {
console.log("beforeDestroy")
},
destroyed: function () {
console.log("destroyed")
},
//when data changes
beforeUpdate: function () {
console.log("beforeUpdate")
},
updated: function () {
console.log("updated")
},
})
</script>
</body>
</html>
3.3 Vue的模板语法
1.插值表达式:{{}}(与v-text作用完全相同)
2.v-text:不解析html语法
3.v-html:解析html语法
4.插值表达式与v-text和v-html中的语法都时JavaScript表达式
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>模板语法</title>
<script src="../vue.js"></script>
</head>
<body>
<div id="app">
<div>{{ content }}</div>
<!-- 此处content为JS表达式 -->
<div v-text="content"></div>
<!-- v-html:不进行转义直接解释输出 -->
<div v-html="'Hello' + content"></div>
</div>
<script>
var app = new Vue({
el: '#app',
data: {
content: '<h1>Vue</h1>'
}
})
</script>
</body>
</html>
3.4 计算属性、方法、侦听器
1.计算属性
特点:内置缓存,依赖值无变化就不会进行计算
2.方法
特点:无内置缓存,只要页面重新渲染就要重新执行
3.侦听器
特点:侦听的变量变化时才会执行程序
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>计算属性、方法、监听器</title>
<script src="../vue.js"></script>
</head>
<body>
<div id="app">
{{ fullName }}
<!-- 方法:{{ fullName() }} -->
{{ age }}
</div>
<script>
var app = new Vue({
el: '#app',
data: {
firstName: 'vience',
lastName: 'tang',
fullName: 'vience tang',//watch
age: 23
},
//计算属性(推荐使用)
//内置缓存,依赖值无变化就不会进行计算
// computed: {
// fullName: function() {
// console.log("计算属性");
// return this.firstName + " " + this.lastName;
// }
// }
//方法
//无内置缓存只要刷新就要重新执行
// methods: {
// fullName: function () {
// console.log("方法");
// return this.firstName + " " + this.lastName;
// }
// }
//侦听的变量变化时才会执行程序
watch: {
firstName: function () {
console.log("监听firstName");
this.fullName = this.firstName + " " + this.lastName;
},
lastName: function () {
console.log("监听lastName");
this.fullName = this.firstName + " " + this.lastName;
}
}
})
</script>
</body>
</html>
3.5 计算属性的setter和getter
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>计算属性的setter和getter</title>
<script src="../vue.js"></script>
</head>
<body>
<div id="app">
{{ fullName }}
</div>
<script>
var app = new Vue({
el: '#app',
data: {
firstName: 'vience',
lastName: 'tang',
},
computed: {
fullName: {
get: function() {
return this.firstName + " " + this.lastName;
},
set: function(value) {
var arr = value.split(" ");
this.firstName = arr[0];
this.lastName = arr[1];
}
}
}
})
</script>
</body>
</html>
3.6 Vue中的样式绑定
1.class样式绑定
对象方式::class="{activated: isActivated}"
数组方式::class="[activated]"
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Vue中的样式绑定-class</title>
<script src="../vue.js"></script>
<style>
.activated { color: red; }
</style>
</head>
<body>
<div id="app">
<!-- <div :class="{activated: isActivated}" @click="handleDivClick">
Hello world
</div> -->
<div :class="[activated]" @click="handleDivClick">
Hello world
</div>
</div>
<script>
var vm = new Vue({
el: '#app',
data: {
// isActivated: false,
activated: ''
},
methods: {
handleDivClick: function () {
// this.isActivated = !this.isActivated
this.activated = this.activated === 'activated' ? '' : 'activated'
}
}
})
</script>
</body>
</html>
2.style样式绑定
对象方式::style="styleOBj"
数组方式::style="[styleOBj, {fontSize: '20px'}]"
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Vue中的样式绑定-style</title>
<script src="../vue.js"></script>
</head>
<body>
<div id="app">
<!-- <div :style="styleOBj" @click="handleDivClick">
Hello world
</div> -->
<div :style="[styleOBj, {fontSize: '20px'}]" @click="handleDivClick">
Hello world
</div>
</div>
<script>
var app = new Vue({
el: '#app',
data: {
styleOBj: {
color: 'black'
}
},
methods: {
handleDivClick: function () {
this.styleOBj.color = this.styleOBj.color === 'black' ? 'red' : 'black'
}
}
})
</script>
</body>
</html>
3.7 Vue中的条件渲染
1.v-if:值为true时显示,值为false时消失
特点:通过DOM的生成与删除实现,比较耗费性能
2.v-show:值为true时显示,值为false时消失
特点:通过CSS中display的值为none来进行隐藏,节省性能
3.v-if v-else-if v-else
注意点1:必须连在一起进行使用 注意点2:若在v-if和v-else(v-else-if)中同事使用input标签时一定要定义不同的key值,若无则会复用已经再在的input标签
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Vue中的条件渲染</title>
<script src="../vue.js"></script>
</head>
<body>
<div id="app">
<!-- 连在一起写 -->
<!-- <div v-if="show === 'a'">This is A</div>
<div v-else-if="show === 'b'">This is B</div>
<div v-else>This is others</div> -->
<!-- 删除新加DOM -->
<div v-if="show">{{msg}}</div>
<div v-else>Bye World</div>
<!-- 若v-if下与v-else下都有一个input输入框时,需要使用不同的key值进行区别,因为VUE会默认减少不必要的渲染而默认使用之前的input -->
<!-- 使用display:none 优先使用 减少DOM的删除与渲染-->
<div v-show="show">{{msg}}</div>
</div>
<script>
var app = new Vue({
el: '#app',
data: {
show: false,
// show: 'a',
msg: 'Hello world'
}
})
</script>
</body>
</html>
3.8 Vue中的列表渲染
1.数组的列表渲染
注意点:使用后端放回的唯一值作为key值
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Vue中的列表渲染</title>
<script src="../vue.js"></script>
</head>
<body>
<div id="app">
<!-- <div v-for='item in list'>{{item}}</div> -->
<!-- 不推荐使用index做为key值,因为使用index作为key值时会存在相同的情况,而且还比较耗费性能 -->
<!-- <div v-for='(item, index) of list' :key='index'>{{index}}---{{item}}</div> -->
<div v-for='item of list' :key='item.id'>{{item.id}}---{{item.text}}</div>
</div>
<script>
var app = new Vue({
el: '#app',
data: {
// list: ["hello", "vience", "nice", "to", "meet", "you"]
list: [ { id: '000001', text: 'hello' }, { id: '000002', text: 'vience' }, { id: '000003', text: 'nice' }, { id: '000004', text: 'to' }, { id: '000005', text: 'meet' }, { id: '000006', text: 'you' } ]
}
})
</script>
</body>
</html>
2.操作数组
注意点:通过数组下标来操作数组,页面不会发生重新渲染,若想发生重新渲染则应该使用下面的两种方法
1.操作数组的方法(变异方法7个):push pop shift unshift splice sort reserve
控制台操作:
vm.list.splice(1, 1, {id: '222222', text: 'Tang'})
2.数组是引用类型,直接改变引用即可
控制台操作:
vm.list = [ { id: '000001', text: 'hello' }, { id: '222222', text: 'Tang' }, { id: '000003', text: 'nice' }, { id: '000004', text: 'to' }, { id: '000005', text: 'meet' }, { id: '000006', text: 'you' } ]
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Vue中的列表渲染---操作数组</title>
<script src="../vue.js"></script>
</head>
<body>
<div id="app">
<!-- <div v-for='item in list'>{{item}}</div> -->
<!-- 不推荐使用index做为key值,因为使用index作为key值时会存在相同的情况,而且还比较耗费性能 -->
<!-- <div v-for='(item, index) of list' :key='index'>{{index}}---{{item}}</div> -->
<div v-for='item of list' :key='item.id'>{{item.id}}---{{item.text}}</div>
<!-- 注意点:通过数组下标来操作数组,页面不会发生重新渲染,若想发生重新渲染则应该使用下面的两种方法 -->
<!-- 1.操作数组的方法:push pop shift unshift splice sort reserve -->
<!-- 控制台操作:vm.list.splice(1, 1, {id: '222222', text: 'Tang'}) -->
<!-- 2.数组是引用类型,直接改变引用即可 -->
<!-- 控制台操作:vm.list = [ { id: '000001', text: 'hello' }, { id: '222222', text: 'Tang' }, { id: '000003', text: 'nice' }, { id: '000004', text: 'to' }, { id: '000005', text: 'meet' }, { id: '000006', text: 'you' } ] -->
</div>
<script>
var vm = new Vue({
el: '#app',
data: {
// list: ["hello", "vience", "nice", "to", "meet", "you"]
list: [ { id: '000001', text: 'hello' }, { id: '000002', text: 'vience' }, { id: '000003', text: 'nice' }, { id: '000004', text: 'to' }, { id: '000005', text: 'meet' }, { id: '000006', text: 'you' } ]
}
})
</script>
</body>
</html>
###3.对象循环渲染
<div v-for='(item, key, index) of userInfo'>{{index}}---{{key}}---{{item}}</div>
注意点:若想给对象增加属性,则需要改变对象的引用
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Vue中的列表渲染---对象</title>
<script src="../vue.js"></script>
</head>
<body>
<div id="app">
<div v-for='(item, key, index) of userInfo'>{{index}}---{{key}}---{{item}}</div>
<!-- 若想给对象增加属性,则需要改变对象的引用 -->
<!-- 控制台输入:vm.userInfo = { id: '000001', name: 'vience', age: 23, salary: 'secret', address: '南京' } -->
</div>
<script>
var vm = new Vue({
el: '#app',
data: { userInfo: { id: '000001', name: 'vience', age: 23, salary: 'secret' } }
})
</script>
</body>
</html>
3.9 Vue中的set方法
Vue.set(vm.userInfo, 'address', '南京')
vm.$set(vm.userInfo, 'address', '南京')
1.对象中的set方法
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Vue中的set方法---对象</title>
<script src="../vue.js"></script>
</head>
<body>
<div id="app">
<div v-for='(item, key, index) of userInfo'>{{index}}---{{key}}---{{item}}</div>
<!-- 若想给对象增加属性,则需要改变对象的引用 -->
<!-- 控制台输入:vm.userInfo = { id: '000001', name: 'vience', age: 23, salary: 'secret', address: '南京' } -->
<!-- 使用set方法也可以改变对象 -->
<!-- 控制台输入:Vue.set(vm.userInfo, 'address', '南京') 或者 vm.$set(vm.userInfo, 'address', '南京') -->
</div>
<script>
var vm = new Vue({
el: '#app',
data: { userInfo: { id: '000001', name: 'vience', age: 23, salary: 'secret' } }
})
</script>
</body>
</html>
2.数组中的set方法
Vue.set(vm.userInfo, 1, 5)
vm.$set(vm.userInfo, 2, 10)
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Vue中的set方法---数组</title>
<script src="../vue.js"></script>
</head>
<body>
<div id="app">
<div v-for='(item, index) of userInfo'>{{index}}---{{item}}</div>
<!-- 使用set方法改变数组 -->
<!-- 控制台输入:Vue.set(vm.userInfo, 1, 5) 或者 vm.$set(vm.userInfo, 2, 10) -->
</div>
<script>
var vm = new Vue({
el: '#app',
data: { userInfo: ['1', '2', '3', '4'] }
})
</script>
</body>
</html>
第4章 深入理解Vue组件
4.1 组件使用的细节点
1.通过is="row"解决table、ul、ol、select中出现的bug
<tr is="row"></tr>
2.子组件之中的data必须是一个函数,返回一个对象,而不是一个对象
data: function() {
return {
content: 'This is a row'
}
},
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>4.1节组件使用中的细节点</title>
<script src="../vue.js"></script>
</head>
<body>
<div id="root">
<!-- 通过is="row"解决table、ul、ol、select中出现的bug -->
<!-- <table>
<tbody>
<tr is="row"></tr>
<tr is="row"></tr>
<tr is="row"></tr>
</tbody>
</table> -->
<!-- <table>
<tbody>
<tr is="row"></tr>
<tr is="row"></tr>
<tr is="row"></tr>
</tbody>
</table> -->
<div ref='hello' @click="handleClick" >
hello world
</div>
</div>
<script>
// Vue.component('row', {
// 子组件之中的data必须是一个函数,返回一个对象,而不是一个对象
// data: function() {
// return {
// content: 'This is a row'
// }
// },
// template: '<tr><td>{{content}}</td></tr>'
// })
var vm = new Vue({
el: '#root',
methods: {
handleClick: function() {
console.log(this.$refs.hello.innerHTML)
// alert('123')
}
}
})
</script>
</body>
</html>
3.ref的使用
3.1 ref使用div标签上时,通过this.$refs.XXX获取的是该标签对应的DOM元素
3.1 ref使用子组件上时,通过this.$refs.XXX获取的是子组件的引用
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>4.1节组件使用中的细节点---ref的用法</title>
<script src="../vue.js"></script>
</head>
<body>
<div id="root">
<!-- ref使用div标签上时,通过this.$refs.XXX获取的是该标签对应的DOM元素 -->
<!-- ref使用子组件上时,通过this.$refs.XXX获取的是子组件的引用 -->
<counter ref='one' @change='handleChange'></counter>
<counter ref='two' @change='handleChange'></counter>
<div>{{ total }}</div>
</div>
<script>
Vue.component('counter', {
template: '<div @click="handleClick">{{ number }}</div>',
data: function() {
return { number: 0 }
},
methods: {
handleClick: function() {
this.number ++
this.$emit('change')
}
}
})
var vm = new Vue({
el: '#root',
data: { total: 0 },
methods: {
handleChange: function() {
this.total = this.$refs.one.number + this.$refs.two.number
}
}
})
</script>
</body>
</html>
4.2 父子组件之间的数据传递
1.父组件 ---> 子组件
父组件通过属性的形式向子组件传递数据
<counter :count='2'></counter>
子组件使用props接收父组件传来的数组
props: ['count'],
2.子组件 ---> 父组件
子组件使用this.emit(′inc′,2,2)方法向父组件传递一个触发事件(可以携带一个或多个参数)‘this.emit('inc', 2)父组件通过对事件进行监听来接收子组件传过来的值
<counter :count='2' @inc='hanleIncrease'>`
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>4.2节父子组件间的数据传递</title>
<script src="../vue.js"></script>
</head>
<body>
<div id="root">
<counter :count='2' @inc='hanleIncrease'></counter>
<counter :count='3' @inc='hanleIncrease'></counter>
<div>{{ total }}</div>
</div>
<script>
var counter = {
props: ['count'],
data: function() {
return { number: this.count }
},
template: '<div @click="handleClick">{{ number }}</div>',
methods: {
handleClick: function() {
// 单向数据流:子组件不能修改父组件传递过来的值,可以通过clone一个副本进行修改
this.number = this.number + 2
// 子组件通过this.$emit('inc', 2,2)方法向父组件传递一个触发事件(可以携带一个或多个参数)
this.$emit('inc', 2)
}
}
}
var vm = new Vue({
el: '#root',
data: { total: 5 },
components: { counter },
methods: {
hanleIncrease: function(val) {
this.total += val
}
}
})
</script>
</body>
</html>
4.3 组件参数校验与非props特性
1.组件参数校验
props: ['content']
props: { content: String }
props: { content: [String, Number] }
props: {
content: {
type: String,
// required: true,
// default: 'default value'
validator: function(value) {
return (value.length > 5)
}
}
}
2.非props特性
非props特性: 子组件没有接受对应的值,而组件使用了,就会报错;父组件调用子组件时,传值的属性会显示在DOM中
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>4.3节组件参数校验与非props特性</title>
<script src="../vue.js"></script>
</head>
<body>
<div id="root">
<child content='hello world'></child>
</div>
<script>
Vue.component('child',{
// props特性:父组件传值,子组件要接收对应的值,父组件调用子组件时,传值的属性不会显示在DOM中
// 非props特性: 子组件没有接受对应的值,而组件使用了,就会报错;父组件调用子组件时,传值的属性会显示在DOM中
// props: ['content']
// props: { content: String }
// props: { content: [String, Number] }
props: {
content: {
type: String,
// required: true,
// default: 'default value'
validator: function(value) {
return (value.length > 5)
}
}
},
template: '<div>{{ content }}</div>'
})
var vm = new Vue({ el: '#root', })
</script>
</body>
</html>
4.4 给组件绑定原生事件
<child @click.native='handleClick'></child>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>4.4节给组件绑定原生事件</title>
<script src="../vue.js"></script>
</head>
<body>
<div id="root">
<!-- 在子组件上绑定的事件属于自定义事件 -->
<!-- <child @click='handleClick'></child> -->
<child @click.native='handleClick'></child>
</div>
<script>
Vue.component('child',{
// 在div元素上绑定的时间属于原生事件
// template: '<div @click="handleClick">Child</div>',
// methods: {
// handleClick: function() {
// this.$emit('click')
// }
// }
template: '<div>Child</div>',
})
var vm = new Vue({
el: '#root',
methods: {
handleClick: function() {
alert('click')
}
}
})
</script>
</body>
</html>
4.5 非父子组件间的传值
1. Vuex
2. Bus/总线/发布订阅模式/观察者模式
Bus创建:
Vue.prototype.bus = new Vue()
事件触发:
this.bus.$emit('change', this.selfContent)
事件监听(单向数据流,不能直接改变父组件传来的值,通过clone改变副本):
this.bus.$on('change', function(msg){
this_ .selfContent = msg
})
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>4.5节非父子组件间的传值</title>
<script src="../vue.js"></script>
</head>
<body>
<div id="root">
<!-- Bus/总线/发布订阅模式/观察者模式 -->
<child content='vience'></child>
<child content='tang'></child>
</div>
<script>
Vue.prototype.bus = new Vue()
Vue.component('child',{
data: function() {
return {
selfContent: this.content
}
},
props: { content: String },
template: '<div @click="handleClick">{{selfContent}}</div>',
methods: {
handleClick: function() {
this.bus.$emit('change', this.selfContent)
}
},
mounted: function() {
var this_ = this
this.bus.$on('change', function(msg){
this_ .selfContent = msg
})
}
})
var vm = new Vue({
el: '#root',
})
</script>
</body>
</html>
4.6 在vue中使用插槽(slot)
1. 插槽一般用于父组件向子组件传递一段DOM结构()
2. 默认内容
3. 具名插槽(支持默认内容)
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>4.6节在vue中使用插槽</title>
<script src="../vue.js"></script>
</head>
<body>
<div id="root">
<!-- slot:用于父组件向子组件传递DOM结构 -->
<!-- <child content='<p>vience</p>'></child> -->
<child>
<!-- 当传入的DOM结构为空时slot显示默认内容 -->
<!-- <p>vience</p> -->
<!-- 具名插槽(支持默认内容) -->
<div class="header" slot="header">header</div>
<div class="footer" slot="footer">footer</div>
</child>
</div>
<script>
Vue.component('child',{
props: { content: String },
// template: `<div>
// <p>hello</p>
// <div v-html='this.content'></div>
// </div>`,
// template: `<div>
// <p>hello</p>
// <slot>默认内容</slot>
// </div>`,
template: `<div>
<slot name='header'></slot>
<div>content</div>
<slot name='footer'></slot>
</div>`,
})
var vm = new Vue({ el: '#root', })
</script>
</body>
</html>
4.7 作用域插槽
使用场景:当子组件做循环或者某一部分显示的DOM由外部传入时使用作用域插槽
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>4.7节作用域插槽</title>
<script src="../vue.js"></script>
</head>
<body>
<div id="root">
<child>
<template slot-scope="props">
<!-- <li> {{props.item}} - hello </li> -->
<h1> {{props.item}} </h1>
</template>
</child>
</div>
<script>
Vue.component('child',{
data: function() {
return { list: [1, 2, 3, 4] }
},
template: `<div><ul> <slot v-for='item of list' :item=item></slot> </ul></div>`,
})
var vm = new Vue({ el: '#root' })
</script>
</body>
</html>
4.8 动态组件与v-once指令
1. 动态组件:<component :is='type'></component>
2. v-once:放在缓存中重复使用
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>4.8节动态组件与v-once指令</title>
<script src="../vue.js"></script>
</head>
<body>
<div id="root">
<child-one v-if="type=== 'child-one'"></child-one>
<child-two v-if="type=== 'child-two'"></child-two>
<!-- <component :is='type'></component> -->
<button @click="handleBtnClick">change</button>
</div>
<script>
Vue.component('child-one',{
template: `<div v-once>child-one</div>`,
})
Vue.component('child-two',{
template: `<div v-once>child-two</div>`,
})
var vm = new Vue({
el: '#root',
data: {
type: 'child-one'
},
methods: {
handleBtnClick: function() {
this.type = (this.type === 'child-one' ? 'child-two' : 'child-one')
}
}
})
</script>
</body>
</html>
第5章 Vue中的动画特效
5.1 Vue中的CSS动画原理
1. 过渡动画效果
通过某一时刻往标签上增加或者移除clss来实现动画效果
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>5.1节Vue中的CSS动画原理</title>
<script src="../vue.js"></script>
<style>
.v-enter, .v-leave-to { opacity: 0; }
.v-enter-active, .v-leave-active { transition: opacity 3s; }
</style>
</head>
<body>
<div id="root">
<!-- 通过某一时刻往标签上增加或者移除clss来实现动画效果 -->
<!-- 过渡动画效果 -->
<transition>
<!-- <div v-if='show'>hello world</div> -->
<div v-show='show'>hello world</div>
</transition>
<button @click="handleBtnClick">切换</button>
</div>
<script>
var vm = new Vue({
el: '#root',
data: { show: true },
methods: {
handleBtnClick: function() {
this.show = !this.show
}
}
})
</script>
</body>
</html>
5.2 Vue中使用animate.css库
1. 使用link引入animate.css文件
<link rel="stylesheet" href="../animate.css">
2. 给transition1标签增加enter-active-class和leave-active-class属性并对这两个属性赋值为animated和所需动画效果即可
<transition name='fade' enter-active-class='animated swing' leave-active-class='animated shake'>
<div v-show='show'>hello world</div>
</transition>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>5.1节Vue中使用animate.css库</title>
<script src="../vue.js"></script>
<link rel="stylesheet" href="../animate.css">
<!-- <style>
@keyframes bounce-in {
0% { transform: scale(0); }
50% { transform: scale(1.5); }
100% { transform: scale(1); }
}
.active { transform-origin: left center; animation: bounce-in 1s; }
.leave { transform-origin: left center; animation: bounce-in 1s reverse; }
</style> -->
</head>
<body>
<div id="root">
<!-- <transition name='fade' enter-active-class='active' leave-active-class='leave'>
<div v-show='show'>hello world</div>
</transition> -->
<transition name='fade' enter-active-class='animated swing' leave-active-class='animated shake'>
<div v-show='show'>hello world</div>
</transition>
<button @click="handleBtnClick">切换</button>
</div>
<script>
var vm = new Vue({
el: '#root',
data: { show: true },
methods: {
handleBtnClick: function() {
this.show = !this.show
}
}
})
</script>
</body>
</html>
5.3 在Vue中同时使用过渡和动画
1. 第一次显示时出现时显示动画
appear appear-active-class='animated swing'
2. 在Vue中同时使用过渡和动画
<style>
.fade-enter, .fade-leave-to { opacity: 0; }
.fade-enter-active, .fade-leave-active { transition: opacity 3s; }
</style>
<transition type='transition' name='fade' appear appear-active-class='animated swing' enter-active-class='animated swing fade-enter-active' leave-active-class='animated shake fade-leave-active'>
3. 在Vue中同时使用过渡和动画时动画时长设置
动画时长以transition为准(3s)
type='transition'
自定义动画时长
:duration='1000'
:duration='{enter:5000, leave:10000}'
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>5.1节在Vue中同时使用过渡和动画</title>
<script src="../vue.js"></script>
<link rel="stylesheet" href="../animate.css">
<style>
.fade-enter, .fade-leave-to { opacity: 0; }
.fade-enter-active, .fade-leave-active { transition: opacity 3s; }
</style>
</head>
<body>
<div id="root">
<!-- appear appear-active-class='animated swing' 第一次显示时出现动画 -->
<!-- type='transition' 动画时长以transition为准(3s) -->
<!-- :duration='1000' 自定义动画时长 :duration='{enter:5000, leave:10000}' -->
<transition type='transition' name='fade' appear appear-active-class='animated swing' enter-active-class='animated swing fade-enter-active' leave-active-class='animated shake fade-leave-active'>
<div v-show='show'>hello world</div>
</transition>
<button @click="handleBtnClick">切换</button>
</div>
<script>
var vm = new Vue({
el: '#root',
data: { show: true },
methods: {
handleBtnClick: function() {
this.show = !this.show
}
}
})
</script>
</body>
</html>
5.4 Vue中JS动画与Velocity.jsde结合
1. JS动画钩子
入场:before-enter,enter,after-enter 离场:before-leave,leave,after-leave
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>5.4节Vue中JS动画与Velocity.jsde结合</title>
<script src="../vue.js"></script>
<script src="../velocity.js"></script>
</head>
<body>
<div id="root">
<!-- 离场动画同理 -->
<transition name='fade' @before-enter='handleBeforeEnter' @enter='handleEnter' @after-enter='handleAfterEnter'>
<div v-show='show'>hello world</div>
</transition>
<button @click="handleBtnClick">切换</button>
</div>
<script>
var vm = new Vue({
el: '#root',
data: { show: true },
methods: {
handleBtnClick: function() {
this.show = !this.show
},
// handleBeforeEnter: function(el) { el.style.color = 'red' },
// handleEnter: function(el, done) {
// setTimeout(() => { el.style.color = 'green' }, 2000)
// setTimeout(() => { done() }, 4000)
// },
// handleAfterEnter: function(el) { el.style.color = '#000000' }
handleBeforeEnter: function(el) {
el.style.opacity = 0
},
handleEnter: function(el, done) {
Velocity(el, {opacity: 1}, {duration: 1000, complete: done})
},
handleAfterEnter: function(el) {
console.log('动画结束')
}
}
})
</script>
</body>
</html>
5.5 Vue中多个元素或组件间的过渡
1. 多个元素之间
mode='in-out':先进入后隐藏 mode='out-in':先隐藏后进入
2. 多个组件之间
<component :is='type'></component>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>5.5节Vue中多个元素或组件间的过渡</title>
<script src="../vue.js"></script>
<style>
.v-enter, .v-leave-to { opacity: 0; }
.v-enter-active, .v-leave-active { transition: opacity 1s; }
</style>
</head>
<body>
<div id="root">
<!-- mode='in-out':先进入后隐藏 mode='out-in':先隐藏后进入 -->
<!-- <transition mode='out-in'>
<div v-if='show' key='hello'>hello world</div>
<div v-else key='bye'>bye world</div>
</transition> -->
<!-- <transition mode='out-in'>
<child v-if='show'></child>
<child-one v-else></child-one>
</transition> -->
<transition mode='out-in'>
<component :is='type'></component>
</transition>
<button @click="handleBtnClick">切换</button>
</div>
<script>
Vue.component('child', {
template: '<div>child</div>'
})
Vue.component('child-one', {
template: '<div>child-one</div>'
})
var vm = new Vue({
el: '#root',
data: {
// show: true,
type: 'child'
},
methods: {
handleBtnClick: function() {
// this.show = !this.show
this.type = this.type === 'child' ? 'child-one' : 'child'
}
}
})
</script>
</body>
</html>
5.6 Vue中的列表过渡
对循环的div外部添加transition-group标签
<transition-group></transition-group>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>5.6节Vue中的列表过渡</title>
<script src="../vue.js"></script>
<style>
.v-enter, .v-leave-to { opacity: 0; }
.v-enter-active, .v-leave-active { transition: opacity 1s; }
</style>
</head>
<body>
<div id="root">
<transition-group>
<div v-for='item of list' :key='item.id'>{{ item.title }}</div>
</transition-group>
<button @click="handleBtnClick">Add</button>
</div>
<script>
var count = 0;
var vm = new Vue({
el: '#root',
data: { list: [] },
methods: {
handleBtnClick: function() {
this.list.push({ id: count++, title: 'hello world' })
}
}
})
</script>
</body>
</html>
5.7 Vue中的动画封装
1. 封装模板,写CSS样式
<style>
.v-enter, .v-leave-to { opacity: 0; }
.v-enter-active, .v-leave-active { transition: opacity 1s; }
</style>
2. 用JS动画封装在组件中(推荐使用方式)
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>5.7节Vue中的动画封装</title>
<script src="../vue.js"></script>
<!-- <style>
.v-enter, .v-leave-to { opacity: 0; }
.v-enter-active, .v-leave-active { transition: opacity 1s; }
</style> -->
</head>
<body>
<div id="root">
<fade :show='show'>
<div>hello world</div>
</fade>
<fade :show='show'>
<h1>hello world</h1>
</fade>
<button @click="handleBtnClick">toggle</button>
</div>
<script>
Vue.component('fade', {
props: ['show'],
template: `<transition @before-enter='handleBeforeEnter' @enter='handleEnter' @after-enter='handleAfterEnter'><slot v-if='show'></slot></transition>`,
methods: {
handleBeforeEnter: function(el) { el.style.color = 'red' },
handleEnter: function(el, done) {
setTimeout(() => { el.style.color = 'green' }, 2000)
setTimeout(() => { done() }, 4000)
},
handleAfterEnter: function(el) { el.style.color = '#000000' }
}
})
var vm = new Vue({
el: '#root',
data: { show: false },
methods: {
handleBtnClick: function() {
this.show = !this.show
}
}
})
</script>
</body>
</html>
第6章 Vue 项目预热
6.1 环境配置
1.配置vue开发环境
参考:www.jianshu.com/p/134149147…
2.在gitee上创建项目方便管理
2.1 在gitee上创建项目
2.2 安装git
2.3 git clone 线上代码并在线下创建vue项目,并上传至线上
6.2 项目代码介绍
6.3 单文件组件与Vue中的路由
<router-view/>
:显示的是当前路由地址所对应的内容
6.4 单页应用VS多页应用
1.多页应用(页面跳转--->返回HTML)
特点:首屏时间快,SEO效果好,页面切换慢
2.单页应用(页面跳转--->JS渲染)
特点:页面切换快,首屏时间稍慢,SEO效果差
6.4 项目代码初始化
1.修改index.html的mate标签
<meta name="viewport" content="width=device-width,initial-scale=1.0,minimum-scale=1.0,maximum-scale=1.0,user-scalable=no">
2.重置CSS样式
import '@/assets/styles/reset.css'
3.解决1像素边框问题
import '@/assets/styles/border.css'
4.解决300毫秒点击延迟问题
npm install fastclick --save
import FastClick from 'fastclick'
FastClick.attach(document.body)
开发实战
知识点1
1.git 切换新的分支开发并最后合并到主分支
①:在gitee上创建新的分支(index-nnn)
②:在项目下面的git Bash中执行git pull
③:继续执行git checkout 'index-nnn'
④:继续执行git status 查看所在分支
⑤:开发完成后执行git status 查看代码变更内容
⑥:执行git add . 把修改的代码提交到本地缓存中
⑦:执行git commit -m 'XXX' 填写备注XXX
⑧:执行git push 把修改的代码提交到线上的新建分支上
⑨:执行git checkout master 切换所在分支为主分支
⑩:执行git merge origin/index-nnn 查看新建分支与主分支内容差别
####十一:执行git push 把新建分支的内容提交到主分支上
常见问题FAQ
- 免费下载或者VIP会员专享资源能否直接商用?
- 本站所有资源版权均属于原作者所有,这里所提供资源均只能用于参考学习用,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担。更多说明请参考 VIP介绍。
- 提示下载完但解压或打开不了?
- 找不到素材资源介绍文章里的示例图片?
- 模板不会安装或需要功能定制以及二次开发?
发表评论
还没有评论,快来抢沙发吧!