Vue基础-代码篇

使用

1
2
3
4
5
Vue的基本使用步骤
1、需要提供标签用于填充数据-#app
2、引入vue.js库文件
3、可以使用vue的语法做功能了-指令
4、把vue提供的数据填充到标签里面-data,state,axios

隐藏

渲染时,隐藏模板属性
带有属性 v-cloak的标签 让他隐藏

背后的原理:先通过样式隐藏内容,然后在内存中进行值的替换,替换好之后再显示最终的结果

填充数据

1、v-text指令用于将数据填充到标签中,作用于插值表达式类似,但是没有闪动问题

2、v-html指令用于将HTML片段填充到标签中,但是可能有安全问题

3、v-pre用于显示原始信息

v-once

<div v-once>{{info}}</div>

v-once的应用场景:如果显示的信息后续不需要再修改,你们可以使用v-once,这样可以提高性能。

双向绑定

v-model='msg'
给标签添加指令,可以绑定数据,一同变化

事件基本用法

1
2
3
4
<button v-on:click='num++'>点击</button>
<button @click='num++'>点击1</button>
<button @click='handle'>点击2</button>
<button @click='handle()'>点击3</button>

methods 中 主要是定义一些函数

1
2
3
4
5
6
handle: function() {
// 这里的this是Vue的实例对象+
console.log(this === vm)
// 在函数中 想要使用data里面的数据 一定要加this
this.num++;
}

事件函数传递

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
<!-- 如果事件直接绑定函数名称,那么默认会传递事件对象作为事件函数的第一个参数 -->
<button v-on:click='handle1'>点击1</button>
<!-- 2、如果事件绑定函数调用,那么事件对象必须作为最后一个参数显示传递,
并且事件对象的名称必须是$event
-->
<button v-on:click='handle2(123, 456,$event)'>点击2</button>

