鼠标事件
@keyup.13="key" methods: { key: function (e) { this.msg = ''; console.log(66666); }, },
点击(单击):@click="方法名" ;
双击 : @dblclick="方法名" ;
鼠标按下: @mousedown="方法名" ;
鼠标抬起: @mouseup="方法名" ;
鼠标移动: @mousemove="方法名" ;
鼠标离开: @mouseleave=“方法名” ;
鼠标离开: @mouseout=“方法名” ;
*mouseleave和mouseout的区别在于mouseout有冒泡行为。
鼠标进入: @mouseenter="方法名" ;
鼠标进入: @mouseover="方法名" 。
*mouseenter和mouseover的区别在于mouseover有冒泡行为。
鼠标滚轮事件
滚轮滚动: @mousewheel="方法名" 。
键盘事件
@keydown(键盘按下时触发)
@keyup(键盘弹起)
@keypress(键盘按住时触发)
获取按键的键码 e.keyCode
方法后面跟keyCode值可以直接绑定键盘按键
@keyup.13 按回车键
@keyup.enter 回车
@keyup.up 上键
@keyup.down 下键
@keyup.left 左键
@keyup.right 右键
@keyup.delete 删除键
@keyup.space 空格
指令
- 本质就是自定义属性
- Vue中指定都是以 v- 开头
v-cloak 防止页面加载时出现闪烁
- 防止页面加载时出现闪烁问题
/*
1、通过属性选择器 选择到 带有属性 v-cloak的标签 让他隐藏
/
[v-cloak]{
/ 元素隐藏 */
display: none;
}
{{msg}}
v-text 将数据填充到标签
-
v-text指令用于将数据填充到标签中,作用于插值表达式类似,但是没有闪动问题
-
如果数据中有HTML标签会将html标签一并输出
-
注意:此处为单向绑定,数据对象上的值改变,插值会发生变化;但是当插值发生变化并不会影响数据对象的值
{{msg}}
v-html 将数据填充到标签,可以将HTML片段填充
-
用法和v-text 相似 但是他可以将HTML片段填充到标签中
-
可能有安全问题, 一般只在可信任内容上使用 v-html,永不用在用户提交的内容上
-
它与v-text区别在于v-text输出的是纯文本,浏览器不会对其再进行html解析,但v-html会将其当html标签解析后输出。
<p>{{message}}</p> <!-- 输出:<span>通过双括号绑定</span> --> <p v-text="text"></p> <!-- 输出:<span>html标签在渲染的时候被源码输出</span> --> </div> <script> let app = new Vue({ el: "#app", data: { message: "<span>通过双括号绑定</span>", html: "<span>html标签在渲染的时候被解析</span>", text: "<span>html标签在渲染的时候被源码输出</span>", } }); </script>
v-pre 显示原始信息跳过编译过程
-
显示原始信息跳过编译过程
-
跳过这个元素和它的子元素的编译过程。
-
一些静态的内容不需要编译加这个指令可以加快渲染
<span v-pre>{{ this will not be compiled }}</span> <!-- 显示的是{{ this will not be compiled }} --> <span v-pre>{{msg}}</span> <!-- 即使data里面定义了msg这里仍然是显示的{{msg}} -->
v-once 执行一次性的插值
-
执行一次性的插值【当数据改变时,插值处的内容不会继续更新】
<!-- 即使data里面定义了msg 后期我们修改了 仍然显示的是第一次data里面存储的数据即 Hello Vue.js --> <span v-once>{{ msg}}</span>
双向数据绑定
- 当数据发生变化的时候,视图也就发生变化
- 当视图发生变化的时候,数据也会跟着同步变化
v-model 输入框中内容改变的时候, 页面上的msg 会自动更新
-
v-model是一个指令,限制在 、、、components中使用
{{msg}}当输入框中内容改变的时候, 页面上的msg 会自动更新
mvvm
- MVC 是后端的分层开发概念; MVVM是前端视图层的概念,主要关注于 视图层分离,也就是说:MVVM把前端的视图层,分为了 三部分 Model, View , VM ViewModel
- m model
- 数据层 Vue 中 数据层 都放在 data 里面
- v view 视图
- Vue 中 view 即 我们的HTML页面
- vm (view-model) 控制器 将数据和视图层建立联系
- vm 即 Vue 的实例 就是 vm
v-on 绑定事件
- 用来绑定事件的
- 形式如:v-on:click 缩写为 @click;
v-bind 响应地更新 HTML 属性
-
v-bind 指令被用来响应地更新 HTML 属性
-
v-bind:href 可以缩写为 :href;
分支结构
v-if 使用场景
v-for 和 v-if 不建议用在一起
当 v-for 和 v-if 处于同一个节点时,v-for 的优先级比 v-if 更高,这意味着 v-if 将分别重复运行于每个 v-for 循环中。如果要遍历的数组很大,而真正要展示的数据很少时,这将造成很大的性能浪费这种场景建议使用 computed,先对数据进行过滤
-
1- 多个元素 通过条件判断展示或者隐藏某个元素。或者多个元素
-
2- 进行两个视图之间的切换
如果flag为true则显示,false不显示!
<div v-if="type === 'A'"> A </div> <!-- v-else-if紧跟在v-if或v-else-if之后 表示v-if条件不成立时执行--> <div v-else-if="type === 'B'"> B </div> <div v-else-if="type === 'C'"> C </div> <!-- v-else紧跟在v-if或v-else-if之后--> <div v-else> Not A/B/C </div>
v-show 和 v-if的区别
- v-show本质就是标签display设置为none,控制隐藏
- v-show只编译一次,后面其实就是控制css,而v-if不停的销毁和创建,故v-show性能更好一点。
- v-if是动态的向DOM树内添加或者删除DOM元素
- v-if切换有一个局部编译/卸载的过程,切换过程中合适地销毁和重建内部的事件监听和子组件
循环结构
v-for
-
用于循环的数组里面的值可以是对象,也可以是普通元素
- {{ item.message }}
})
-
不推荐同时使用 v-if 和 v-for
-
当 v-if 与 v-for 一起使用时,v-for 具有比 v-if 更高的优先级。
<!-- 循环结构-遍历对象 v 代表 对象的value k 代表对象的 键 i 代表索引 ---> <div v-if='v==13' v-for='(v,k,i) in obj'>{{v + '---' + k + '---' + i}}</div>
- key 的作用
-
key来给每个节点做一个唯一标识
-
key的作用主要是为了高效的更新虚拟DOM
- ...
v-model 获取单选框中的值
hobby 的值就是选中的值,我们只需要实时监控他的值就可以了
<input type="checkbox" id="ball" value="1" v-model='hobby'
v-model 获取下拉框和文本框中的值
occupation 的值就是选中的值,我们只需要实时监控他的值就可以了
-->
<!-- multiple 多选 -->
<select v-model='occupation' multiple>
<option value="0">请选择职业...</option>
<option value="1">教师</option>
<option value="2">软件工程师</option>
<option value="3">律师</option>
</select>
表单修饰符
- .number 转换为数值
- 注意点:
- 当开始输入非数字的字符串时,因为Vue无法将字符串转换成数值
- 所以属性值将实时更新成相同的字符串。即使后面输入数字,也将被视作字符串。
- .trim 自动过滤用户输入的首尾空白字符
- 只能去掉首尾的 不能去除中间的空格
- .lazy 将input事件切换成change事件
- .lazy 修饰符延迟了同步更新属性值的时机。即将原本绑定
输入改变事件改成失去焦点事件 在 input 事件的同步逻辑转变为绑定在 change 事件上
-
在失去焦点 或者 按下回车键时才更新
<!--自动过滤用户输入的首尾空白字符 --> <input v-model.trim="msg"> <!-- 在“change”时而非“input”时更新 --> <input v-model.lazy="msg" >
##自定义指令
- 内置指令不能满足我们特殊的需求
- Vue允许我们自定义指令
Vue.directive 注册全局指令
Vue.directive('ff', {
inserted: function (el) {
el.focus();
},
});
带参数 Vue.directive 注册全局指令 带参数
<input type="text" v-vv="color" />
Vue.directive('vv', {
inserted: function (el, binding) {
console.log(binding);
el.style.backgroundColor = binding.value;
},
});
自定义指令局部指令
- 局部指令,需要定义在 directives 的选项 用法和全局用法一样
- 局部指令只能在当前组件里面使用
- 当全局指令和局部指令同名时以局部指令为准
<input type="text" v-color='msg'>
<input type="text" v-focus>
<script type="text/javascript">
/*
自定义指令-局部指令
*/
var vm = new Vue({
el: '#app',
data: {
msg: {
color: 'red'
}
},
//局部指令,需要定义在 directives 的选项
directives: {
color: {
bind: function(el, binding){
el.style.backgroundColor = binding.value.color;
}
},
focus: {
inserted: function(el) {
el.focus();
}
}
}
});
</script>
自定义指令
- 内置指令不能满足我们特殊的需求
- Vue允许我们自定义指令
Vue.directive 注册全局指令
<!--
使用自定义的指令,只需在对用的元素中,加上'v-'的前缀形成类似于内部指令'v-if','v-text'的形式。
-->
<input type="text" v-focus>
<script>
// 注意点:
// 1、 在自定义指令中 如果以驼峰命名的方式定义 如 Vue.directive('focusA',function(){})
// 2、 在HTML中使用的时候 只能通过 v-focus-a 来使用
// 注册一个全局自定义指令 v-focus
Vue.directive('focus', {
// 当绑定元素插入到 DOM 中。 其中 el为dom元素
inserted: function (el) {
// 聚焦元素
el.focus();
}
});
new Vue({
el:'#app'
});
</script>
Vue.directive 全局指令带参数
自定义指令-带参数
<input type="text" v-color='msg'>
<script type="text/javascript">
/*
自定义指令-带参数
bind - 只调用一次,在指令第一次绑定到元素上时候调用
*/
Vue.directive('color', {
// bind声明周期, 只调用一次,指令第一次绑定到元素时调用。在这里可以进行一次性的初始化设置
// el 为当前自定义指令的DOM元素
// binding 为自定义的函数形参 通过自定义属性传递过来的值 存在 binding.value 里面
bind: function(el, binding){
// 根据指令的参数设置背景色
// console.log(binding.value.color)
el.style.backgroundColor = binding.value.color;
}
});
var vm = new Vue({
el: '#app',
data: {
msg: {
color: 'blue'
}
}
});
</script>
自定义指令局部指令
-
局部指令,需要定义在 directives 的选项 用法和全局用法一样
-
局部指令只能在当前组件里面使用
-
当全局指令和局部指令同名时以局部指令为准
计算属性 computed
-
模板中放入太多的逻辑会让模板过重且难以维护 使用计算属性可以让模板更加的简洁
-
计算属性是基于它们的响应式依赖进行缓存的
-
computed比较适合对多个变量或者对象进行处理后返回一个结果值,也就是数多个变量中的某一个值发生了变化则我们监控的这个值也就会发生变化
{{reverseString}}{{reverseString}}{{reverseMessage()}}{{reverseMessage()}}
侦听器 watch 响应数据的变化
-
使用watch来响应数据的变化
-
一般用于异步或者开销较大的操作
-
watch 中的属性 一定是data 中 已经存在的数据
-
当需要监听一个对象的改变时,普通的watch方法无法监听到对象内部属性的改变,只有data中的数据才能够监听到变化,此时就需要deep属性对对象进行深度监听
名:姓:{{fullName}}<script type="text/javascript"> /* 侦听器 */ var vm = new Vue({ el: '#app', data: { firstName: 'Jim', lastName: 'Green', // fullName: 'Jim Green' }, //watch 属性 定义 和 data 已经 methods 平级 watch: { // 注意: 这里firstName 对应着data 中的 firstName // 当 firstName 值 改变的时候 会自动触发 watch firstName: function(val) { this.fullName = val + ' ' + this.lastName; }, // 注意: 这里 lastName 对应着data 中的 lastName lastName: function(val) { this.fullName = this.firstName + ' ' + val; } } }); </script>
过滤器 --用于一些常见的文本格式化
-
Vue.js允许自定义过滤器,可被用于一些常见的文本格式化。
-
过滤器可以用在两个地方:双花括号插值和v-bind表达式。
-
过滤器应该被添加在JavaScript表达式的尾部,由“管道”符号指示
-
支持级联操作
-
过滤器不改变真正的data,而只是改变渲染的结果,并返回过滤后的版本
-
全局注册时是filter,没有s的。而局部过滤器是filters,是有s的
<div id="app"> <input type="text" v-model='msg'> <!-- upper 被定义为接收单个参数的过滤器函数,表达式 msg 的值将作为参数传入到函数中 --> <div>{{msg | upper}}</div> <!-- 支持级联操作 upper 被定义为接收单个参数的过滤器函数,表达式msg 的值将作为参数传入到函数中。 然后继续调用同样被定义为接收单个参数的过滤器 lower ,将upper 的结果传递到lower中 --> <div>{{msg | upper | lower}}</div> <div :abc='msg | upper'>测试数据</div> </div>
过滤器中传递参数
<div id="box">
<!--
filterA 被定义为接收三个参数的过滤器函数。
其中 message 的值作为第一个参数,
普通字符串 'arg1' 作为第二个参数,表达式 arg2 的值作为第三个参数。
-->
{{ message | filterA('arg1', 'arg2') }}
</div>
<script>
// 在过滤器中 第一个参数 对应的是 管道符前面的数据 n 此时对应 message
// 第2个参数 a 对应 实参 arg1 字符串
// 第3个参数 b 对应 实参 arg2 字符串
Vue.filter('filterA',function(n,a,b){
if(n<10){
return n+a;
}else{
return n+b;
}
});
new Vue({
el:"#box",
data:{
message: "哈哈哈"
}
})
</script>
vue的生命周期
从开始创建、初始化数据、编译模板、挂载Dom、渲染→更新→渲染、卸载等一系列过程
简单讲是一个组件从开始到最后消亡所经历的各种状态,就是一个组件的生命周期
一个vue实例在创建过程中调用的几个生命周期钩子。
1.beforeCreate 在实例初始化之后
说明:在实例初始化之后,数据观测 (data observer) 和 event/watcher 事件配置之前被调用 注意:此时,无法获取 data中的数据、methods中的方法
2.created 发送ajax请求来对已经构建完毕的vue对象
这是一个常用的生命周期,可以调用methods中的方法、改变data中的数据。最常见的就是发送ajax请求来对已经构建完毕的vue对象的静态属性进行一些初始化。
3.beforeMount 在挂载开始之前被调用
4.mounted 实例已经挂载到页面
此时,vue实例已经挂载到页面中,可以获取到el中的DOM元素,进行DOM操作
5.beforeUpdate 数据更新时调用,
发生在虚拟 DOM 重新渲染和打补丁之前。你可以在这个钩子中进一步地更改状态,这不会触发附加的重渲染过程。
6.updated 组件 DOM 已经更新,
所以你现在可以执行依赖于 DOM 的操作。
7.beforeDestroy 实例销毁之前调用。
在这一步,实例仍然完全可用。使用场景:实例销毁之前,执行清理任务,比如:清除定时器等
8.destroyed 实例销毁后调用
说明:Vue 实例销毁后调用。调用后,Vue 实例指示的所有东西都会解绑定,所有的事件监听器会被移除,所有的子实例也会被销毁。 ————————————————
原文链接:blog.csdn.net/weixin_3908…
生命周期详解
- 事物从出生到死亡的过程
- Vue实例从创建 到销毁的过程 ,这些过程中会伴随着一些函数的自调用。我们称这些函数为钩子函数
常用的 钩子函数
beforeCreate 在实例初始化之后,数据观测和事件配置之前被调用 此时data 和 methods 以及页面的DOM结构都没有初始化 什么都做不了
created 在实例创建完成后被立即调用此时data 和 methods已经可以使用 但是页面还没有渲染出来
beforeMount 在挂载开始之前被调用 此时页面上还看不到真实数据 只是一个模板页面而已
mounted el被新创建的vm.$el替换,并挂载到实例上去之后调用该钩子。 数据已经真实渲染到页面上 在这个钩子函数里面我们可以使用一些第三方的插件
beforeUpdate 数据更新时调用,发生在虚拟DOM打补丁之前。 页面上数据还是旧的
updated 由于数据更改导致的虚拟DOM重新渲染和打补丁,在这之后会调用该钩子。 页面上数据已经替换成最新的
beforeDestroy 实例销毁之前调用
destroyed 实例销毁后调用
数组变异方法
- 在 Vue 中,直接修改对象属性的值无法触发响应式。当你直接修改了对象属性的值,你会发现,只有数据改了,但是页面内容并没有改变
- 变异数组方法即保持数组方法原有功能不变的前提下对其进行功能拓展
push() 往数组最后面添加一个元素
push() 往数组最后面添加一个元素,成功返回当前数组的长度
pop() 删除数组的最后一个元素
pop() 删除数组的最后一个元素,成功返回删除元素的值 #### shift() 删除数组的第一个元素 shift() 删除数组的第一个元素,成功返回删除元素的值
unshift() 往数组最前面添加一个元素
unshift() 往数组最前面添加一个元素,成功返回当前数组的长度
splice() 删除元素,删除元素下标-个数-删除替换的值
splice() 有三个参数,第一个是想要删除的元素的下标(必选),第二个是想要删除的个数(必选),第三个是删除 后想要在原位置替换的值
sort() 数组按照字符编码默认从小到大排序
sort() 使数组按照字符编码默认从小到大排序,成功返回排序后的数组
reverse() 将数组倒序,成功返回倒序后的数组
reverse() 将数组倒序,成功返回倒序后的数组
替换数组
- 不会改变原始数组,但总是返回一个新数组
filter() 方法创建一个新的数组
filter filter() 方法创建一个新的数组,新数组中的元素是通过检查指定数组中符合条件的所有元素。
concat() 方法用于连接两个或多个数组
concat concat() 方法用于连接两个或多个数组。该方法不会改变现有的数组
slice() 方法可从已有的数组中返回选定的元素
slice slice() 方法可从已有的数组中返回选定的元素。该方法并不会修改数组,而是返回一个子数组
动态数组响应式数据
- Vue.set(a,b,c) 让 触发视图重新更新一遍,数据动态起来
- a是要更改的数据 、 b是数据的第几项、 c是更改后的数据
reduce遍历循环
init是后面的0,item是当前属性
var arr = [1, 2, 3, 4];
var cc = 0;
cc = arr.reduce((init, item) => {
return (init += item);
}, 0);
console.log(cc);
注册全局组件
组件注意事项
- 组件参数的data值必须是函数同时这个函数要求返回一个对象
- 组件模板必须是单个根元素
- 组件模板的内容可以是模板字符串
//<my-comp></my-comp>
Vue.component('my-comp', {
data: function () {
return {
msg: 'HelloWorld',
};
},
template: ``,
});
注册局部组件
局部注册
- 只能在当前注册它的vue实例中使用
<div id="app">
<my-component></my-component>
</div>
<script>
// 定义组件的模板
var Child = {
template: '<div>A custom component!</div>'
}
new Vue({
components: {
'my-component': Child
}
})
</script>
组件之间传值
父组件向子组件传值
- 父组件发送的形式是以属性的形式绑定值到子组件身上。
- 然后子组件用属性props接收
- 在props中使用驼峰形式,模板中需要使用短横线的形式字符串形式的模板中没有这个限制
:title='ptitle'
props: ['title'],
template: '<div>{{title}}</div>'
子组件向父组件传值
- 子组件用$emit()触发事件
- $emit() 第一个参数为 自定义的事件名称 第二个参数为需要传递的数据
- 父组件用v-on 监听子组件的事件
在组件里面
父
@enlarge-text='handle($event)'
子
@click='$emit("enlarge-text", 5)'
兄弟之间的传递
- 兄弟之间传递数据需要借助于事件中心,通过事件中心传递数据
- 提供事件中心 var hub = new Vue()
- 传递数据方,通过一个事件触发hub.$emit(方法名,传递的数据)
- 接收数据方,通过mounted(){} 钩子中 触发hub.$on()方法名
- 销毁事件 通过hub.$off()方法名销毁之后无法进行传递数据
<div id="app">
<div>父组件</div>
<div>
<button @click='handle'>销毁事件</button>
</div>
<test-tom></test-tom>
<test-jerry></test-jerry>
</div>
<script type="text/javascript" src="js/vue.js"></script>
<script type="text/javascript">
/*
兄弟组件之间数据传递
*/
//1、 提供事件中心
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(){
//2、传递数据方,通过一个事件触发hub.$emit(方法名,传递的数据) 触发兄弟组件的事件
hub.$emit('jerry-event', 2);
}
},
mounted: function() {
// 3、接收数据方,通过mounted(){} 钩子中 触发hub.$on(方法名
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(){
//2、传递数据方,通过一个事件触发hub.$emit(方法名,传递的数据) 触发兄弟组件的事件
hub.$emit('tom-event', 1);
}
},
mounted: function() {
// 3、接收数据方,通过mounted(){} 钩子中 触发hub.$on()方法名
hub.$on('jerry-event', (val) => {
this.num += val;
});
}
});
var vm = new Vue({
el: '#app',
data: {
},
methods: {
handle: function(){
//4、销毁事件 通过hub.$off()方法名销毁之后无法进行传递数据
hub.$off('tom-event');
hub.$off('jerry-event');
}
}
});
</script>
组件插槽
匿名插槽
<div id="app">
<my-comp>ff</my-comp>
</div>
Vue.component('my-comp', {
data: function () {
return {
msg: 'HelloWorld',
};
},
template: `<div>
<h2>嘟嘟嘟</h2>
<slot>默认</slot>
</div>`,
});
具名插槽
<div id="app">
<my-comp>
<p slot="header">666</p>
</my-comp>
</div>
</body>
<script src="./js/vue.js"></script>
<script>
Vue.component('my-comp', {
template: `<div>
<header>
<slot name="header">默认111</slot>
</header>
</div> `,
});
var vm = new Vue({
el: '#app',
data: { msg: '' },
methods: {},
});
</script>
作用域插槽
-
父组件对子组件加工处理
-
既可以复用子组件的slot,又可以使slot内容不一致
<div id="app"> <!-- 1、当我们希望li 的样式由外部使用组件的地方定义,因为可能有多种地方要使用该组件, 但样式希望不一样 这个时候我们需要使用作用域插槽 --> <fruit-list :list='list'> <!-- 2、 父组件中使用了<template>元素,而且包含scope="slotProps", slotProps在这里只是临时变量 ---> <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> </div> <script type="text/javascript" src="js/vue.js"></script> <script type="text/javascript"> /* 作用域插槽 */ Vue.component('fruit-list', { props: ['list'], template: ` <div> <li :key='item.id' v-for='item in list'> ### 3、 在子组件模板中,<slot>元素上有一个类似props传递数据给组件的写法msg="xxx", ### 插槽可以提供一个默认内容,如果如果父组件没有为这个插槽提供了内容,会显示默认的内容。 如果父组件为这个插槽提供了内容,则默认的内容会被替换掉 <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' }] } }); </script>