一. es6语法
1. 认识let和const
1)let声明变量,let声明的变量属于局部作用域
<script type="text/javascript">
// let声明的变量是块级作用域,不能重复声明;而var声明的变量可以
{
let a = 10;
// let a = 20;
}
console.log(a);
</script>
<script type="text/javascript">
// 变量提升问题
// var的情况
console.log(foo); // 输出undefined
var foo = 2;
// let的情况
console.log(bar); // 报错ReferenceError
let bar = 2
</script>
2)const声明常量
<script type="text/javascript">
// const声明一个只读的常量。一旦声明,常量的值就不能改变
const a = 12;
console.log(a);
a = 3; // 会报错
console.log(a);
// const声明的变量不得改变值,即const一旦声明变量,就必须立即初始化,不能留到以后赋值
const b; // SyntaxError,会报错
</script>
2. 模板字符串
<script type="text/javascript">
// 模板字符串,用反引号`标识。它可以当作普通字符串使用,也可以用来定义多行字符串,或者在字符串中嵌入变量
var a = "Hello";
var b = "Tom";
var str = `
${a} World, this is ${b}
`;
console.log(str);
</script>
3. 箭头函数
<script type="text/javascript">
// 箭头函数,参数为多个时需要加括号并用逗号隔开
var f = a => a;
// 等同于
var f = function(a){
return a;
}
var f2 = (a, b) => a + b;
</script>
<script type="text/javascript">
var person1 = {
name: '项羽',
age: 30,
fav: function(){
// 是使用时定义的对象
console.log(this);
console.log(this.name);
}
};
person1.fav();
var person2 = {
name: '项羽',
age: 45,
fav:()=>{
// 如果使用了箭头函数,this指的是定义时所使用的对象,即指向了window
console.log(this);
console.log(this.name);
}
};
person2.fav();
</script>
4. 对象的单体模式
<script type="text/javascript">
// 单体模式
var person = {
name: '项羽',
age: 30,
fav(){
console.log(this);
}
};
person.fav();
</script>
5. 面向对象
<script type="text/javascript">
// 构造函数的方式创建对象
function Animal(name, age) {
this.name = name;
this.age = age;
}
Animal.prototype.showName = function(){
console.log(this.name);
};
Animal.prototype.showAge = function(){
console.log(this.age);
}
var cat = new Animal("Miao", 12);
cat.showName();
cat.showAge();
</script>
<script type="text/javascript">
class Animal{
constructor(name, age){
this.name = name;
this.age = age;
}
showName(){
console.log(this.name);
}
}
var dog = new Animal('Wang', '10');
dog.showName();
</script>
二. nodejs服务器语言
npm init --yes 初始化我们的项目,自动生成一个package.json文件
npm install jquery --save
npm install webpack --save-dev
npm run dev 运行环境
npm run build 编译代码
npm install -g cnpm -registry=https://registry.npm.taobao.org 下载使用cnpm提高速度
三. Vue基础
1. {{}}:模板语法插值
{{变量}}
{{1 + 1}}
{{'hello'}}
{{函数的调用}}, 例如:{{ 'hello world'.split("").reverse().join()}}
{{1 == 1 ? '真的' : '假的'}}
2. 创建简单的Vue对象
<body>
<div id="app">
<h3>{{title}}</h3>
</div>
<script>
// 1. 创建vue实例化对象
// 参数
var app = new Vue({
el:"#app",
// 所有的数据都放在数据属性中
data:{
title: "VUE"
}
})
</script>
</body>
3. 指令系统
在vue中提供了一套为(数据驱动视图)更为方便的操作,这些操作被称为指令系统,以v-xxx所表示。
指令中封装了一些DOM行为,结合属性作为一个暗号,暗号有相应的值,根据不同的值,框架会进行相应的DOM操作的绑定。
1) v-text和v-html
v-text等价于{{}} 实现原理:innerText
v-html实现原理:innterHTML
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
</head>
<body>
<!-- 1. 先引包-->
<script type="text/javascript" src="./node_modules/vue/dist/vue.js"></script>
<div id='app'>
</div>
<script type="text/javascript">
// 2. 创建vue
new Vue({
el: '#app',
data: {
msg: 'hello Vue',
msg2: '数据',
msg3: '<a href="#">这是html的数据</a>'
},
template: `
<div>
<h3>{{ msg }}</h3>
<h2 v-text='msg2'></h2>
<p v-html='msg3'></p>
</div>
`
})
</script>
</body>
</html>
2)条件渲染
(1)v-if,表示条件渲染
v-else-if
v-else
v-if是“真正”的条件渲染,因为它会确保在切换过程中条件块内的事件监听器和子组件适当地被销毁和重建
v-if也是惰性的:如果在初始渲染时条件为假,则什么也不做-----直到条件第一次变为真时,才会开始渲染条件快。
相比之下,v-show就简单的多---不管初始条件是什么,元素总是会被渲染,并且只是简单地基于CSS进行切换。
一般来说,v-if有更高的切换开销,而v-show有更高的初始渲染开销。因此,如果需要非常频繁地切换,则使用v-show较好;如果在运行时条件很少改变,则使用v-if较好。
<body>
<div id="app">
<!--插值语法-->
<h3>{{msg}}</h3>
<div>{{1>2?"TRUE":"FALSE"}}</div>
<div v-if = 'show'>if条件显示True</div>
<div v-else>if条件显示False</div>
</div>
<script>
var app = new Vue({
el:"#app",
data:{
msg: "今天学习vue",
show: false
}
})
</script>
</body>
<div v-if="type === 'a' ">
Adam
</div>
<div v-if="type === 'b' ">
Bruce
</div>
<div v-if="type === 'c' ">
Chris
</div>
v-else元素必须紧跟在v-if或v-else-if元素后面,否则将不会被识别
(2)v-on,事件
<body>
<div id="app">
<!--插值语法-->
<h3>{{msg}}</h3>
<div>{{1>2?"TRUE":"FALSE"}}</div>
<div v-if = 'show'>if条件显示</div>
<button v-on:click="clickHandler">切换</button>
</div>
<script>
var app = new Vue({
el:"#app",
data:{
msg: "今天学习vue",
show: false
},
methods:{
clickHandler: function(){
this.show = !this.show;
}
}
})
</script>
</body>
(3)v-show,显示内容
v-show的元素始终会被渲染并保留在DOM中。v-show只是简单地切换元素的CSS属性display
<body>
<div id="app">
<!--插值语法-->
<h3>{{msg}}</h3>
<div>{{1>2?"TRUE":"FALSE"}}</div>
<div v-if = 'show'>if条件显示</div>
<button v-on:click="clickHandler">切换</button>
<div v-show="isShow">演示v-show</div>
</div>
<script>
var app = new Vue({
el:"#app",
data:{
msg: "今天学习vue",
show: false,
isShow: true,
},
methods:{
clickHandler: function(){
this.show = !this.show;
}
}
})
</script>
</body>
3)class与style绑定
使用v-bind: class = '{} || [] || 变量名 || 常量' 对我们的页面中标签的属性进行绑定。所有的属性都可以进行绑定,注意只要使用了v-bind后面的字符串一定是数据属性中的值
a. 绑定字符串
<body>
<div id="app">
<!--插值语法-->
<h3>{{msg}}</h3>
<div>{{1>2?"TRUE":"FALSE"}}</div>
<div v-if = 'show'>if条件显示</div>
<button v-on:click="clickHandler">切换</button>
<div v-show="isShow">演示v-show</div>
<div v-show="isShow" v-bind:title="title">演示绑定</div>
</div>
<script>
var app = new Vue({
el:"#app",
data:{
msg: "今天学习vue",
show: false,
isShow: true,
title: "鼠标悬停的提示",
},
methods:{
clickHandler: function(){
this.show = !this.show;
}
}
})
</script>
</body>
b. 绑定图片
<body>
<div id="app">
<!--插值语法-->
<h3>{{msg}}</h3>
<div>{{1>2?"TRUE":"FALSE"}}</div>
<div v-if = 'show'>if条件显示</div>
<button v-on:click="clickHandler">切换</button>
<div v-show="isShow">演示v-show</div>
<div v-show="isShow" v-bind:title="title">演示绑定</div>
<img v-bind:src="imgSrc">
</div>
<script>
var app = new Vue({
el:"#app",
data:{
msg: "今天学习vue",
show: false,
isShow: true,
title: "鼠标悬停的提示",
imgSrc: "./1.jpg"
},
methods:{
clickHandler: function(){
this.show = !this.show;
}
}
})
</script>
</body>
c. 绑定时间
<body>
<div id="app">
<!--插值语法-->
<h3>{{msg}}</h3>
<div>{{1>2?"TRUE":"FALSE"}}</div>
<div v-if = 'show'>if条件显示</div>
<button v-on:click="clickHandler">切换</button>
<div v-show="isShow">演示v-show</div>
<div v-show="isShow" v-bind:title="title">演示绑定</div>
<img v-bind:src="imgSrc">
<div v-bind:title="time">显示时间</div>
</div>
<script>
var app = new Vue({
el:"#app",
data:{
msg: "今天学习vue",
show: false,
isShow: true,
title: "鼠标悬停的提示",
imgSrc: "./1.jpg",
time: `页面加载于${new Date().toLocaleString()}`,
},
methods:{
clickHandler: function(){
this.show = !this.show;
}
}
})
</script>
</body>
d. 绑定类
<body>
<div id="app">
<!--插值语法-->
<h3>{{msg}}</h3>
<div>{{1>2?"TRUE":"FALSE"}}</div>
<div v-if = 'show'>if条件显示</div>
<button v-on:click="clickHandler">切换</button>
<div v-show="isShow">演示v-show</div>
<div v-show="isShow" v-bind:title="title">演示绑定</div>
<img v-bind:src="imgSrc">
<div v-bind:title="time">显示时间</div>
<div class="box" v-bind:class='{box2:isGreen}'></div>
<button @click="changeColor">切换颜色</button>
</div>
<script>
var app = new Vue({
el:"#app",
data:{
msg: "今天学习vue",
show: false,
isShow: true,
title: "鼠标悬停的提示",
imgSrc: "./1.jpg",
time: `页面加载于${new Date().toLocaleString()}`,
isGreen: true,
},
methods:{
clickHandler: function(){
this.show = !this.show;
},
changeColor: function(){
this.isGreen = !this.isGreen;
}
}
})
</script>
</body>
我们可以吧一个数组穿个v-bind:class,以应用一个class列表:
<div v-bind:class="{activeClass, errorClass}"></div>
data: {
activeClass: "active",
errorClass: "text-align",
}
3)事件处理
(1)监听事件
可以用v-on监听DOM事件,并在触发时运行有一个JavaScript代码
vue中使用v-on:click对当前DOM绑定click事件 注意:所有的原生js的事件使用v-on都可以绑定
<body>
<div id="app">
<!--插值语法-->
<h3>{{msg}}</h3>
<div>{{1>2?"TRUE":"FALSE"}}</div>
<div v-if = 'show'>if条件显示</div>
<button v-on:click="clickHandler">切换</button>
<div v-show="isShow">演示v-show</div>
<div v-show="isShow" v-bind:title="title">演示绑定</div>
<img v-bind:src="imgSrc">
<div v-bind:title="time">显示时间</div>
<div class="box" v-bind:class='{box2:isGreen}'></div>
<button @click="changeColor">切换颜色</button>
<button v-on:click="count+=1">加{{count}}</button>
</div>
<script>
var app = new Vue({
el:"#app",
data:{
msg: "今天学习vue",
show: false,
isShow: true,
title: "鼠标悬停的提示",
imgSrc: "./1.jpg",
time: `页面加载于${new Date().toLocaleString()}`,
isGreen: true,
count: 0,
},
methods:{
clickHandler: function(){
this.show = !this.show;
},
changeColor: function(){
this.isGreen = !this.isGreen;
}
}
})
</script>
</body>
v-on与v-if的结合:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
<style type='text/css'>
.box{
width: 200px;
height: 200px;
background-color: red;
}
</style>
</head>
<body>
<!-- 1. 先引包-->
<script type="text/javascript" src="./node_modules/vue/dist/vue.js"></script>
<div id='app'>
<button v-on:click='showHandler()'>{{ btnText }}</button>
<div class="box" v-if="isShow"></div>
</div>
<script type="text/javascript">
// 2. 创建vue
new Vue({
el: '#app',
// data在Vue实例化中可以是一个对象,也可以是一个函数,但是在组件中,data必须是一个函数,函数内容一定return一个独享
data: function(){
return {
isShow: true,
btnText: '显示/隐藏',
}
},
methods: {
showHandler(){
// if(this.isShow){
// this.isShow = false;
// }else{
// this.isShow = true;
// }
this.isShow = !this.isShow
}
}
})
</script>
</body>
</html>
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
<style type='text/css'>
.box{
width: 200px;
height: 200px;
background-color: red;
}
.isGreen{
width: 500px;
height: 500px;
background-color: green;
}
.active{
background-color: yellow;
}
</style>
</head>
<body>
<!-- 1. 先引包-->
<script type="text/javascript" src="./node_modules/vue/dist/vue.js"></script>
<div id='app'>
<button v-on:click='showHandler()'>{{ btnText }}</button>
<div class="box" v-if="isShow"></div>
<div class='isGreen' v-bind:class='{active:isYellow}'></div>
<button v-on:click='changeColor()'>切换颜色</button>
</div>
<script type="text/javascript">
// 2. 创建vue
new Vue({
el: '#app',
// data在Vue实例化中可以是一个对象,也可以是一个函数,但是在组件中,data必须是一个函数,函数内容一定return一个独享
data: function(){
return {
isShow: true,
btnText: '显示/隐藏',
isYellow: false
}
},
methods: {
showHandler(){
// if(this.isShow){
// this.isShow = false;
// }else{
// this.isShow = true;
// }
this.isShow = !this.isShow
},
changeColor(){
this.isYellow = !this.isYellow
}
}
})
</script>
</body>
</html>
轮播图实现:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
<style type='text/css'>
ul{
list-style: none;
overflow: hidden;
width: 400px;
}
ul li{
float: left;
width: 100px;
height: 40px;
line-height: 40px;
background-color: purple;
color: #fff;
text-align: center;
}
ul li .active{
background-color: green;
}
</style>
</head>
<body>
<!-- 1. 先引包-->
<script type="text/javascript" src="./node_modules/vue/dist/vue.js"></script>
<div id='slider'>
<img :src='currentImgSrc' alt=''>
<ul>
<li v-for='(item, index) in imgArr' :class="{active:currentIndex==index}" @click='clickHandler(index)'>
{{ index + 1}}
</li>
</ul>
</div>
<script type="text/javascript">
var imgArr = [
{id: 1, imgSrc: './imgs/1.jpg'},
{id: 2, imgSrc: './imgs/2.jpg'},
{id: 3, imgSrc: './imgs/3.jpg'},
{id: 4, imgSrc: './imgs/4.jpg'},
]
new Vue({
el: '#slider',
template: ``,
data: function(){
return {
imgArr: imgArr,
currentIndex: 0,
currentImgSrc: './imgs/1.jpg',
}
},
methods: {
clickHandler(index){
this.currentIndex = index;
this.currentImgSrc = this.imgArr[index].imgSrc;
}
}
})
</script>
</body>
</html>
v-on的几个好处:
1. HTML模板能轻松定位在JavaScript代码里对应的方法
2. 无需在JavaScript里手动绑定事件,ViewModel代码可以是非常纯粹的逻辑,和DOM完全解耦,更易于测试
3. 当一个ViewModel被销毁时,所有的事件处理器都会自动被删除。
在Vue中的简写:
- v-bind: :class :src :id === v-bind:class v-bind:src v-bind:id
- v-on:click === @click
4)列表渲染
一个数组列表的v-for,用v-for把一个数组对应为一组的元素。
v-for
我么用v-for指令根据一组数组的选项列表进行渲染,v-for指令需要使用item in items形式的特殊语法,items是元数据数组并且item是数组元素迭代的别名。
另外:v-for还支持一个可选的第二参数为当前项的索引
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
</head>
<body>
<!-- 1. 先引包-->
<script type="text/javascript" src="./node_modules/vue/dist/vue.js"></script>
<div id='app'>
<ul>
<li v-for='(item, index) in menu'>
<h3>{{index}}: {{item.name}}, ¥{{item.price}}</h3>
</li>
</ul>
</div>
<script type="text/javascript">
// 2. 创建vue
new Vue({
el: '#app',
data: {
msg: 'hello Vue',
msg2: '数据',
msg3: '<a href="#">这是html的数据</a>',
menu: [
{'name': '蒸羊羔', 'price': 60},
{'name': '蒸熊掌', 'price': 300},
{'name': '烧花鸭', 'price': 45},
{'name': '烧子鹅', 'price': 70},
]
},
})
</script>
</body>
</html>
<body>
<div id="app">
<div class="lunbo">
<img :src="currentSrc" @mouseenter="closeTimer" @mouseleave="startTimer">
<ul>
<li v-for = "(item, index) in imgArr" @click="imgHandler(item)">{{index+1}}</li>
</ul>
<button @click="imgPrev">上一张</button>
<button @click="imgNext">下一张</button>
</div>
</div>
<script>
var app = new Vue({
el:"#app",
data:{
msg: "今天学习vue",
show: false,
isShow: true,
title: "鼠标悬停的提示",
imgSrc: "./1.jpg",
time: `页面加载于${new Date().toLocaleString()}`,
isGreen: true,
count: 0,
imgArr: [
{id:1, src:"./images/1.jpg"},
{id:2, src:"./images/2.jpg"},
{id:3, src:"./images/3.jpg"},
{id:4, src:"./images/4.jpg"},
],
currentSrc: "./images/1.jpg",
currentIndex: 0,
timer: null,
},
created(){
this.timer = setInterval(this.imgNext, 2000)
},
methods:{
clickHandler: function(){
this.show = !this.show;
},
changeColor: function(){
this.isGreen = !this.isGreen;
},
imgHandler(item){
this.currentSrc = item.src;
},
imgNext(){
if (this.currentIndex == this.imgArr.length - 1){
this.currentIndex = -1;
}
this.currentIndex++;
this.currentSrc = this.imgArr[this.currentIndex].src;
},
imgPrev(){
if (this.currentIndex == 0){
this.currentIndex = this.imgArr.length;
}
this.currentIndex--;
this.currentSrc = this.imgArr[this.currentIndex].src;
},
closeTimer(){
clearInterval(this.timer);
},
startTimer(){
this.timer = setInterval(this.imgNext, 2000);
}
}
})
</script>
</body>
5)v-html解析标签
<body>
<div id="app">
<div class="lunbo">
<img :src="currentSrc" @mouseenter="closeTimer" @mouseleave="startTimer">
<ul>
<li v-for = "(item, index) in imgArr" @click="imgHandler(item)">{{index+1}}</li>
</ul>
<button @click="imgPrev">上一张</button>
<button @click="imgNext">下一张</button>
</div>
</div>
<div v-html="str">
</div>
<script>
var app = new Vue({
el:"#app",
data:{
msg: "今天学习vue",
show: false,
isShow: true,
title: "鼠标悬停的提示",
imgSrc: "./1.jpg",
time: `页面加载于${new Date().toLocaleString()}`,
isGreen: true,
count: 0,
imgArr: [
{id:1, src:"./images/1.jpg"},
{id:2, src:"./images/2.jpg"},
{id:3, src:"./images/3.jpg"},
{id:4, src:"./images/4.jpg"},
],
currentSrc: "./images/1.jpg",
currentIndex: 0,
timer: null,
str: "<p>嘿嘿嘿</p>",
},
created(){
this.timer = setInterval(this.imgNext, 2000)
},
methods:{
clickHandler: function(){
this.show = !this.show;
},
changeColor: function(){
this.isGreen = !this.isGreen;
},
imgHandler(item){
this.currentSrc = item.src;
},
imgNext(){
if (this.currentIndex == this.imgArr.length - 1){
this.currentIndex = -1;
}
this.currentIndex++;
this.currentSrc = this.imgArr[this.currentIndex].src;
},
imgPrev(){
if (this.currentIndex == 0){
this.currentIndex = this.imgArr.length;
}
this.currentIndex--;
this.currentSrc = this.imgArr[this.currentIndex].src;
},
closeTimer(){
clearInterval(this.timer);
},
startTimer(){
this.timer = setInterval(this.imgNext, 2000);
}
}
})
</script>
</body>
4. 组件
这里有两种组件的注册类型:全局注册和局部注册。
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
<style type='text/css'>
</style>
</head>
<body>
<script type="text/javascript" src="./node_modules/vue/dist/vue.js"></script>
<div id='app'>
</div>
<script type="text/javascript">
// 1. 声明入口组件
// 声明头部组件
Vheader = {
template: `
<div class='head'>我是Header</div>
`
}
// 局部组件
var Vmain = {
template: `
<div class='main'>
我是Main
<Vheader/>
</div>
`,
components:{
// 等价于Vheader:Vheader 2.挂在子组件
Vheader
}
}
new Vue({
el: '#app',
// 3. 使用子组件
template: `<Vmain></Vmain>`,
data: {
},
components:{
// 2. 挂载子组件
Vmain: Vmain
}
})
</script>
</body>
</html>
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
<style type='text/css'>
*{
padding:0;
margin: 0;
}
body{
color: white;
}
.head{
width: 100%;
height: 70px;
background-color: purple;
text-align: center;
line-height: 70px;
color: #fff;
font-size: 20px;
}
.main{
width: 100%;
}
.wrapper{
width: 100%;
height: 1200px;
}
.wrapper .side{
width: 30%;
height: 1200px;
background-color: green;
float: left;
}
.wrapper .content{
width: 70%;
height: 1200px;
background-color: black;
float: left;
}
</style>
</head>
<body>
<script type="text/javascript" src="./node_modules/vue/dist/vue.js"></script>
<div id='app'>
</div>
<script type="text/javascript">
// 1. 声明入口组件
// 声明头部组件
var Vheader = {
template: `
<div class='head'>我是Header</div>
`
}
var Vside = {
template: `
<div class='side'>我是侧边栏</div>
`
}
var Vcontent = {
template: `
<div class='content'>我是内容区域</div>
`
}
// 局部组件
var Vmain = {
template: `
<div class='main'>
<Vheader/>
<div class='wrapper'>
<Vside/>
<Vcontent/>
</div>
</div>
`,
components:{
// 等价于Vheader:Vheader 2.挂在子组件
Vheader,
Vside,
Vcontent
}
}
new Vue({
el: '#app',
// 3. 使用子组件
template: `<Vmain></Vmain>`,
data: {
},
components:{
// 2. 挂载子组件
Vmain: Vmain
}
})
</script>
</body>
</html>
1)通过Prop向子组件传递数据
prop是可以在组件上注册的一些自定义特性。
(1)在子组件自定义特性
当一个值传递给一个prop特性的时候,它就变成了那个组件实例的一个属性,那么我们就可以像访问data中的值一样
(2)要在父组件中导入的子组件内部绑定自定义的属性<Vheader :title='父组件中data声明的数据属性'>
注意:一个组件默认可以拥有任意数量的prop,任何值都可以传递给任何prop。
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
<style type='text/css'>
*{
padding:0;
margin: 0;
}
body{
color: white;
}
.head{
width: 100%;
height: 70px;
background-color: purple;
text-align: center;
line-height: 70px;
color: #fff;
font-size: 20px;
}
.main{
width: 100%;
}
.wrapper{
width: 100%;
height: 1200px;
}
.wrapper .side{
width: 30%;
height: 1200px;
background-color: green;
float: left;
}
.wrapper .content{
width: 70%;
height: 1200px;
background-color: black;
float: left;
}
</style>
</head>
<body>
<script type="text/javascript" src="./node_modules/vue/dist/vue.js"></script>
<div id='app'>
</div>
<script type="text/javascript">
// 1. 声明入口组件
// 声明头部组件
var Vheader = {
template: `
<div class='head'>{{title}}</div>
`,
props: ['title']
}
var Vside = {
template: `
<div class='side'>我是侧边栏</div>
`
}
var Vcontent = {
template: `
<div class='content'>我是内容区域</div>
`
}
// 局部组件
var Vmain = {
template: `
<div class='main'>
<Vheader :title='title'></Vheader>
<div class='wrapper'>
<Vside/>
<Vcontent/>
</div>
</div>
`,
components:{
// 等价于Vheader:Vheader 2.挂在子组件
Vheader,
Vside,
Vcontent
},
props: ['title']
}
new Vue({
el: '#app',
// 3. 使用子组件
template: `<Vmain :title="text" :posts='posts'></Vmain>`,
data: {
text: "我是一个标题",
posts: [
{id:1, title:'组件中的传值', content: '通过prop传递数据1'},
{id:2, title:'组件中的传值', content: '通过prop传递数据2'},
{id:3, title:'组件中的传值', content: '通过prop传递数据3'},
]
},
components:{
// 2. 挂载子组件
Vmain: Vmain
}
})
</script>
</body>
</html>
2)通过事件向子组件传递数据
我们可以调用内建的$emit方法并传入事件的名字,来向父级组件触发一个事件
(1)给子组件中的某个按钮绑定原生事件,我们可以调用内建的this.$emit('自定义的事件名', '传递的数据'),来向父级组件触发一个自定义事件
(2)在父组件中的子组件标签中,要绑定自定义的事件
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
<style type='text/css'>
*{
padding:0;
margin: 0;
}
body{
color: white;
}
.head{
width: 100%;
height: 70px;
background-color: purple;
text-align: center;
line-height: 70px;
color: #fff;
font-size: 20px;
}
.main{
width: 100%;
}
.wrapper{
width: 100%;
height: 1200px;
}
.wrapper .side{
width: 30%;
height: 1200px;
background-color: green;
float: left;
}
.wrapper .content{
width: 70%;
height: 1200px;
background-color: black;
float: left;
}
</style>
</head>
<body>
<script type="text/javascript" src="./node_modules/vue/dist/vue.js"></script>
<div id='app'>
</div>
<script type="text/javascript">
// 1. 声明入口组件
// 声明头部组件
var Vheader = {
template: `
<div class='head'>{{title}}</div>
`,
props: ['title']
}
var Vside = {
template: `
<div class='side'>我是侧边栏</div>
`
}
var Vcontent = {
template: `
<div class='content'>
我是内容区域
<button @click='changeSize()'>改变字体大小</button>
</div>
`,
methods: {
changeSize(){
// 通过$emit()方法来触发自定义的事件
// 第一个参数是自定义的事件名字,第二个参数就是传递的值
this.$emit('postChangeSize',3)
}
}
}
// 局部组件
var Vmain = {
template: `
<div class='main' :style='{fontSize: fontsize + "px"}'>
<Vheader :title='title'></Vheader>
<div class='wrapper'>
<Vside/>
<Vcontent @postChangeSize='clickHandler'/>
</div>
</div>
`,
data(){
return{
fontsize: 18,
}
},
methods: {
clickHandler(value){
this.fontsize = this.fontsize += value
}
},
components:{
// 等价于Vheader:Vheader 2.挂在子组件
Vheader,
Vside,
Vcontent
},
props: ['title']
}
new Vue({
el: '#app',
// 3. 使用子组件
template: `<Vmain :title="text" :posts='posts'></Vmain>`,
data: {
text: "我是一个标题",
posts: [
{id:1, title:'组件中的传值', content: '通过prop传递数据1'},
{id:2, title:'组件中的传值', content: '通过prop传递数据2'},
{id:3, title:'组件中的传值', content: '通过prop传递数据3'},
]
},
components:{
// 2. 挂载子组件
Vmain: Vmain
}
})
</script>
</body>
</html>
3)公共组件
全局组件的使用:
Vue.component('全局组件的名字', {
跟new Vue()实例化对象中的options是一样,但要注意:
不管是公共组件还是局部组件,data必须是个函数,函数一定要有返回值
})
<slot>元素作为承载分发内容的出口
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
<style type='text/css'>
*{
padding:0;
margin:0;
}
#head{
width: 100%;
height: 80px;
background-color: purple;
}
.primary{
color: #fff;
background-color: #409eff;
border-color: #409eff;
}
.success{
color: #fff;
background-color: #67c23a;
border-color: #67c23a;
}
</style>
</head>
<body>
<script type="text/javascript" src="./node_modules/vue/dist/vue.js"></script>
<div id='app'>
</div>
<script type="text/javascript">
// 创建公共组件
// 第一个参数是公共组件的名字,第二个参数options
Vue.component('Vbtn', {
template:`<button class='default' :class='type'>
<slot></slot>
</button>`,
props:['type']
})
var Vheader = {
template:`<div id='head'>
<Vbtn>登录</Vbtn>
<Vbtn>注册</Vbtn>
<Vbtn>提交</Vbtn>
<Vbtn>默认的按钮</Vbtn>
<Vbtn type='primary'>主要的按钮</Vbtn>
<Vbtn type='success'>成功的按钮</Vbtn>
</div>`
}
var App = {
template:`<div>
<Vheader></Vheader>
</div>`,
components:{
Vheader
}
}
new Vue({
el: '#app',
data(){
return{
}
},
template: `<App/>`,
components:{
App
}
})
</script>
</body>
</html>
5. v-model
表单输入绑定
单向绑定:把Model绑定到View上,当我们用JavaScript代码更新Model时,View就会自动更新
双向绑定:如果用户更新了View,Model的数据也自动被更新了,这种情况就是双向绑定。
v-model指令在表单<input>及<textarea>元素上创建双向数据绑定。它会根据控件类型自动选取正确的方法来更新元素。v-model只适用于表单控件中。
<body>
<form id="computed">
<input type="text" v-model="msg">
<input type="text" v-model.lazy="msg"> <!--懒加载-->
<input type="number" v-model.number="msg">
<input type="number" v-model.trim="msg">
<h3>{{msg}}</h3>
</form>
<script>
var app = new Vue({
el:"#computed",
data:{
msg: "Hello World!",
},
})
</script>
</body>
6.过滤器
可以自定义过滤器,用于一些常见的文本格式化。过滤器可以用在两个地方:双花括号插值和v-bind表达式。过滤器应该被添加在JavaScript表达式的尾部,由“管道”符号指示:
{{ message | capitalize}}
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
<style type='text/css'>
*{
padding:0;
margin:0;
}
</style>
</head>
<body>
<script type="text/javascript" src="./node_modules/vue/dist/vue.js"></script>
<div id='app'>
<input type='text' v-model='price'>
<h3>{{ price | currentPrice }}</h3>
<h4>{{ msg | reverse }}</h4>
</div>
<script type="text/javascript">
// 注册全局过滤器
Vue.filter('reverse', function(value){
return value.split(' ').reverse().join(' ');
})
new Vue({
el: '#app',
data(){
return{
price: 0,
msg: 'hello world'
}
},
// 局部过滤器,当前组件中声明过滤器
// 注册局部过滤器
filters:{
currentPrice: function(value){
return "$" + value
}
}
})
</script>
</body>
</html>
7. 侦听属性之watch
Vue停工了一种通用的方式来观察和响应Vue实例上的数据变动:侦听属性
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
<style type='text/css'>
*{
padding:0;
margin:0;
}
</style>
</head>
<body>
<script type="text/javascript" src="./node_modules/vue/dist/vue.js"></script>
<div id='app'>
<input type='text' v-model='myName'>
<h3>{{myName}}</h3>
<button @click='clickHandler'>修改</button>
</div>
<script type="text/javascript">
// 注册全局过滤器
Vue.filter('reverse', function(value){
return value.split(' ').reverse().join(' ');
})
new Vue({
el: '#app',
template: ``,
data(){
return{
myName: 'Dante',
}
},
methods:{
clickHandler(){
this.myName = 'Nero',
}
},
watch: {
// 检测单个属性 命令式
myName: function(value){
if(value==='Dante'){
console.log("Rock and Roll")
}
}
}
})
</script>
</body>
</html>
8. 计算属性
计算属性默认值只有getter方法
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
<style type='text/css'>
*{
padding:0;
margin:0;
}
</style>
</head>
<body>
<script type="text/javascript" src="./node_modules/vue/dist/vue.js"></script>
<div id='app'>
<input type='text' v-model='desc'>
<h3>{{ desc }}</h3>
<button @click='clickHandler'>修改</button>
</div>
<script type="text/javascript">
new Vue({
el: '#app',
data(){
return{
name: 'Dante',
}
},
methods:{
clickHandler(){
this.desc = 'Nero';
}
},
computed:{
desc: {
set: function(newValue){
this.name = newValue;
},
get: function(){
var str = this.name;
return str;
}
}
}
})
</script>
</body>
</html>
音乐播放器的实现:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
<style type='text/css'>
*{
padding:0;
margin:0;
}
ul{
list-style: none;
}
ul li{
margin: 30px 20px;
padding: 10px;
}
.active{
background-color: gray;
}
</style>
</head>
<body>
<script type="text/javascript" src="./node_modules/vue/dist/vue.js"></script>
<div id='music'>
<audio :src="currentSrc" controls='' autoplay=""></audio>
<ul>
<li v-for='(song, index) in songs' @click='clickHandler(index)' :class='{active:currentIndex==index}'>
<h2>{{ song.id }} -- 歌名:{{ song.name}}</h2>
<p>歌手:{{ song.author }}</p>
</li>
</ul>
</div>
<script type="text/javascript">
var musicData = [
{
id: 1,
name: '于荣光-少林英雄',
author: '于荣光',
songSrc: './static/于荣光 - 少林英雄.mp3'
},
{
id: 2,
name: 'Joel Adams - Please Dont Go',
author: 'Joel Adams',
songSrc: './static/Joel Adams - Please Dont Go.mp3'
},
{
id: 3,
name: 'MKJ - Time',
author: 'MKJ',
songSrc: './static/MKJ - Time.mp3'
},
{
id: 4,
name: 'Russ - Psycho(Pt. 2)',
author: 'Russ',
songSrc: './static/Russ - Psycho (Pt. 2).mp3'
},
]
new Vue({
el: '#music',
data(){
return{
songs: musicData,
currentIndex: 0,
}
},
template: ``,
methods:{
clickHandler(index){
this.currentIndex = index;
}
},
computed:{
currentSrc(){
return this.songs[this.currentIndex].songSrc;
}
},
})
</script>
</body>
</html>
9. 选项/生命周期钩子
所有的生命周期钩子自动绑定this上下文到实例中,因此可以访问数据,对属性和方法进行运算。这意味着不能使用箭头函数来定义一个生命周期方法。这是因为箭头函数绑定了父上下文,因此this与期待的Vue实例不同,this.fetchTodos的行为未定义。
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
<style type='text/css'>
*{
padding:0;
margin:0;
}
</style>
</head>
<body>
<script type="text/javascript" src="./node_modules/vue/dist/vue.js"></script>
<div id='app'>
<App></App>
</div>
<script type="text/javascript">
var Test = {
data(){
return{
msg: '哈哈哈'
}
},
template: `
<div>
{{ msg }}
<button @click='changeHandler'></button>
</div>
`,
methods:{
changeHandler(){
this.msg = this.msg + " Rock"
}
},
beforeCreate(){
// 组件创建之前,一般不做任何操作
console.log(this.msg);
},
created(){
// 组件创建之后
// 使用该组件,就会触发以上的钩子函数,created中可以操作数据,发送ajax,并且可以实现vue==》页面的影响
console.log(this.msg);
this.msg = '嘿嘿嘿';
},
beforeMount(){
// 装载数据到DOM之前会调用
console.log(document.getElementById('app'));
},
mounted(){
// 这个地方可以操作DOM
// 装载数据到DOM之后会调用 可以获取到真实存在的DOM元素,vue操作以后的DOM
console.log(document.getElementById('app'));
},
beforeUpdate(){
// 在更新之前,调用此钩子,应用:获取原始的DOM
console.log(document.getElementById('app').innerHTML);
},
updated(){
// 在更新之前,调用此钩子,应用:获取最新的DOM
console.log(document.getElementById('app').innerHTML);
},
activated(){
console.log('组件被激活了');
},
deactivated(){
console.log('组件被停用了');
},
// 性能消耗太大
beforeDestroy(){
console.log('beforeDestroy')
},
destroyed(){
console.log('destroyed')
}
}
var App = {
data(){
return {
isShow: true,
}
},
template:`
<div>
<keep-alive>
<Test v-if='isShow'></Test>
</keep-alive>
<button @click='changeHandler'>改变组件的生死</button>
</div>
`,
methods:{
changeHandler(){
this.isShow = !this.isShow;
}
},
components:{
Test
}
}
new Vue({
el: '#app',
data(){
return{
}
},
template: ``,
components:{
App
}
})
</script>
</body>
</html>
10. $ref获取DOM元素
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
<style type='text/css'>
*{
padding:0;
margin:0;
}
</style>
</head>
<body>
<script type="text/javascript" src="./node_modules/vue/dist/vue.js"></script>
<div id='app'>
</div>
<script type="text/javascript">
var App = {
data(){
return {
}
},
template:`
<div>
<button ref='btn'>我是按钮</button>
<p ref='tt'>TT</p>
</div>
`,
beforeCreate(){
},
created(){
},
beforeMount(){
},
mounted(){
var op = this.$refs.tt
this.$refs.btn.onclick = function(){
alert(op.innerHTML);
}
},
methods:{
changeHandler(){
this.isShow = !this.isShow;
}
},
}
new Vue({
el: '#app',
data(){
return{
}
},
template: `<App/>`,
components:{
App
}
})
</script>
</body>
</html>
11. 使用$nextTick的特殊情况
获取更新之后的dom添加事件
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
<style type='text/css'>
*{
padding:0;
margin:0;
}
</style>
</head>
<body>
<script type="text/javascript" src="./node_modules/vue/dist/vue.js"></script>
<div id='app'>
</div>
<script type="text/javascript">
var App = {
data(){
return{
isShow: false,
}
},
template:`
<div>
<input type='text' v-if='isShow' ref='fos'>
</div>
`,
mounted(){
// vue实现响应式并不是数据发生变化之后DOM立刻发生变化,而是按一定的策略进行DOM的更新
// $nextTick是在下次Dom更新循环结束之后执行的延迟回调,在修改数据之后使用$nextTick,则可以在回调中获取更新后的DOM
this.isShow = true;
this.$nextTick(function(){
this.$refs.fos.focus()
})
},
}
new Vue({
el: '#app',
data(){
return{
}
},
template: `<App/>`,
components:{
App
}
})
</script>
</body>
</html>
四. Vue进阶
1. 前端路由的实现
前端路由:
- 锚点值 监视
- ajax获取动态的数据
- 核心点是锚点值的改变
下载vue-router: npm install vue-router --save
(1)引入vue-router的模块,默认会抛出一个VueRouter对象
(2)Vue.use(VueRouter)
(3)创建路由对象
(4)路由对象挂在到Vue实例当中
2. Vue-router的基本使用
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
<style type='text/css'>
*{
padding:0;
margin:0;
}
</style>
</head>
<body>
<script type="text/javascript" src="./node_modules/vue/dist/vue.js"></script>
<!--1. 引入vue-routerduixiang-->
<script type="text/javascript" src="./node_modules/vue-router/dist/vue-router.js"></script>
<div id='app'>
</div>
<!--全聚德VueRouter对象 vue-router提供了两个全聚德组件router-link router-view -->
<script type="text/javascript">
// 2. 让Vue使用该VueRouter创建
Vue.use(VueRouter);
var Login = {
template: `
<div>登录页面</div>
`
}
var Register = {
template: `
<div>注册页面</div>
`
}
// 3. 创建一个路由对象
var router = new VueRouter({
// 配置路由对象
routes: [
{
path: '/login',
component: Login
},
{
path: '/register',
component: Register
},
]
});
// router-link默认会被渲染成a标签,to属性默认会被渲染成href属性
// router-view是所有路由的出口
var App = {
template: `
<div>
<router-link to='/login'>登录页面</router-link>
<router-link to='/register'>登录页面</router-link>
<router-view></router-view>
</div>
`
}
new Vue({
el: '#app',
components:{
App
},
router,
template: `<App/>`
})
</script>
</body>
</html>
3. 命名路由的使用
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
<style type='text/css'>
*{
padding:0;
margin:0;
}
</style>
</head>
<body>
<script type="text/javascript" src="./node_modules/vue/dist/vue.js"></script>
<!--1. 引入vue-routerduixiang-->
<script type="text/javascript" src="./node_modules/vue-router/dist/vue-router.js"></script>
<div id='app'>
</div>
<!--全聚德VueRouter对象 vue-router提供了两个全聚德组件router-link router-view -->
<script type="text/javascript">
// 2. 让Vue使用该VueRouter创建
Vue.use(VueRouter);
var Login = {
template: `
<div>登录页面</div>
`
}
var Register = {
template: `
<div>注册页面</div>
`
}
// 3. 创建一个路由对象
var router = new VueRouter({
// 配置路由对象
routes: [
{
path: '/login',
name:'login',
component: Login
},
{
path: '/register',
name:'register',
component: Register
},
]
});
// router-link默认会被渲染成a标签,to属性默认会被渲染成href属性
// router-view是所有路由的出口
var App = {
template: `
<div>
<router-link to="{name:'login'}">登录页面</router-link>
<router-link to="{name:'register'}">注册页面</router-link>
<router-view></router-view>
</div>
`
}
new Vue({
el: '#app',
components:{
App
},
router,
template: `<App/>`
})
</script>
</body>
</html>
4. 路由参数param和query的使用
路由范式:
xxx.html#/user/1 params
// 配置路由对象中
{
path: '/user/:id',
componenet: User
}
<router-link :to="{name:'user', params:{id:1}}"></router-link>
xxx.html#/user?userId=1 query
{
path: '/user',
}
<router-link :to="{name:'User', query:{id:1}}"></router-link>
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
<style type='text/css'>
*{
padding:0;
margin:0;
}
</style>
</head>
<body>
<script type="text/javascript" src="./node_modules/vue/dist/vue.js"></script>
<!--1. 引入vue-routerduixiang-->
<script type="text/javascript" src="./node_modules/vue-router/dist/vue-router.js"></script>
<div id='app'>
</div>
<!--全聚德VueRouter对象 vue-router提供了两个全聚德组件router-link router-view -->
<script type="text/javascript">
// 2. 让Vue使用该VueRouter创建
Vue.use(VueRouter);
var UserParams = {
template: `
<div>我是用户1</div>
`,
}
var UserQuery = {
template: `
<div>我是用户2</div>
`
}
// 3. 创建一个路由对象
var router = new VueRouter({
// 配置路由对象
routes: [
{
// 动态的路由参数以冒号开头
path: '/user/:userId',
name: 'userp',
component: UserParams
},
{
path: '/user',
name: 'userq',
component: UserQuery,
},
]
});
// router-link默认会被渲染成a标签,to属性默认会被渲染成href属性
// router-view是所有路由的出口
var App = {
template: `
<div>
<router-link :to='{name:"userp", params:{userId:1}}'>用户1</router-link>
<router-link :to='{name:"userq", query:{userId:2}}'>用户2</router-link>
<router-view></router-view>
</div>
`
}
new Vue({
el: '#app',
components:{
App
},
router,
template: `<App/>`
})
</script>
</body>
</html>
5. 编程式导航
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
<style type='text/css'>
*{
padding:0;
margin:0;
}
</style>
</head>
<body>
<script type="text/javascript" src="./node_modules/vue/dist/vue.js"></script>
<!--1. 引入vue-routerduixiang-->
<script type="text/javascript" src="./node_modules/vue-router/dist/vue-router.js"></script>
<div id='app'>
</div>
<!--全聚德VueRouter对象 vue-router提供了两个全聚德组件router-link router-view -->
<script type="text/javascript">
// 2. 让Vue使用该VueRouter创建
Vue.use(VueRouter);
var UserParams = {
template: `
<div>我是用户1</div>
`
}
var UserQuery = {
template: `
<div>我是用户2</div>
`
}
// 3. 创建一个路由对象
var router = new VueRouter({
// 配置路由对象
routes: [
{
// 动态的路由参数以冒号开头
path: '/user/:userId',
name: 'userp',
component: UserParams
},
{
path: '/user',
name: 'userq',
component: UserQuery,
},
]
});
// router-link默认会被渲染成a标签,to属性默认会被渲染成href属性
// router-view是所有路由的出口
var App = {
template: `
<div>
<button @click='paramsHandler'>用户1</button>
<button @click='queryHandler'>用户2</button>
<router-view></router-view>
</div>
`,
methods:{
paramsHandler(){
// 编程式导航
this.$router.push({name:'userp', params:{userId:123}})
},
queryHandler(){
this.$router.push({name:'userq', query:{userId: 321}})
}
}
}
new Vue({
el: '#app',
components:{
App
},
router,
template: `<App/>`
})
</script>
</body>
</html>
6. 嵌套路由的使用
一个router-view嵌套另外一个router-view
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
<style type='text/css'>
*{
padding:0;
margin:0;
}
</style>
</head>
<body>
<script type="text/javascript" src="./node_modules/vue/dist/vue.js"></script>
<!--1. 引入vue-routerduixiang-->
<script type="text/javascript" src="./node_modules/vue-router/dist/vue-router.js"></script>
<div id='app'>
</div>
<!--全聚德VueRouter对象 vue-router提供了两个全聚德组件router-link router-view -->
<script type="text/javascript">
// 嵌套路由
// 需求:进入首页之后,点击音乐/home/music 电影/home/movie
Vue.use(VueRouter);
var Home = {
template: `
<div>我是首页
<router-link to='/home/music'>音乐</router-link>
<router-link to='/home/movie'>电影</router-link>
<!--子路由组建的出口-->
<router-view></router-view>
</div>
`
}
var Music = {
template:`
<div>我是音乐</div>
`
}
var Movie = {
template:`
<div>我是电影</div>
`
}
var router = new VueRouter({
// 配置路由对象
routes: [
{
path: '/',
// redirect: {name: 'home'},
redirect: '/home'
},
{
path: '/home',
name: 'home',
component: Home,
children: [
// 动态路由匹配 表示子组件中的结构是不同的
// 当访问/home时,Home组件的出口是不会渲染任何内容,因为没有匹配到合适的子路由
{
path: '',
component: Music
},
{
path: 'music',
component: Music,
},
{
path: 'movie',
component: Movie,
},
]
},
]
});
// router-link默认会被渲染成a标签,to属性默认会被渲染成href属性
// router-view是所有路由的出口
var App = {
template: `
<div>
<router-link :to='{name: "home"}'>首页</router-link>
<router-view></router-view>
</div>
`,
methods:{
}
}
new Vue({
el: '#app',
components:{
App
},
router,
template: `<App/>`
})
</script>
</body>
</html>
7. 动态路由匹配
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
<style type='text/css'>
*{
padding:0;
margin:0;
}
</style>
</head>
<body>
<script type="text/javascript" src="./node_modules/vue/dist/vue.js"></script>
<!--1. 引入vue-routerduixiang-->
<script type="text/javascript" src="./node_modules/vue-router/dist/vue-router.js"></script>
<div id='app'>
</div>
<!--全聚德VueRouter对象 vue-router提供了两个全聚德组件router-link router-view -->
<script type="text/javascript">
// 嵌套路由
// 需求:进入首页之后,点击音乐/home/music 电影/home/movie
Vue.use(VueRouter);
var Timeline = {
template: `
<div>
<router-link :to='{name:"comDesc", params:{id: "android"}}'>Android</router-link>
<router-link :to='{name:"comDesc", params:{id: "frontend"}}'>前端</router-link>
<!--子路由组建的出口-->
<router-view></router-view>
</div>
`
}
var Pins = {
template: `
<div>我是沸点
<!--子路由组建的出口-->
<router-view></router-view>
</div>
`
}
// 共同的子组件
var ComDesc = {
data(){
return{
msg: ''
}
},
template: `
<div>我是{{msg}}
<!--子路由组建的出口-->
<router-view></router-view>
</div>
`,
created(){
this.msg = "Android"
},
watch:{
// 注意:当使用路由参数时,例如从/user/foo导航到/user/bae,原来的组件实例会被复用。
// 因为两个路由都渲染同个组件,比起销毁再创建,复用则显得更加高效。不过这也意味着组件的生命周期钩子不再被调用
'$route'(to, from){
this.msg = to.params.id;
}
}
}
var router = new VueRouter({
// 配置路由对象
routes: [
{
path: '/timeline',
component: Timeline,
children: [
{
path: '',
component: ComDesc
},
{
path: '/timeline/:id',
name: 'comDesc',
component: ComDesc
}
]
},
{
path: '/pins',
name: 'pins',
component: Pins,
},
]
});
// router-link默认会被渲染成a标签,to属性默认会被渲染成href属性
// router-view是所有路由的出口
var App = {
template: `
<div>
<router-link to='/timeline'>首页</router-link>
<router-link to='/pins'>沸点</router-link>
<router-view></router-view>
</div>
`,
methods:{
}
}
new Vue({
el: '#app',
components:{
App
},
router,
template: `<App/>`
})
</script>
</body>
</html>
8. keep-alive在路由中的使用
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
<style type='text/css'>
*{
padding:0;
margin:0;
}
</style>
</head>
<body>
<script type="text/javascript" src="./node_modules/vue/dist/vue.js"></script>
<!--1. 引入vue-routerduixiang-->
<script type="text/javascript" src="./node_modules/vue-router/dist/vue-router.js"></script>
<div id='app'>
</div>
<!--全聚德VueRouter对象 vue-router提供了两个全聚德组件router-link router-view -->
<script type="text/javascript">
// 嵌套路由
// 需求:进入首页之后,点击音乐/home/music 电影/home/movie
Vue.use(VueRouter);
var Timeline = {
template: `
<div>
我是首页
</div>
`,
created(){
console.log('首页组件创建了');
},
mounted(){
console.log('首页组件DOM加载了');
},
destroyed(){
console.log('沸点销毁了');
}
}
var Pins = {
template: `
<div>
<h3 @click='clickHandler'>我是沸点</h3>
</div>
`,
methods:{
clickHandler(e){
e.target.style.color='red';
}
}
}
var router = new VueRouter({
// 配置路由对象
routes: [
{
path: '/timeline',
component: Timeline,
},
{
path: '/pins',
name: 'pins',
component: Pins,
},
]
});
// router-link默认会被渲染成a标签,to属性默认会被渲染成href属性
// router-view是所有路由的出口
var App = {
template: `
<div>
<router-link to='/timeline'>首页</router-link>
<router-link to='/pins'>沸点</router-link>
//
<keep-alive>
<router-view></router-view>
</keep-alive>
</div>
`,
methods:{
}
}
new Vue({
el: '#app',
components:{
App
},
router,
template: `<App/>`
})
</script>
</body>
</html>
9. 权限控制
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
<style type='text/css'>
*{
padding:0;
margin:0;
}
</style>
</head>
<body>
<script type="text/javascript" src="./node_modules/vue/dist/vue.js"></script>
<!--1. 引入vue-routerduixiang-->
<script type="text/javascript" src="./node_modules/vue-router/dist/vue-router.js"></script>
<div id='app'>
</div>
<!--全聚德VueRouter对象 vue-router提供了两个全聚德组件router-link router-view -->
<script type="text/javascript">
// 嵌套路由
// 需求:进入首页之后,点击音乐/home/music 电影/home/movie
Vue.use(VueRouter);
var Home = {
template: `
<div>
我是首页
</div>
`,
}
var Questionbank = {
template: `
<div>
<h3>我是题库</h3>
</div>
`,
}
// 登录组件
var Login = {
data(){
return{
name: '',
pwd: ''
}
},
template: `
<div>
<input type="text" v-model='name'/>
<input type="text" v-model='pwd'/>
<input type="button" value="登录" @click="loginHandler">
</div>
`,
methods:{
loginHandler(){
// 进行登录
// 存储用户名和密码,保存到localStorage然后跳转至相应的路由
localStorage.setItem('user', {name:this.name, pwd:this.pwd});
// 编程式导航
this.$router.push({name:'questionbank'});
}
}
}
var router = new VueRouter({
// 配置路由对象
routes: [
{
path: '/home',
component: Home,
},
{
path: '/questionbank',
name: 'questionbank',
component: Questionbank,
// 给未来的路由,做权限控制
meta:{
// 表明访问该组件需要登录
auth: true,
}
},
{
path: '/login',
component: Login,
}
]
});
// 全局的导航守卫
router.beforeEach(function(to, from, next){
// 如果不调用next(),页面会卡住
if(to.meta.auth){
if(localStorage.getItem('user')){
next();
}else{
next({path: '/login'});
}
}else{
// 直接放行
next();
}
});
// router-link默认会被渲染成a标签,to属性默认会被渲染成href属性
// router-view是所有路由的出口
var App = {
template: `
<div>
<router-link to='/home'>首页</router-link>
<router-link to='/questionbank'>智能题库</router-link>
<router-link to='/login'>登录</router-link>
<a href='#' @click='clear'>退出</a>
<keep-alive>
<router-view></router-view>
</keep-alive>
</div>
`,
methods:{
clear(){
// 退出
localStorage.removeItem('user');
this.$router.push('/login')
}
}
}
new Vue({
el: '#app',
components:{
App
},
router,
template: `<App/>`
})
</script>
</body>
</html>
10. Axios
Axios是一个基于promise的HTTP库,可以用在浏览器和node.js中
1)axios的get请求
// 为给定ID的user创建请求
axios.get('/user?ID=123')
.then(function(response){
console.log(response);
})
.catch(function(error){
console.log(error);
});
2)axios的post请求
axios.post('/user', {
firstName: "Josh",
lastName: "Howard"
})
.then(function(response){
console.log(response);
})
.catch(function(error){
console.log(error);
});
3)axios的GET和POST请求实例
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
<style type='text/css'>
*{
padding:0;
margin:0;
}
</style>
</head>
<body>
<script type="text/javascript" src="./node_modules/vue/dist/vue.js"></script>
<!--1. 引入vue-routerduixiang-->
<script type="text/javascript" src="./node_modules/axios/dist/axios.js"></script>
<div id='app'>
</div>
<!--全聚德VueRouter对象 vue-router提供了两个全聚德组件router-link router-view -->
<script type="text/javascript">
var App = {
data(){
return{
msg: '',
}
},
template: `
<div>
<button @click="sendAjax">发get请求</button>
<div v-html='msg'></div>
<button @click="sendAjaxByPost">发post请求</button>
</div>
`,
methods:{
sendAjax(){
axios.get('http://127.0.0.1:8800/')
.then((res)=>{
console.log(res);
this.msg = res.data;
})
.catch((err)=>{
console.log(err);
})
},
sendAjaxByPost(){
var params = new URLSearchParams();
params.append('name', "Ajax");
axios.post('http://127.0.0.1:8800/create', params)
.then(function(res){
console.log(res);
}).catch(function(err){
console.log(err);
})
}
}
}
new Vue({
el: '#app',
components:{
App
},
router,
template: `<App/>`
})
</script>
</body>
</html>
4)axios的URL默认匹配1
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
<style type='text/css'>
*{
padding:0;
margin:0;
}
</style>
</head>
<body>
<script type="text/javascript" src="./node_modules/vue/dist/vue.js"></script>
<script type="text/javascript" src="./node_modules/axios/dist/axios.js"></script>
<div id='app'>
</div>
<script type="text/javascript">
// 挂载Vue.prototype.$axios = axios;使用插件
挂载Vue.prototype.$axios = axios
// 配置公共的url
axios.defaults.baseURL = 'http://127.0.0.1:8800';
var App = {
data(){
return{
msg: '',
}
},
template: `
<div>
<button @click="sendAjax">发get请求</button>
<div v-html='msg'></div>
<button @click="sendAjaxByPost">发post请求</button>
</div>
`,
methods:{
sendAjax(){
},
sendAjaxByPost(){
var params = new URLSearchParams();
params.append('name', "Ajax");
this.$axios.post('/create', params)
.then(function(res){
console.log(res);
}).catch(function(err){
console.log(err);
})
}
}
}
new Vue({
el: '#app',
components:{
App
},
router,
template: `<App/>`
})
</script>
</body>
</html>
11. webpack
对前端中的资源(html、css、js、png、mp3等)进行编译打包,支持模块化es6的module
webpack中有很多loader
1)css-loader; style-loader
module.exports = {
entry: {
"main": "./main.js"
},
output: {
filename: "./bundle.js"
},
watch: true,
// 模块中的loader
module:{
loaders:[
{
test: /\.css$/,
loader: 'style-loader!css-loader'
}
]
}
2)vue-loader
12. 前端脚手架
安装vue-cli:npm install -g @vue/cli
vue init <模板> <项目名>,例如:vue init webpack-simple my-project
模板:webpack-simple 简单的配置webpack的模板
vue init webpack webpack_project
13. vuex
Vuex是一个专为Vue.js应用程序开发的状态管理模式
下载npm install vuex -S
1) index.js
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex);
const store = new Vuex.Store({
// 五大将 state mutation action getter module
state:{
count:1
},
mutations:{
// 修改状态 更改 Vuex 的 store 中的状态state的唯一方法是提交(commit) mutation
// 方法
// 只能做同步操作 不能 直接commit
// 同步
addCount(state,val){
state.count+=val;
},
// 同步
asyncHandler(state,val){
state.count+=val;
}
},
actions:{
// Action 类似于 mutation,不同在于:
// Action 提交 mutation,而不是直接变更状态。
// Action 可以包含任意异步操作。
asyncHandler({commit},val){
commit('asyncHandler',val)
},
addCount({commit},val){
setTimeout(()=>{
commit('addCount',val)
},2000)
}
}
});
export default store;
2) main.js
// The Vue build version to load with the `import` command
// (runtime-only or standalone) has been set in webpack.base.conf with an alias.
import Vue from 'vue'
import App from './App'
import store from './store'
Vue.config.productionTip = false
/* eslint-disable no-new */
new Vue({
el: '#app',
store,
components: { App },
template: '<App/>'
})
3) HelloWorld.vue
<template>
<div class="hello">
<h2>{{myCount}}</h2>
<Child />
<button @click ='asyncHandler'>同步修改</button>
<button @click ='change'>异步修改</button>
</div>
</template>
<script>
import Child from './child'
export default {
name: 'HelloWorld',
data () {
return {
msg: 'Welcome to Your Vue.js App'
}
},
computed:{
myCount(){
return this.$store.state.count;
}
},
components:{
Child
},
methods:{
change(){
this.$store.dispatch('addCount',3)
},
asyncHandler(){
this.$store.dispatch('asyncHandler',1);
}
}
}
</script>
<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped>
h1, h2 {
font-weight: normal;
}
ul {
list-style-type: none;
padding: 0;
}
li {
display: inline-block;
margin: 0 10px;
}
a {
color: #42b983;
}
</style>
4) child.vue
<template>
<div>
<p>{{myCount}}</p>
</div>
</template>
<script>
export default {
name: 'child',
data() {
return {
};
},
computed:{
myCount(){
return this.$store.state.count;
}
}
};
</script>
<style lang="css" scoped>
</style>