handle1: function(event) {
console.log(event.target.innerHTML)

}
handle2: function(p, p1, event) {
console.log(p, p1)
// 通过event可以拿到触发事件的对象
// event.target.tagName表示标签的名称
console.log(event.target.tagName)
// event.target.innerHTML获取标签的内容
console.log(event.target.innerHTML)

this.num++;

事件修饰符

学习链接

1
2
3
4
5
6
7
8
<button v-on:click.stop='handle1'>点击1</button>
<a href="http://www.baidu.com" v-on:click.prevent='handle2'>百度</a>

// 阻止冒泡
// event.stopPropagation();

// 阻止默认行为
// event.preventDefault();

按键修饰符

1
2
<input type="text" v-on:keyup.f1='handleSubmit' v-model='pwd'>

按键修饰符

1
2
3
4
5
6
<input type="text" v-on:keyup.delete='clearContent' v-model='uname'>

clearContent:function(){
// 按delete键的时候,清空用户名
this.uname = '';
},

简单计算器

思路:
input,输入信息,双向绑定变量(指令),在data中声明
点击按钮,this. 获取信息,然后+-*/
输出,参考上面的输出指令,这里v-text

属性绑定

动态绑定信息,绑定的是变量,data中声明,可修改

1
2
3
4
5
6
7
8
9
10
11
12
13
<a v-bind:href="url">百度</a>
<a :href="url">百度1</a>
<button v-on:click='handle'>切换</button>

data: {
url: 'http://www.baidu.com'
},
methods: {
handle: function(){
// 修改URL地址
this.url = 'http://itcast.cn';
}
}

v-model本质

1
2
3
4
5
6
7
8
<input type="text" v-bind:value="msg" v-on:input='handle'>
<input type="text" v-bind:value="msg" v-on:input='msg=$event.target.value'>
<input type="text" v-model='msg'>

handle: function(event){
// 使用输入域中的最新的数据覆盖原来的数据
this.msg = event.target.value;
}

样式绑定

01

样式绑定布尔值,切换是 非

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
.active {
border: 1px solid red;
width: 100px;
height: 100px;
}
.error {
background-color: orange;
}

<div v-bind:class="{active: isActive,error: isError}">
测试样式
</div>
<button v-on:click='handle'>切换</button>

handle: function(){
// 控制isActive的值在true和false之间进行切换
this.isActive = !this.isActive;
this.isError = !this.isError;
}

02

样式 动态绑定-变量

1
2
3
4
5
6
7
8
9
10
11
<div v-bind:class='[activeClass, errorClass]'>测试样式</div>

data: {
activeClass: 'active',
errorClass: 'error'
},

handle: function(){
this.activeClass = '';
this.errorClass = '';
},

03

样式 动态绑定细节

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
<div v-bind:class='[activeClass, errorClass, {test: isTest}]'>测试样式</div>
<div v-bind:class='arrClasses'></div>
<div v-bind:class='objClasses'></div>
<div class="base" v-bind:class='objClasses'></div>

<button v-on:click='handle'>切换</button>

样式绑定相关语法细节:
1、对象绑定和数组绑定可以结合使用
2、class绑定的值可以简化操作
3、默认的class如何处理?默认的class会保留

data: {
activeClass: 'active',
errorClass: 'error',
isTest: true,
arrClasses: ['active','error'],
objClasses: {
active: true,
error: true
}
},

handle: function(){
// this.isTest = false;
this.objClasses.error = false;
}

04

行内样式-style 动态绑定
样式在data 里面写

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
                             这里是变量
<div v-bind:style='{border: borderStyle, width: widthStyle, height: heightStyle}'></div>
<div v-bind:style='objStyles'></div>
<div v-bind:style='[objStyles, overrideStyles]'></div>
<button v-on:click='handle'>切换</button>

data: {
borderStyle: '1px solid blue',
widthStyle: '100px',
heightStyle: '200px',
objStyles: {
border: '1px solid green',
width: '200px',
height: '100px'
},
overrideStyles: {
border: '5px solid orange',
backgroundColor: 'blue'
}
},


methods: {
handle: function(){
this.heightStyle = '100px';
this.objStyles.width = '100px';
}
}

分支结构

v-if
v-else
操作dom

v-show
操作样式

1
2
3
4
5
6
7
8
9
10
<div v-if='score>=90'>优秀</div>
<div v-else-if='score<90&&score>=80'>良好</div>
<div v-else-if='score<80&&score>60'>一般</div>
<div v-else>比较差</div>
<div v-show='flag'>测试v-show</div>

data: {
score: 10,
flag: false
},

循环结构

遍历数组

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
<li v-for='item in fruits'>{{item}}</li>
<li v-for='(item, index) in fruits'>{{item + '---' + index}}</li>
<li>-----------------</li>
<li :key='item.id' v-for='(item, index) in myFruits'>
<span>{{item.ename}}</span>
<span>-----</span>
<span>{{item.cname}}</span>
</li>

data: {
fruits: ['apple', 'orange', 'banana'],
myFruits: [{
id: 1,
ename: 'apple',
cname: '苹果'
},{
id: 2,
ename: 'orange',
cname: '橘子'
},{
id: 3,
ename: 'banana',
cname: '香蕉'
}]
}

遍历对象

k v i

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
<div v-if='v==13' v-for='(v,k,i) in obj'>{{v + '---' + k + '---' + i}}</div>

// 使用原生js遍历对象
var obj = {
uname: 'lisi',
age: 12,
gender: 'male'
}
for(var key in obj) {
console.log(key, obj[key])
}

var vm = new Vue({
el: '#app',
data: {
obj: {
uname: 'zhangsan',
age: 13,
gender: 'female'
}
}
});

选项卡案例

配合样式来渲染,,v-for可以渲染全部,但是有了样式,就只显示其中之一
样式也是排他思想,所有display: none, 当前display: block

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
<ul>
<li v-on:click='change(index)' :class='currentIndex==index?"active":""' :key='item.id'
v-for='(item,index) in list'>{{item.title}}</li>
</ul>

<div :class='currentIndex==index?"current":""' :key='item.id' v-for='(item, index) in list'>
<img :src="item.path">
</div>


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: function(index) {
// 在这里实现选项卡切换操作:本质就是****操作类名******
// 如何操作类名?就是通过currentIndex
this.currentIndex = index;
}
}

