9.21
按键修饰符
@keyup.按键1的按键修饰符 = “方法1”
@keyup.按键1键码 = “方法1”
触发按键1时,调用方法1
Vue自带的按键修饰符(键码自己查询):.enter .tab .delete .esc .space .up .down .left .right
自定义全局按键修饰符样例:
Vue.config.keyCodes.f2 = 113; 此时,@keyup.f2等效于@keyup.113(113为f2的键码)
Vue的ajax语句
get
this.$http.get('地址').then( function(result){console.log(成功)}, function(result){console.log(失败)}) this.$http.get('地址' ).thin(result => {})
post
this.$http.post('地址',{ 数据 },{ 数据类型 }).then( function(result){console.log(成功)}, function(result){console.log(失败)}) this.$http.post('地址',{ 数据 },{ 数据类型 } ).thin(result => {})
jsonp
this.$http.jsonp('地址').then( function(result){console.log(成功)}, function(result){console.log(失败)}) this.$http.jsonp('地址' ).thin(result => {})
请求地址的根域名可以通过全局配置,同时每次单独发起http请求的时候,请求的url路径应该以相对路径开头,前面不能带/,否则不会启用根路径做拼接
this.$http.get('http://vue.studyit.io/api/delprodlist...')... === Vue.http.options.root = 'http://vue.studyit.io/'; ... this.$http.get('api/delprodlist...')... ...
post请求第三个参数——数据类型可以通过全局启用,则其范围内的post请求的第三个参数可以不写
this.$http.post('地址' , { 数据 } , { emulateJSON: true}) === Vue.http.options.emulateJSON = true; ... this.$http.post('地址', { 数据 })... ...
样例
<body> <div id="app"> <input type="text" v-model="name"> <input type="button" value="添加" @click="add"> </div> </body> <script> var vm = new Vue({ el: "#app", data: {name: ""}, methods: { add(){ this.$http.post('http://vue.studyit.io/api/addprodlist' , { name: this.name } , { emulateJSON: true} ).thin(result => { if(result.body.status === 0){alert("添加成功!");} else{alert("添加失败!");} }) } } }) </script>
动画
-
使用过渡类名制作动画
.v-enter{状态1}
.v-leave-to{状态2}
.v-enter-active{动作1}
.v-leave-active{动作2}
<transition>元素</transition>
transition元素是Vue官方提供的
使用动画时,用transition元素把需要被动画控制的元素包裹起来
具体过程:- 元素出现前为状态1(包括偏移位置)
- 元素出现时,为动作1(包括时间段之类的)
- 元素消失前为状态2
- 元素消失时,为动作2
.v-move{...}
为元素出场时的动作
修改v-前缀
.my-enter{状态1}
.my-leave-to{状态2}
.my-enter-active{动作1}
.my-leave-active{动作2}
<transition name="my">元素</transition>
上述代码效果与之前的代码一致 -
animate(第三方类)实现动画
前提:引入animate.css
样例1:
<transition
enter-active-class="animated bounceIn"
leave-active-class="animated bounceOut" >
<h3 v-if="flag">这是一个h3</h3>
</transition>
bounceIn、bounceOut为css文件中绑定的入场、出场动作样例2:
<transition
enter-active-class="bounceIn"
leave-active-class="bounceOut" :duration="200" >
<h3 v-if="flag" class="animated">这是一个h3</h3>
</transition>
出入场时间为200毫秒,其余与样例1一致样例3:
<transition
enter-active-class="bounceIn"
leave-active-class="bounceOut"
:duration="{ enter: 200 , leave: 400 }">
<h3 v-if="flag" class="animated">这是一个h3</h3>
</transition>
入场时间为200毫秒,出场时间为400毫秒,其余与样例1一致 -
使用钩子函数
使用过渡类名与animate都要有一个出场入场的动作
而使用钩子函数可以只有一个入场的动作
样例:
<transition
@before-enter="beforeEnter"
@enter="enter"
@after-enter="afterEnter">
<div class="ball" v-if="flag"></div>
</transition>
before-enter绑定的函数为动画开始之前
enter绑定的函数为动画动作、时间等
after-enter绑定的函数为动画完成之后三者绑定的函数的第一个参数为执行动画的dom元素,是一个元素的js dom对象
对应的函数样例:var vm = new Vue({ el: "#app", data: {flag: false}, methods: { beforeEnter(el){ el.style.transform = "translate(0,0)" }, enter(el, done){ el.offsetWidth; el.style.transform = "translate(150px,450px)" el.style.transition = "all 1s ease" done() }, afterEnter(el){ this.flag=!this.flag } } })
el.offsetWidth;
enter函数中的这句话没有实际的作用,但是不写动画效果不会出现过程
可以认为该语句强制动画刷新
另:el.offsetLeft(上下左右)或el.offsetHeight都行done()
enter函数中的done,其实就是afterEnter函数,即done为afterEnter函数的引用
done函数为必须的函数,否则enter函数和afterEnter函数之间就会出现延迟 -
列表动画
<transition-group appear tag="ul">
<li v-for="(item , i) in list" :key="item.id" @click="del(i)">
{{item.id }} --- {{ item.name }}
</li>
</transition-group>
在实现列表的过渡的时候,如果需要过渡元素,是通过v-for循环渲染出来的,不能使用transition包裹,需要使用transitionGroup(作为标签时写作transition-group)
如果要为v-for循环创建的元素设置动画,必须为每一个元素设置:key属性
组件
1.创建组件的方式:
-
使用Vue.extend和Vue.component来创建全局的Vue组件
var com1 = Vue.extend({
template: '<h3>这是使用Vue.extend创建的组件</h3>'
})
使用Vue.component(‘组件的名称’,创建出来的组件模板对象(即Vue.extend对象))
Vue.component('myCom',com1);
Vue.component('mycom',com1);
上述可简写为:
Vue.component('myCom',Vue.extend({ template: '<h3>这是使用Vue.extend创建的组件</h3>' }));
通过template属性,指定了组件要展示的HTML结构
如果使用Vue.component定义全局组件的时候,组件名称使用了驼峰命名,则在引用组件的时候,需要把大写的驼峰改为小写的驼峰,同时在两个单词之间,使用-链接
如果不使用驼峰,则直接拿名称来使用即可
即第一个引用时为:<my-com></my-com>
即第二个引用时为:
<mycom></mycom>
-
省略Vue.extend
Vue.component('myCom2',{template: '<h3>这是使用Vue.extend创建的组件</h3>'})
-
在被控制的app外面,使用template元素,定义组件的HTML模板结构
<template id="tmp1">
<div>
<h1>这个测试的h1文本</h1>
</div>
</template>
Vue.component('mycom3',{template: '#tmp1'})
ps:论哪种方式创建出来的组件,组件的template属性指向的模板内容,必须有且只能有唯一的一个根元素
即'<h3></h3><h3></h3>'
不行,需要改为'<div><h3></h3><h3></h3></div>'
2.组件中的data和methods:
Vue.component('com',{ template: '<div><button @click="add">自增</button><h3>{{count}}</h3></div>', data: function () { return { count: 0 }; }, methods: { add(){ this.count ++ } } })
组件可以有自己的data数据
组件中的data和实例中的data不一样,实例中的data可以为一个对象,但是组件中的data必须是一个方法
组件中的data除了必须是一个方法之外,这个方法的内部,还必须返回一个对象才行
组件中data数据的使用方式和实例中的一样
若data返回的对象为一个全局的对象变量,那么该组件被调用多次时,数据是共通的
3.组件的切换方式:
- 使用v-if和绑定事件切换
- 使用component标签
<component :is="comName"></component>
Vue提供了 component ,来展示对应的名称的组件
component 是一个占位符, :is 属性,可以用来指定要展示的组件的名称(comName为对应要展示的组件的名称,为字符串)
样例:<body> <div id="app"> <a href="" @click.prevent="comName='login'">登录</a> <a href="" @click.prevent="comName='register'">注册</a> <component :is="comName"></component> </div> </body> <script> Vue.component('login',{template: '<h3>登录组件</h3>'}) Vue.component('register',{template: '<h3>注册组件</h3>'}) var vm = new Vue({ el: "#app", data: { flag: false, comName: '' } }) </script>
- 组件切换动画
.v-enter,.v-leave-to{opacity: 0;transform: translateX(80px);} .v-enter-active,.v-leave-active{transition: all 0.5s ease;} <transition mode="out-in"> <component :is="comName"></component> </transition>
作业:
- 组件有哪几种定义方式
- 使用Vue.extend定义组件模板对象,再通过Vue.component定义组件
- 直接使用Vue.component定义组件模板对象
- 在被Vue控制的div外荣国template标签(含id)定义一个组件模板(html格式),再通过Vue.component定义组件(通过id锁定组件模板)
- 组件和template的区别是什么
template只是组件模板,是单纯的字符串,而组件是将template解析成为HTML格式的代码,并可以被调用 - 为什么组件的data必须是一个function
- 为了可以返回一个对象,这样组件在被多次调用时,各个组件获取的数据就不会一样
- 创建一个vm对象,带有三个子组件,在其视图中添加一个按钮,要求实现点击按钮三组件轮流切换效果
<body> <div id="app"> <button @click="change">切换</button> <component :is="comName"></component> </div> </body> <script> var vm = new Vue({ el: "#app", data: { count: 1, comName: '' }, methods: { change(){ if(this.count == 3) this.comName = 'com3'; else if(this.count == 2) this.comName = 'com2'; else this.comName = 'com1'; this.count %= 3; this.count++; } }, components: { 'com1': {template: '<h1>这是第一大组件</h1>'}, 'com2': {template: '<h2>这是第二大组件</h2>'}, 'com3': {template: '<h3>这是第三大组件</h3>'} } }) </script>
9.19
MVVM:
M为前端数据,V为前端html结构,VM为两者的调度
零碎的属性
1.v-cloak
数据导入后,v-cloak属性会去掉
2.v-text
v-text在数据导入后才会作为纯文本显示,但会把元素原数据清空,而插值表达式({{msg}})只会替换原先的占位符
3.v-html和v-text基本一样,不过会把数据作为html文本格式显示
4.v-bind
将data中的数据作为变量使用:(绑定属性)<input type="button" value="按钮" v-bind:title="title">
v-bind会将后面的引号里的东西作为js表达式去解析
<input type="button" value="按钮" v-bind:title="title + '123'">
v-bind:可简写为 ‘:’
5.v-on(绑定事件):
v-on:可简写为@ 事件类型写在元素中,具体事件方法写在methods中<input type="button" value="按钮" v-on:click="show"> <input type="button"value="按钮" v-on:mouseover="show"> var vm = new Vue({ el: '#app', data:{ msg: '123' , msg2: '<h1>略略略</h1>', title: '这是一个title' }, methods:{ //这个methods属性中定义了当前vue实例中所有可行的方法 show: function(){ alert(123); } } })
在vm实例中,想获取data中的数据或者方法,必须通过this.数据属性名 或 this.方法名进行访问
修饰符(可以串联)
.stop 阻止冒泡
.prevent 阻止默认行为
.captrue 实现捕获触发事件的机制
.self只有通过该元素本身才会触发函数(能够阻止自身的冒牌行为)
.once 只触发一次
v-model
实现数据的双向绑定
在页面中一个更改某元素(该元素调用msg),会使所有相关元素(同样调用msg)随之改变
只能运用于表单元素
input(radio,text,address,email。。。) select checkbox textarea
vue中样式的使用
用数组的方式引用class
<h1 :class="['red','thin']">这是一个很大的h1</h1>
在数组中使用三元表达式
<h1 :class="['red','thin',flag?'active':'']">这是一个很大的h1</h1>
ps:若flag(vm的data中的数据)为真,则引用class active
在数组中使用对象代替三元表达式
<h1 :class="['red','thin',{'active':flag}]">这是一个很大的h1</h1>
直接使用对象(对象引号可带可不带,属性值为标识符,可以用vm中的数据代替)
<h1 :class="{red: true,thin: true,italic: flag,active: flag}">这是一个很大的h1</h1>
vue使用内联样式
以对象形式使用
<h1 :style="{color:'red','font-weight':200}">这是一个很大的h1</h1>
在vm的data中绑定样式,在元素中引用
<h1 :style="styleobj1">这是一个很大的h1</h1>
在2的基础上,元素使用数组引用多个样式
<h1 :style="[styleobj1,styleobj2]">这是一个很大的h1</h1>
v-for
1.迭代数组
<p v-for="(item, i) in list">索引值:{{i}} --- 每一项:{{item}}</p> data:{ list:[1,2,3,4,5,6] }
2.迭代对象
<p v-for="(item, i) in list">id:{{item.id}} --- 每一项:{{item.name}} --- 索引:{{i}}</p> data:{ list:[ {id:1,name:'zs1'}, {id:2,name:'zs2'}, {id:3,name:'zs3'}, {id:4,name:'zs4'} ] }
3.迭代对象数组
<p v-for="(val, key,i) in user">值:{{ val }} --- 键:{{ key }} --- 索引:{{ i }}</p> data:{ user:{ id:1, name:'zs1', gender:'男' } }
4.迭代数字 eg:
循环到10,从1开始<p v-for="count in 10">这是第 {{count}} 次循环</p>
注意vue.js在2.20版本后使用对象必须有key(用于判断)
作业:
1、总结一下v-text和v-html和插值表达式的差别
插值表达式({{msg}})只会将数据作为纯文本替换原先的占位符
v-text在数据导入后才会作为纯文本显示,但会把元素原数据清空
v-html和v-text基本一样,不过会把数据作为html文本格式显示
2、完成创建一个vue对象并和id是app的div进行绑定,然后在该div中分别用插值表达式、v-text、v-html获取到vm下data中的msg的值
<body>
<div id="app">
<p v-text="msg"></p>
<p v-html="msg"></p>
</div>
</body>
<script>
var vm = new Vue({
el: '#app',
data:{
msg: "<h1>vm文本</h1>"
}
})
</script>
3、什么是MVVM模式,这样设计有什么优点
主要是为了让我们开发方便,因为MVVM提供了数据的双向绑定(由VM提供)
4、使用vue将下列data中cat记录显示插入到页面之中
<body>
<div id="app">
<p v-text="cat.name"></p>
<p v-text="cat.age"></p>
<p v-text="cat.desc"></p>
</div>
</body>
<script>
var vm = new Vue({
el: '#app',
data:{
cat: {
name: '罗小黑',
age: 18,
desc: '是一只黑色的猫'
}
}
})
</script>
5、使用vue,完成一个登陆校验功能。
<body>
<div id="app">
<input type="text" placeholder="账号" v-model="username"><br>
<input type="text" placeholder="密码" v-model="password"><br>
<input type="button" value="登录" @click="insert">
</div>
</body>
<script>
var vm = new Vue({
el: '#app',
data:{
username: "",
password: "",
userName: "zhang3",
passWord: "123456"
},
methods: {
insert(){
if(this.username != this.userName){
alert("账号错误!");
return ;
}
if(this.password != this.passWord){
alert("密码错误!");
return ;
}
window.location = "http://www.baidu.com";
}
}
})
</script>
9.20
v-if&v-show
v-if的特点是每次都会重新删除或创建元素
v-show的特点每次不会重新进行dom的删除和创建操作,只是切换了元素的display:none样式 v-if有较高的切换性能消耗
v-show有较高的初始渲染消耗 如果元素涉及到频繁的切换,最好不要使用v-if,推荐使用v-show
如果元素可能永远不会被显示出来被用户看到,则推荐使用v-if
遍历数组的新方法
1.forEach无法被中止
将对象数组list中name键包含key的所有对象添加到新的对象数组newList中 this.list.forEach(item => { if(item.name.indexOf(key) != -1){ newList.push(item); } })
2.some返回true能中止
删除一个list对象数组中id键为Id的对象,并中止循环 this.list.some((item,i)=>{ if(item.id == Id){ this.list.splice(i,1); return true; } })
3.filter能返回对象(若多个则构成一个数组),且不会被中断
获取list对象数组中name键包含key的所有对象组成的数组 return this.list.filter(item => { if(item.name.includes(key)){ return item; } })
4.findIndex寻找想找的索引index
获取list对象数组中id为Id的index var index = this.list.findIndex(item => { if(item.id == Id){ return true; } })
字符串相关方法
- indexOf
s1.indexOf(s1),若s1不存在字符串s2,返回-1,反之,返回s2的第一个字符在s1的位置(从0开始)
- includes
s1.includes(s2),若s1包含字符串s2,则返回true,反之返回false
- toString().padStart
s1.toString().padStart(maxLength,fillString) 从头,为s1填充fillString,直到长度为maxLength
- toString().padEnd
s1.toString().padEnd(maxLength,fillString) 从尾,为s1填充s2,直到长度为maxLength
- replace
s1.replace(‘s2’,‘s3’);将s1中第一个s2替换为s3
s1.replace(/s2/g,‘s3’);将s1中所有s2替换为s3
- parseInt
i = parseInt(s) 将s转化为整数i
- 拼接字符串
`${y}-${m}-${d} ${hh}:${mm}:${ss}`
等效于
y+'-'+m+'-'+d+' '+hh+':'+mm+':'+ss
过滤器
1.使用格式
{{ String | 过滤器1的名称(s1,s2,...) | 过滤器2的名称(s1,s2,...) }} 公有过滤器 Vue.filter('过滤器的名称',function(String,s1,s2,...){ //代码 }) 私有过滤器 var vm2 = new Vue({ el: '#app2', filters: { 过滤器的名称: function(String,s1,s2,...){ //代码 } } })
ps:
第一个参数固定为管道符前面传递过来的数据,即被过滤对象
过滤器调用的时候采用的是就近原则,如果私有过滤器和全局过滤器名称一致,优先私有过滤器
公有样例:
<p>{{ msg | msgFormat('疯狂','123') | test }}</p> Vue.filter('msgFormat',function(msg ,arg ,arg2){ return msg.replace(/单纯/g,arg + arg2); }) Vue.filter('test',function(msg){ return msg + "==========="; })
自定义指令
使用(暂未知可否传多个参数)
<h3 v-指令名=" 参数 " v-fontsize="30">文本</h3> 公有指令 Vue.directive('指令名',{ bind: function(el,binding){代码}, inserted: function(el){代码}, updated: function(el){代码} }) 私有指令 var vm2 = new Vue({ el: '#app2', directives: { 指令名: { bind: function(el,binding){}, inserted: function(el){}, updated: function(el){} } } })
bind方法
- 指令绑定到元素上,还没有插入dom中去时,即在内存中,还没渲染到页面时,执行,且只执行一次
- 和样式相关的操作,一般都可以放在bind中执行
inserted方法
- 元素插入到dom时,即渲染到页面后,会(只)执行一次
- 和JS行为有关的操作,最好在inserted中去执行,防止JS行为不执行
updated方法
- 当VNode更新时,会执行updated,可能会触发多次
简写操作(只有bind和updated方法时)
公有 Vue.directive('指令名',function(el,binding){}) 私有 var vm2 = new Vue({ el: '#app2', directives: { 指令名: function(el,binding){} } })
公有样例:
<h3 v-fontsize="30">xxxxxx</h3> <input type="text" v-focus> Vue.directive('focus',{ inserted: function(el){ el.focus(); } }) Vue.directive('fontsize',{ inserted: function(el,binding){ el.style.fontSize = parseInt(binding.value) + 'px'; } })
作业
- 说说几个常用的字符操作函数filter、some的差别
filter能返回对象(若多个则构成一个数组),且不会被中断
some返回true会被中断
- indexOf和includes的差别
s1.indexOf(s1),若s1不存在字符串s2,返回-1,反之,返回s2的第一个字符在s1的位置(从0开始)
s1.includes(s2),若s1包含字符串s2,则返回true,反之返回false
- 谈谈你对v-on的理解
用于绑定事件,可简写为@,绑定事件的类型需在后面写,事件函数可以加载参数
样例:<input type="button" value="按钮" v-on:click="show" @mouseover="show(参数1,参数2,...)">
@click="del(index)"
和@click="del("index")"
的差别是什么
@click=“del(index)”
绑定点击事件del,传递参数为变量index
@click=“del(“index”)”
绑定点击事件del,传递参数为字符串"index"
- 下列代码六个函数的执行顺序是什么
<div onclick="m11();" @click.capture="m12()"> <div onclick="m21();" @click.capture="m22()"> <button onclick="m31();" @click="m32()">一个按钮</button> </div> </div>
执行顺序为m12,m22,m31,m32,m21,m11
- 定义一个私有指令,使加载该指令的标签都拥有红色字体。
<body> <p v-red>123456</p> </body> <script> Vue.directive('red',{ bind: function(el,c){ el.style.color= 'red'; } }) </script>