使用
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