———-


表单基本操作

结构
form > div*4

div > span > 表单元素

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
<input type="text" v-model='uname'>

<input type="radio" id="male" value="1" v-model='gender'>
<label for="male">男</label>
<input type="radio" id="female" value="2" v-model='gender'>
<label for="female">女</label>

<input type="checkbox" id="ball" value="1" v-model='hobby'>
<label for="ball">篮球</label>
<input type="checkbox" id="sing" value="2" v-model='hobby'>
<label for="sing">唱歌</label>
<input type="checkbox" id="code" value="3" v-model='hobby'>
<label for="code">写代码</label>

<select v-model='occupation' multiple>
<option value="0">请选择职业...</option>
<option value="1">教师</option>
<option value="2">软件工程师</option>
<option value="3">律师</option>
</select>

<textarea v-model='desc'></textarea>

<input type="submit" value="提交" @click.prevent='handle'>

// v-model 绑定的变量在这里,赋初始值
data: {
uname: 'lisi',
gender: 2,
hobby: ['2','3'],
// occupation: 3
occupation: ['2','3'],
desc: 'nihao'
},

表单域修饰符用法

1:number
在用v-model进行双向绑定时,用number修饰符。如:v-model.number.
做用:直接将input输入框的值转换为number类型。

2:trim:去掉字符串两头的空字符。

3:lazy :将input事件换位change事件。
v-model默认是input事件,就是只要input数据一变,视图就会随着变。
chang是当input框失去焦点时才触发。
如:v-model.lazy

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<input type="text" v-model.number='age'>
<input type="text" v-model.trim='info'>
<input type="text" v-model.lazy='msg'>

data: {
age: '',
info: '',
msg: ''
},
methods: {
handle: function(){
console.log(this.age + 13)
// console.log(this.info.length)
}
}

计算属性基本用法

看,这里是变量,,而且没有在data里面。。。

1
2
3
4
5
6
7
8
9
10
11
<div>{{msg}}</div>
<div>{{reverseString}}</div>

data: {
msg: 'Nihao'
},
computed: {
reverseString: function(){
return this.msg.split('').reverse().join('');
}
}

计算属性和方法的区别

计算属性与方法的区别:计算属性是基于依赖进行缓存的,而方法不缓存

计算属性执行一次,method执行3次
注意使用的时候,方法要加()-表示调用

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
<div>{{reverseString}}</div>
<div>{{reverseString}}</div>
<div>{{reverseString}}</div>
<div>{{reverseMessage()}}</div>
<div>{{reverseMessage()}}</div>
<div>{{reverseMessage()}}</div>

methods: {
reverseMessage: function(){
console.log('methods')
return this.msg.split('').reverse().join('');
}
},
computed: {
reverseString: function(){
console.log('computed')
// return this.msg.split('').reverse().join('');
var total = 0;
for(var i=0;i<=this.num;i++){
total += i;
}
return total;
}
}

侦听器基本使用方法

侦听器- 侦听变量变化

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
<div>{{fullName}}</div>
<div>{{firstName}} {{lastName}}</div>

data: {
firstName: 'Jim',
lastName: 'Green',
// fullName: 'Jim Green'
},

computed: {
// fullName: function(){
// return this.firstName + ' ' + this.lastName;
// }
},

watch: {
firstName: function(val) {
this.fullName = val + ' ' + this.lastName;
},
lastName: function(val) {
this.fullName = this.firstName + ' ' + val;
}
}

侦听器案例

watch 侦听变量, 调用methods中的方法,
侦听uname 判断是否合理。

  • 侦听器
  • 1、采用侦听器监听用户名的变化
  • 2、调用后台接口进行验证
  • 3、根据验证的结果调整提示信息
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
<span>
<input type="text" v-model.lazy='uname'>
</span>
<span>{{tip}}</span>

data: {
uname: '',
tip: ''
},

methods: {
checkName: function(uname) {
// 调用接口,但是可以使用定时任务的方式模拟接口调用
var that = this;
setTimeout(function(){
// 模拟接口调用
if(uname == 'admin') {
that.tip = '用户名已经存在,请更换一个';
}else{
that.tip = '用户名可以使用';
}
}, 2000);
}
},

watch: {
uname: function(val){
// 调用后台接口验证用户名的合法性
this.checkName(val);
// 修改提示信息
this.tip = '正在验证...';
}
}

过滤器的基本用法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<div>{{msg | upper}}</div>
<div>{{msg | upper | lower}}</div>

Vue.filter('lower', function(val) {
// 请注意,该方法并不会修改数组,而是返回一个子数组。如果想删除数组中的一段元素,
// 应该使用方法 Array.splice()。
return val.charAt(0).toLowerCase() + val.slice(1);
});

data: {
msg: ''
},
filters: {
upper: function(val) {
return val.charAt(0).toUpperCase() + val.slice(1);
}
}

带参数的过滤器

格式化日期

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
<div>{{date | format('yyyy-MM-dd hh:mm:ss')}}</div>

Vue.filter('format', function(value, arg) {
function dateFormat(date, format) {
if (typeof date === "string") {
var mts = date.match(/(\/Date\((\d+)\)\/)/);
if (mts && mts.length >= 3) {
date = parseInt(mts[2]);
}
}
date = new Date(date);
if (!date || date.toUTCString() == "Invalid Date") {
return "";
}
var map = {
"M": date.getMonth() + 1, //月份
"d": date.getDate(), //日
"h": date.getHours(), //小时
"m": date.getMinutes(), //分
"s": date.getSeconds(), //秒
"q": Math.floor((date.getMonth() + 3) / 3), //季度
"S": date.getMilliseconds() //毫秒
};

format = format.replace(/([yMdhmsqS])+/g, function(all, t) {
var v = map[t];
if (v !== undefined) {
if (all.length > 1) {
v = '0' + v;
v = v.substr(v.length - 2);
}
return v;
} else if (t === 'y') {
return (date.getFullYear() + '').substr(4 - all.length);
}
return all;
});
return format;
}
return dateFormat(value, arg);
})

data: {
date: new Date()
}

生命周期

常用共8个
beforeCreate
created –最早可以使用方法和数据的地方

beforeMount-都已经完成数据变更了,就是没有渲染,可以改变数据
mounted

beforeUpdate-数据更新时候调用的
updated

beforeDestroy-实例尚在,可以使用,节省资源用
destroyed

动态响应数据处理

调用api

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
<li v-for='item in list'>{{item}}</li>

<div>{{info.name}}</div>
<div>{{info.age}}</div>
<div>{{info.gender}}</div>

data: {
list: ['apple', 'orange', 'banana'],
info: {
name: 'lisi',
age: 12
}
},

vm.$set(vm.list, 1, 'lemon');
// 改变orange为lemon

vm.$set(vm.info, 'gender', 'female');
// 也可以添加一个gender属性,值为femal

图书管理案例

增删改查。。

01

首先先有个样子
渲染 数组

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
<tr :key='item.id' v-for='item in books'>
<td>{{item.id}}</td>
<td>{{item.name}}</td>
<td>{{item.date}}</td>
<td>
<a href="" @click.prevent>修改</a>
<span>|</span>
<a href="" @click.prevent>删除</a>
</td>
</tr>

data: {
books: [{
id: 1,
name: '三国演义',
date: ''
},{
id: 2,
name: '水浒传',
date: ''
},{
id: 3,
name: '红楼梦',
date: ''
},{
id: 4,
name: '西游记',
date: ''
}]
}

02

增加添加功能

写入数据-即添加入数组
创建一个空对象,填入数据,把对象添加进数组

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
<div class="book">
<div>
<label for="id">
编号:
</label>
<input type="text" id="id" v-model='id'>
<label for="name">
名称:
</label>
<input type="text" id="name" v-model='name'>
<button @click='handle'>提交</button>
</div>
</div>

id: '',
name: '',

handle: function(){
// 添加图书
var book = {};
book.id = this.id;
book.name = this.name;
book.date = '';
this.books.push(book);
// 清空表单
this.id = '';
this.name = '';

03

修改图书-创建一个数组 根据id查找 (过滤器),修改的内容写入源id
设置了一个标志, 不允许修改id,, :disabled=”flag”

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
<input type="text" id="id" v-model='id' :disabled="flag">
<input type="text" id="name" v-model='name'>

这一步是显示在输入框中的(填充到表单),最后完成修改是在提交按钮中的
<a href="" @click.prevent='toEdit(item.id)'>修改</a>

toEdit: function(id) {
// 禁止修改ID
this.flag = true;
console.log(id)
// 根据ID查询出要编辑的数据
var book = this.books.filter(function(item) {
return item.id == id;
});
console.log(book)
// 把获取到的信息填充到表单
this.id = book[0].id;
this.name = book[0].name;
}


handle: function() {
//判断是否是修改菜单过来的,
//如果不是,就添加,不是还填了一个判断,是否为空
 if (this.flag) {
  // 编辑图书
  // 就是根据当前的ID去更新数组中对应的数据
  this.books.some((item) => {
  if (item.id == this.id) {
  item.name = this.name;
  // 完成更新操作之后,需要终止循环
  return true;
  }
  });
  this.flag = false;
 } else {
  // 添加图书
  if (this.id && this.name) {
  var book = {};
  book.id = this.id;
  book.name = this.name;
  book.date = '';
  this.books.push(book);
  // 清空表单
  this.id = '';
  this.name = '';
  }
  // 清空表单
this.id = '';
this.name = '';
},
 }

04

删除图书

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<a href="" @click.prevent='deleteBook(item.id)'>删除</a>

deleteBook: function(id) {
// 删除图书
// 根据id从数组中查找元素的索引
// var index = this.books.findIndex(function(item){
// return item.id == id;
// });
// 根据索引删除数组元素
// this.books.splice(index, 1);
// -------------------------
// 方法二:通过filter方法进行删除
this.books = this.books.filter(function(item) {

return item.id != id;
});

05

常用特性-即相关功能,以及常用的设计思路
data中初始化,”” [] false
mounted中写入数据,后台数据通常这里写入、获取,然后填充入模板
全局时间过滤器

时间、总数、是否重名-disabled开关

———–


组件基本使用

全局注册,名字,{}
数据-方法有返回值
模板属性-定义渲染内容
方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<button-counter></button-counter>

Vue.component('button-counter', {
data: function(){
return {
count: 0
}
},
template: '<button @click="handle">点击了{{count}}次</button>',
methods: {
handle: function(){
this.count += 2;
}
}
})

组件注意事项

  • 组件注册注意事项
  • 1、组件参数的data值必须是函数
  • 2、组件模板必须是单个跟元素
  • 3、组件模板的内容可以是模板字符串
1
2
3
4
5
6
template: `
<div>
<button @click="handle">点击了{{count}}次</button>
<button>测试123</button>
</div>
`,
  • 组件注册注意事项
  • 如果使用驼峰式命名组件,那么在使用组件的时候,
  • 只能在字符串模板中用驼峰的方式使用组件,
  • 但是在普通的标签模板中,必须使用短横线的方式使用组件
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
<button-counter></button-counter>
<hello-world></hello-world>

Vue.component('HelloWorld', {
data: function(){
return {
msg: 'HelloWorld'
}
},
template: '<div>{{msg}}</div>'
});

Vue.component('button-counter', {
data: function(){
return {
count: 0
}
},
template: `
<div>
<button @click="handle">点击了{{count}}次</button>
<button>测试123</button>
<HelloWorld></HelloWorld>**********************
</div>
`,
methods: {
handle: function(){
this.count += 2;
}
}
})

局部组件

局部组件注册
局部组件只能在注册他的父组件中使用

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
 <div id="app">
<hello-world></hello-world>
<hello-tom></hello-tom>
<hello-jerry></hello-jerry>
<test-com></test-com>
</div>

Vue.component('test-com',{
template: '<div>Test<hello-world></hello-world></div>'
});
var HelloWorld = {
data: function(){
return {
msg: 'HelloWorld'
}
},
template: '<div>{{msg}}</div>'
};
var HelloTom = {
data: function(){
return {
msg: 'HelloTom'
}
},
template: '<div>{{msg}}</div>'
};
var HelloJerry = {
data: function(){
return {
msg: 'HelloJerry'
}
},
template: '<div>{{msg}} <input /></div>'
};
var vm = new Vue({
el: '#app',
data: {

},
components: {
'hello-world': HelloWorld,
'hello-tom': HelloTom,
'hello-jerry': HelloJerry
}
});

父传子基础

子组件通过props接收

有冒号,说明传的是变量

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
 <div>{{pmsg}}</div>
<menu-item title='来自父组件的值'></menu-item>
<menu-item :title='ptitle' content='hello'></menu-item>

Vue.component('menu-item', {
props: ['title', 'content'],
data: function() {
return {
msg: '子组件本身的数据'
}
},
template: '<div>{{msg + "----" + title + "-----" + content}}</div>'
});

var vm = new Vue({
el: '#app',
data: {
pmsg: '父组件中内容',
ptitle: '动态绑定属性'
}
});

props的命名规则

:menu-title='ptitle'---- props: ['menuTitle'],
testTile="hello"----- props: ['testTile'],

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<div>{{pmsg}}</div>
<menu-item :menu-title='ptitle'></menu-item>

Vue.component('third-com', {
props: ['testTile'],
template: '<div>{{testTile}}</div>'
});
Vue.component('menu-item', {
props: ['menuTitle'],
template: '<div>{{menuTitle}}<third-com testTile="hello"></third-com></div>'
});
var vm = new Vue({
el: '#app',
data: {
pmsg: '父组件中内容',
ptitle: '动态绑定属性'
}
});

props属性值类型

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
<menu-item :pstr='pstr' :pnum='12' pboo='true' :parr='parr' :pobj='pobj'></menu-item>

props: ['pstr', 'pnum', 'pboo', 'parr', 'pobj'],

template: `
<div>
<div>{{pstr}}</div>
<div>{{12 + pnum}}</div>
<div>{{typeof pboo}}</div>
<ul>
<li :key='index' v-for='(item,index) in parr'>{{item}}</li>
</ul>
<span>{{pobj.name}}</span>
<span>{{pobj.age}}</span>
</div>
</div>
`

data: {
pmsg: '父组件中内容',
pstr: 'hello',
parr: ['apple', 'orange', 'banana'],
pobj: {
name: 'lisi',
age: 12
}
}

子传父

父组件自定义事件。通过子组件触发

子组件向父组件传值-基本用法
props传递数据原则:单向数据流

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
<div :style='{fontSize: fontSize + "px"}'>{{pmsg}}</div>
<menu-item :parr='parr' @enlarge-text='handle'></menu-item>

Vue.component('menu-item', {
props: ['parr'],
template: `
<div>
<ul>
<li :key='index' v-for='(item,index) in parr'>{{item}}</li>
</ul>
<button @click='$emit("enlarge-text")'>扩大父组件中字体大小</button>
</div>
`
});

data: {
pmsg: '父组件中内容',
parr: ['apple','orange','banana'],
fontSize: 10
},
methods: {
handle: function(){
// 扩大字体大小
this.fontSize += 5;
}
}

子传父带参数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
<div :style='{fontSize: fontSize + "px"}'>{{pmsg}}</div>
<menu-item :parr='parr' @enlarge-text='handle($event)'></menu-item>


Vue.component('menu-item', {
props: ['parr'],
template: `
<div>
<ul>
<li :key='index' v-for='(item,index) in parr'>{{item}}</li>
</ul>
<button @click='$emit("enlarge-text", 5)'>扩大父组件中字体大小</button>
<button @click='$emit("enlarge-text", 10)'>扩大父组件中字体大小</button>
</div>
`
});

var vm = new Vue({
el: '#app',
data: {
pmsg: '父组件中内容',
parr: ['apple','orange','banana'],
fontSize: 10
},
methods: {
handle: function(val){
// 扩大字体大小
this.fontSize += val;
}
}
});

兄弟组件之间数据交互

学习链接

*兄弟组件之间数据传递
提供事件中心–var hub = new Vue();

$on-监听事件,
$once-监听事件,执行一次
$off-销毁事件
$emit-触发父组件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
<div>父组件</div>
<div>
<button @click='handle'>销毁事件</button>
</div>
<test-tom></test-tom>
<test-jerry></test-jerry>

// 提供事件中心
var hub = new Vue();

Vue.component('test-tom', {
data: function() {
return {
num: 0
}
},
template: `
<div>
<div>TOM:{{num}}</div>
<div>
<button @click='handle'>点击</button>
</div>
</div>
`,
methods: {
handle: function() {
hub.$emit('jerry-event', 2);
}
},
mounted: function() {
// 监听事件
hub.$on('tom-event', (val) => {
this.num += val;
});
}
);

Vue.component('test-jerry', {
data: function() {
return {
num: 0
}
},
template: `
<div>
<div>JERRY:{{num}}</div>
<div>
<button @click='handle'>点击</button>
</div>
</div>
`,
methods: {
handle: function() {
// 触发兄弟组件的事件
hub.$emit('tom-event', 1);
}
},
mounted: function() {
// 监听事件
hub.$on('jerry-event', (val) => {
this.num += val;
});
}
});

var vm = new Vue({
el: '#app',
data: {

},
methods: {
handle: function() {
hub.$off('tom-event');
hub.$off('jerry-event');
}
}
});


插槽基础

组件插槽:父组件向子组件传递内容

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<alert-box>有bug发生</alert-box>
<alert-box>有一个警告</alert-box>
<alert-box></alert-box>

Vue.component('alert-box', {
template: `
<div>
<strong>ERROR:</strong>
<slot>默认内容</slot>
</div>
`
});

var vm = new Vue({
el: '#app',
data: {
}
});

具名插槽用法

slot命名-位置

1
2
3
4
5
<p slot='header'>标题信息</p>

<header>
<slot name='header'></slot>
</header>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
<div id="app">
<base-layout>
<p slot='header'>标题信息</p>
<p>主要内容1</p>
<p>主要内容2</p>
<p slot='footer'>底部信息信息</p>
</base-layout>

<p>--------------------</p>

<base-layout>
<template slot='header'>
<p>标题信息1</p>
<p>标题信息2</p>
</template>
<p>主要内容1</p>
<p>主要内容2</p>
<template slot='footer'>
<p>底部信息信息1</p>
<p>底部信息信息2</p>
</template>
</base-layout>
</div>

Vue.component('base-layout', {
template: `
<div>
<header>
<slot name='header'></slot>
</header>
<main>
<slot></slot>
</main>
<footer>
<slot name='footer'></slot>
</footer>
</div>
`
});

var vm = new Vue({
el: '#app',
data: {
}
});

作用域插槽

学习链接

学习链接

分而治之

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
<fruit-list :list='list'>	
<template slot-scope='slotProps'>
<strong v-if='slotProps.info.id==3' class="current">{{slotProps.info.name}}</strong>
<span v-else>{{slotProps.info.name}}</span>
</template>
</fruit-list>

Vue.component('fruit-list', {
props: ['list'],
template: `
<div>
<li :key='item.id' v-for='item in list'>
<slot :info='item'>{{item.name}}</slot>
</li>
</div>
`
});

var vm = new Vue({
el: '#app',
data: {
list: [{
id: 1,
name: 'apple'
},{
id: 2,
name: 'orange'
},{
id: 3,
name: 'banana'
}]
}
);

购物车案例

组件化布局!!!
有收获!!

分-合

先定义模板-类似vue组件-分
定义组件,组件加载模板,使用模板-类似index.vue-合
使用组件


在组件内定义数据,传入子组件


删除,子组件,触发父组件,父组件删除


数量更新
some用法
输入框触发 blur事件
blur触发父方法-触发事件过程传递参数
父方法,根据传值找到位置,改变参数


按钮操作数量
触发事件,传递参数-sub、add
父方法中,根据传递的值判断,查找位置,修改数据


总结
一个总组件,其他分组件,分合
触发事件,传递参数,查找位置,修改数据

——–


Promise