vue.js了解篇3(指令)

目录
  1. 指令
    内置指令
    1. v-show 指令
    2. v-if 指令
    3. v-on 指令
    4. v-html指令、v-text 指令
    5. v-bind指令
    6. v-model指令
    7. 插值
  2. 自定义指令

前言

Vue.js模版语法基于 HTML模板语法(能被遵循规范的浏览器和HTML解析器 解析)的同时,允许开发者声明式地将 DOM 绑定至底层 Vue 实例的数据(底层实现:Vue 将模板编译成虚拟 DOM渲染函数,将数据渲染到html元素中)。也可以不使用模板,直接使用render渲染函数。

1. 指令(内置指令)
指令
    以v-开头加上指令名
参数    
    在指令后面以:指明,如:v-bind:href="url"
修饰符    
    在参数后面以.指明,如:v-on:submit.prevent="onSubmit"
部分指令可缩写
  <a v-bind:href="url"></a>
  缩写为
  <a :href="url"></a>

  <a v-on:click="doSomething"></a>
  缩写为
  <a @click="doSomething"></a>
  1. v-show 指令
是否展示
  不支持 <template> 元素
  本质:始终被渲染,只是简单地切换元素的CSS属性display来实现显示和隐藏。

示例

<h1 v-show="ok">Hello!</h1>
  1. v-if 指令
是否插入元素
  本质:根据条件选择是否渲染,为true创建为false销毁

  v-if 有更高的切换开销,而 v-show 有更高的初始渲染开销。因此,如果需要非常频繁地切换,则使用 v-show;反之则使用 v-if。
  v-if 是惰性的:如果在初始渲染时条件为假,则什么也不做——直到条件第一次变为真时,才会开始渲染条件块。
  v-for 具有比 v-if 更高的优先级(不推荐同时使用 v-if 和 v-for)。
  1. v-on 指令(用于事件监听)
事件修饰符
  <!-- 不响应 该单击事件冒泡(只执行当前元素的点击事件,不向父控件冒泡)(默认:事件是向父控件不断冒泡) -->
  <a v-on:click.stop="doThis"></a>
  <!-- 提交事件不再重载页面(阻止默认的事件,只执行自定义事件) -->
  <form v-on:submit.prevent="onSubmit"></form>
  <!-- 修饰符可以串联(顺序很重要) 
v-on:click.prevent.self 会阻止所有的点击,而 v-on:click.self.prevent 只会阻止对元素自身的点击
 -->
  <a v-on:click.stop.prevent="doThat"></a>
  <!-- 只有修饰符 -->
  <form v-on:submit.prevent></form>
  <!-- 添加事件侦听器时使用事件捕获模式,当点击内部子元素时 先处理带有capture的自定义事件,然后才交由内部子元素进行处理 -->
  <div v-on:click.capture="doThis">...</div>
  <!-- 只当事件在该元素本身(如果是子元素触发则不回调)触发时触发回调 -->
  <div v-on:click.self="doThat">...</div>
  <!-- click 事件只能点击一次,2.1.4版本新增 -->
  <a v-on:click.once="doThis"></a>
  <!-- 滚动时将会立即触发,而不会等待 `onScroll` 完成才触发,不要把 .passive 和 .prevent 一起使用,因为 .prevent 将会被忽略 -->
  <div v-on:scroll.passive="onScroll">...</div>
按键修饰符(电脑端)
  .enter
  .tab
  .delete (捕获 "删除" 和 "退格" 键)
  .esc
  .space
  .up
  .down
  .left (鼠标左键)
  .right(鼠标右键)
  2.1.0 新增 修饰键(与普通键不同,需先按住修饰键再按住普通键才触发)
    .ctrl
    .alt
    .shift
    .meta 注意:在 Mac 系统键盘上,meta 对应 command 键 (⌘)。在 Windows 系统键盘 meta 对应 Windows 徽标键 (⊞)。在 Sun 操作系统键盘上,meta 对应实心宝石键 (◆)。
  2.5.0 新增  .exact 精确控制
    <!-- 即使 Alt 或 Shift 被一同按下时也会触发 -->
    <button @click.ctrl="onClick">A</button>
    <!-- 有且只有 Ctrl 被按下的时候才触发 -->
    <button @click.ctrl.exact="onCtrlClick">A</button>
    <!-- 没有任何系统修饰符被按下的时候才触发 -->
    <button @click.exact="onClick">A</button>
  2.2.0 新增 鼠标按钮修饰键
    .left
    .right
    .middle
可以通过全局config.keyCodes对象自定义按键修饰符别名
  // 可以使用 `v-on:keyup.f1`
  Vue.config.keyCodes.f1 = 112

例1:
<!-- 只有在 keyCode 是 13 时调用 vm.submit() -->
<input v-on:keyup.13="submit">
同上(记住所有的 keyCode 比较困难,所以 Vue 为最常用的按键提供了别名)
<input v-on:keyup.enter="submit">
缩写
<input @keyup.enter="submit">

例2:
<p><!-- Alt + C -->
<input @keyup.alt.67="clear">
<!-- Ctrl + Click -->
<div @click.ctrl="doSomething">Do something</div>
2.6.0新增动态参数
<a v-on:[eventName]="doSomething"> ... </a>

  动态参数预期会求出一个字符串,异常情况下值为 null。null会移除绑定,任何其它非字符串类型的值都将会触发一个警告。
  动态参数表达式有一些语法约束,因为某些字符,如空格和引号,放在 HTML attribute 名里是无效的。
  动态参数不要使用大写字符来命名,浏览器会把 attribute名全部强制转为小写导致响应失效。

示例1(直接修改属性,不适合复杂的逻辑)

<div id="app">
  <button v-on:click="counter += 1">增加 1</button>
  <p>这个按钮被点击了 {{ counter }} 次。</p>
</div>
 
<script>
new Vue({
  el: '#app',
  data: {
    counter: 0
  }
})
</script>

示例2(调用方法)

<div id="app">
   <!-- `greet` 是在下面定义的方法名 -->
  <button v-on:click="greet">Greet</button>
  <button v-on:click="say('hi')">Say hi</button>
  <button v-on:click="warn('hello', $event)">hello</button>
</div>
 
<script>
var app = new Vue({
  el: '#app',
  data: {
    name: 'Vue.js'
  },
  // 在 `methods` 对象中定义方法
  methods: {
    greet: function (event) {
      // `this` 在方法里指当前 Vue 实例
      alert('Hello ' + this.name + '!')
      // `event` 是原生 DOM 事件
      if (event) {
          alert(event.target.tagName)
      }
    },
    say: function (message) {
      alert(message)
    }
    warn: function (message, event) {
      // 现在我们可以访问原生事件对象
      if (event) event.preventDefault()
      alert(message)
    }
  }
})
// 也可以用 JavaScript 直接调用方法
app.greet() // -> 'Hello Vue.js!'
</script>
  1. v-html指令、v-text 指令

v-html指令

嵌入html内容

注意:
  1. 更新元素的 innerHTML,不会作为 Vue 模板进行编译(例如:scoped属性无效) 。
  2. 容易导致XSS 攻击,永不用在用户提交的内容上。
示例

<div id="app">
    <div v-html="message"></div>
</div>
...
<script>
new Vue({
  el: '#app',
  data: {
    message: '<h1>Hello World</h1>'
  }
})
</script>

v-text 指令

会覆盖元素中原来的内容 

<h1 v-text="site">22</h1>
  1. v-bind指令(属性绑定)
v-bind:组件属性

特殊属性:样式绑定v-bind:class、v-bind:style。在将 v-bind 用于 class 和 style 时,Vue.js 做了专门的增强,表达式结果的类型除了字符串之外,还可以是对象或数组。

示例1

<a v-bind:href="url">...</a>

示例2 (2.6.0以上新增动态属性,其他指令也如此)

<a v-bind:[attributeName]="url"> ... </a>

1、attributeName可以是data中的一个属性,null时移除该绑定
2、<a v-bind:['foo' + bar]="value"> ... </a>无效,不能包含空格和引号

示例3 (缩写)

<!-- 缩写 -->
<a :href="url">...</a>
等价于
<!-- 完整语法 -->
<a v-bind:href="url">...</a>

样式绑定 示例1

<!--结果:<div class="active"></div>-->
<div v-bind:class="{ active: isActive }"></div>
<script>
new Vue({
  el: '#app',
  data: {
    isActive: true
  }
})
</script>

<style>
.active {
    width: 100px;
    height: 100px;
    background: green;
}
</style>

样式绑定 示例2(和普通css属性共存)

<!--结果:<div class="static active text-danger"></div>-->
<div id="app">
  <div class="static" v-bind:class="{ active: isActive, 'text-danger': hasError }">
  </div>
</div>
<script>
new Vue({
  el: '#app',
  data: {
    isActive: true,
    hasError: false
  }
})
</script>

<style>
.active {
    width: 100px;
    height: 100px;
    background: green;
}
.text-danger {
    background: red;
}
</style>

样式绑定 示例3(对象)

<div id="app">
  <div v-bind:class="classObject"></div>
  <div v-bind:class="{active:true}"></div>
</div>

<script>
new Vue({
  el: '#app',
  data: {
    classObject: {
      active: true,
      'text-danger': true
    }
  }
})
</script>


<style>
.active {
    width: 100px;
    height: 100px;
    background: green;
}
.text-danger {
    background: red;
}
</style>

样式绑定 示例4(计算属性)

<div id="app">
  <div v-bind:class="classObject"></div>
</div>

<script>
new Vue({
  el: '#app',
  data: {
  isActive: true,
  error: null
  },
  computed: {
    classObject: function () {
      return {
        active: this.isActive && !this.error,
        'text-danger': this.error && this.error.type === 'fatal',
      }
    }
  }
})

<style>
.active {
    width: 100px;
    height: 100px;
    background: green;
}
.text-danger {
    background: red;
}
</style>

样式绑定 示例5(数组)

<div id="app">
    <div v-bind:class="[activeClass, errorClass]"></div>
</div>
<script>
new Vue({
  el: '#app',
  data: {
    activeClass: 'active',
    errorClass: 'text-danger'
  }
})
</script>
<style>
.active {
    width: 100px;
    height: 100px;
    background: green;
}
.text-danger {
    background: red;
}
</style>


数组里放对象
<div v-bind:class="[{ active: isActive }, errorClass]"></div>

样式绑定 示例6(三元表达式)

<div id="app">
    <div v-bind:class="[errorClass ,isActive ? activeClass : '']"></div>
</div>
<script>
new Vue({
  el: '#app',
  data: {
    isActive: true,
    activeClass: 'active',
    errorClass: 'text-danger'
  }
})
</script>
<style>
.active {
    width: 100px;
    height: 100px;
    background: green;
}
.text-danger {
    background: red;
}
</style>

样式绑定 示例7(v-bind:style---多个)

<!--结果:<div style="color: green; font-size: 30px;">Hello World</div>-->
<div id="app">
    <div v-bind:style="{ color: activeColor, fontSize: fontSize + 'px' }">Hello World</div>
</div>
<script>
new Vue({
  el: '#app',
  data: {
    activeColor: 'green',
    fontSize: 30
  }
})
</script>

样式绑定 示例8(v-bind:style---对象)

<div id="app">
  <div v-bind:style="styleObject">Hello World</div>
</div>
<script>
new Vue({
  el: '#app',
  data: {
    styleObject: {
      color: 'green',
      fontSize: '30px'
    }
  }
})
</script>

示例9(v-bind:style---数组)

<div id="app">
  <div v-bind:style="[baseStyles, overridingStyles]">hello</div>
</div>
<script>
new Vue({
  el: '#app',
  data: {
    baseStyles: {
      color: 'green',
      fontSize: '30px'
    },
    overridingStyles: {
      'font-weight': 'bold'
    }
  }
})
</script>
2.3以上
<div :style="{ display: ['-webkit-box', '-ms-flexbox', 'flex'] }"></div>
只会渲染数组中最后一个被浏览器支持的值。在本例中,如果浏览器支持不带浏览器前缀的 flexbox,那么就只会渲染 display: flex。

示例10 (组件)

Vue.component('my-component', {
  template: '<p class="foo bar">Hi</p>'
})
<my-component class="baz boo"></my-component>

最终渲染(组件上使用 class 属性时,这些 class 将被添加到该组件的根元素上面。这个元素上已经存在的 class 不会被覆盖。)
<p class="foo bar baz boo">Hi</p>
  1. v-model指令
获取用户输入
    用来在 input、select、text、checkbox、radio 等表单控件元素上创建双向数据绑定,根据表单上的值自动更新绑定的元素的值。


本质:
  负责监听用户的输入事件以更新数据,并对一些极端场景进行一些特殊处理

注意:
  1. v-model 会忽略所有表单元素的 value、checked、selected 特性的初始值而总是将 Vue 实例的数据作为数据来源。应该通过 JavaScript 在组件的 data 选项中声明初始值。
  2. v-model 不会在输入法组合文字过程中得到更新。如果想处理这个过程,使用 input 事件。
  3. 对于单选按钮,复选框及选择框的选项,v-model 绑定的值通常是静态字符串 (对于复选框也可以是布尔值)
  4. 在默认情况下,v-model 在每次 input 事件触发后将输入框的值与数据进行同步 (除了上述输入法组合文字时)。可以添加 lazy 修饰符,从而转变为使用 change 事件进行同步
    <!-- 在“change”时而非“input”时更新 -->
    <input v-model.lazy="msg" >
  5. 即使在 type="number" 时,HTML 输入元素的值也总会返回字符串。如果这个值无法被 parseFloat() 解析,则会返回原始的值。如果想自动将用户的输入值转为数值类型,可以给 v-model 添加 number 修饰符:
    <input v-model.number="age" type="number">
  6.如果要自动过滤用户输入的首尾空白字符,可以给 v-model 添加 trim 修饰符
    <input v-model.trim="msg">
<input v-model="searchText">

等价于

<input
  v-bind:value="searchText"
  v-on:input="searchText = $event.target.value"
>

示例1

<div id="app">
    <p>{{ message }}</p>
    <input v-model="message">
</div>
<script>
new Vue({
  el: '#app',
  data: {
    message: 'Runoob!'
  }
})
</script>

示例2 (多行文本)

<span>Multiline message is:</span>
<p style="white-space: pre-line;">{{ message }}</p>
<br>
<textarea v-model="message" placeholder="add multiple lines"></textarea>

示例3 (复选框)

<div id='example-3'>
  <input type="checkbox" id="jack" value="Jack" v-model="checkedNames">
  <label for="jack">Jack</label>
  <input type="checkbox" id="john" value="John" v-model="checkedNames">
  <label for="john">John</label>
  <input type="checkbox" id="mike" value="Mike" v-model="checkedNames">
  <label for="mike">Mike</label>
  <br>
  <span>Checked names: {{ checkedNames }}</span>
</div>

ew Vue({
  el: '#example-3',
  data: {
    checkedNames: []
  }
})
<input
  type="checkbox"
  v-model="toggle"
  true-value="yes"
  false-value="no"
>
里的 true-value 和 false-value 特性并不会影响输入控件的 value 特性,因为浏览器在提交表单时并不会包含未被选中的复选框。如果要确保表单中这两个值中的一个能够被提交,(比如“yes”或“no”),请换用单选按钮。

示例4 (单选)

<div id="example-4">
  <input type="radio" id="one" value="One" v-model="picked">
  <label for="one">One</label>
  <br>
  <input type="radio" id="two" value="Two" v-model="picked">
  <label for="two">Two</label>
  <br>
  <span>Picked: {{ picked }}</span>
</div>

new Vue({
  el: '#example-4',
  data: {
    picked: ''
  }
})

示例5 (选择框)

<div id="example-5">
  <select v-model="selected">  <!--加 multiple 为多选-->
    <option disabled value="">请选择</option>
    <option>A</option>
    <option>B</option>
    <option>C</option>
  </select>
  <span>Selected: {{ selected }}</span>
</div>

new Vue({
  el: '...',
  data: {
    selected: ''
  }
})

如果 v-model 表达式的初始值未能匹配任何选项,<select> 元素将被渲染为“未选中”状态。在 iOS 中,这会使用户无法选择第一个选项。因为这样的情况下,iOS 不会触发 change 事件。推荐像上面这样提供一个值为空的禁用选项。
<select v-model="selected">
  <option v-for="option in options" v-bind:value="option.value">
    {{ option.text }}
  </option>
</select>
<span>Selected: {{ selected }}</span>

new Vue({
  el: '...',
  data: {
    selected: 'A',
    options: [
      { text: 'One', value: 'A' },
      { text: 'Two', value: 'B' },
      { text: 'Three', value: 'C' }
    ]
  }
})
  1. 插值

以下三种数据绑定都支持JavaScript 表达式(不能是语句)

  1. 文本 (数据绑定最常见的形式)
<span>Message: {{ msg }}</span>
当msg属性发生改变后,插值处的内容都会自动更新

注意:
  1. 双大括号会将数据解释为普通文本,而非 HTML 代码。会对html代码进行转义,避免脚本注入。
  2. 不能作用在 HTML元素的属性上
  3. v-once(一次性地插值,当数据改变时,插值处的内容不会更新)
      <span v-once>这个将不会改变: {{ msg }}</span>
  1. html片段
<span v-html="rawHtml"></span>

注意:
  站点上动态渲染的任意 HTML 可能会非常危险,因为它很容易导致 XSS 攻击。请只对可信内容使用 HTML 插值,绝不要对用户提供的内容使用插值
  1. v-bind (绑定html属性的值)
<div v-bind:disabled="isDis"></div>

注意:
  1. 当参数类型是bool类型时,只有true才会生效。null、undefined 或 false则 disabled 特性不会被包含在渲染出来的 <div> 元素中(即div元素上不会有disabled这个属性)。
  2. 如果isDis该字段包含了html代码,会进行转义,避免了脚本注入。
示例

<div id="app">
    {{5+5}}<br>
    {{ ok ? 'YES' : 'NO' }}<br>
    {{ message.split('').reverse().join('') }}
    <div v-bind:id="'list-' + id">Hello</div>
    <p>{{ message }}</p>    数据绑定
    <img title="{{message}}" alt="{{message}}" v-attr="src: message">
</div>
...
<script>
new Vue({
  el: '#app',
  data: {
    ok: true,
    message: 'ssbb',
    id : 1
  }
})
</script>

模板表达式都被放在沙盒中,只能访问全局变量的一个白名单,如 Math 和 Date 。不应该在模板表达式中试图访问用户定义的全局变量。
2. 自定义指令
  1. 两种注册方式

通过以下示例(v-focus指令 功能-在页面加载时,元素获得焦点)了解2种注册方式。

注册全局指令

<div id="app">
    <p>页面载入时,input 元素自动获取焦点:</p>
    <input v-focus>
</div>
 
<script>
// 注册一个全局自定义指令 v-focus
Vue.directive('focus', {
  // 当绑定元素插入到 DOM 中。
  inserted: function (el) {
    // 聚焦元素
    el.focus()
  }
})
// 创建根实例
new Vue({
  el: '#app'
})
</script>

注册局部指令

<div id="app">
  <p>页面载入时,input 元素自动获取焦点:</p>
  <input v-focus>
</div>
 
<script>
// 创建根实例
new Vue({
  el: '#app',
  directives: {  // 存放自定义指令
    // 注册一个局部的自定义指令 v-focus
    focus: {
      // 指令的定义
      inserted: function (el) {
        // 聚焦元素
        el.focus()
      }
    }
  }
})
</script>
  1. 钩子(生命周期的某阶段会执行相应方法)
函数(可选)

  1、bind: 
    指令第一次绑定到元素时调用【只调用一次】
    用于:进行一次性的初始化设置
  2、inserted: 
    被绑定元素插入父节点时调用 (父节点存在即可调用,不必存在于文档中)
  3、update: 
    被绑定元素所在模板更新时调用,而不论绑定值是否变化。可通过比较更新前后的绑定值,可以忽略不必要的模板更新。可能发生在其子 VNode 更新之前。
  4、componentUpdated: 
    被绑定元素所在模板更新后调用(指令所在组件的 VNode 及其子 VNode 全部更新后调用)
  5、unbind: 
    指令与元素解绑时调用【只调用一次】
函数参数

  1、el(指令所绑定的元素,可直接操作DOM)
  2、binding(一个对象,包含以下属性)
      name: 指令名,不包括 v- 前缀。
      value: 指令的绑定值, 例如: v-my-directive="1 + 1", value 的值是 2。
      oldValue: 指令绑定的前一个值(仅在 update 和 componentUpdated 钩子中可用)。无论值是否改变都可用。
      expression: 绑定值的表达式或变量名。 例如 v-my-directive="1 + 1" , expression 的值是 "1 + 1"。
      arg: 传给指令的参数。例如 v-my-directive:foo, arg 的值是 "foo"。
      modifiers: 一个包含修饰符的对象。 例如: v-my-directive.foo.bar, 修饰符对象 modifiers 的值是 { foo: true, bar: true }。
  3、vnode(Vue 编译生成的虚拟节点)
  4、oldVnode(上一个虚拟节点,仅在 update 和 componentUpdated 钩子中可用)。

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

示例1

<div id="app"  v-runoob:hello.a.b="message">
</div>
 
<script>
Vue.directive('runoob', {
  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: '#app',
  data: {
    message: 'Hello World!'
  }
})
</script>

示例2

<div id="baseexample">
  <p>Scroll down the page</p>
  <p v-pin="200">Stick me 200px from the top of the page</p>
</div>
Vue.directive('pin', {
  bind: function (el, binding, vnode) {
    el.style.position = 'fixed'
    el.style.top = binding.value + 'px'
  }
})
new Vue({
  el: '#baseexample'
})

===============
===============
动态
<!--
指令的参数可以是动态的
v-mydirective:[argument]="value"
-->

<div id="dynamicexample">
  <h3>Scroll down inside this section ↓</h3>
  <p v-pin:[direction]="200">I am pinned onto the page at 200px to the left.</p>
</div>
Vue.directive('pin', {
  bind: function (el, binding, vnode) {
    el.style.position = 'fixed'
    var s = (binding.arg == 'left' ? 'left' : 'top')
    el.style[s] = binding.value + 'px'
  }
})
new Vue({
  el: '#dynamicexample',
  data: function () {
    return {
      direction: 'left'
    }
  }
})

示例3(指令简写)

不需要其他钩子函数时可简写

Vue.directive('hello', function (el, binding) {  // 在 bind 和 update 时触发相同行为,而不关心其它的钩子
  // 设置指令的背景颜色
  el.style.backgroundColor = binding.value.color
})

示例4(可传入JavaScript 表达式)

<div id="app">
    <div v-runoob="{ color: 'green', text: 'Hello World!' }"></div>
</div>
 
<script>
Vue.directive('runoob', function (el, binding) {
    // 简写方式设置文本及背景颜色
    el.innerHTML = binding.value.text
    el.style.backgroundColor = binding.value.color
})
new Vue({
  el: '#app'
})
</script>
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • 这篇笔记主要包含 Vue 2 不同于 Vue 1 或者特有的内容,还有我对于 Vue 1.0 印象不深的内容。关于...
    云之外阅读 10,466评论 0 29
  • 一、了解Vue.js 1.1.1 Vue.js是什么? 简单小巧、渐进式、功能强大的技术栈 1.1.2 为什么学习...
    蔡华鹏阅读 8,658评论 0 3
  • Vue 实例 属性和方法 每个 Vue 实例都会代理其 data 对象里所有的属性:var data = { a:...
    云之外阅读 6,666评论 0 6
  • 1. Vue 实例 1.1 创建一个Vue实例 一个 Vue 应用由一个通过 new Vue 创建的根 Vue 实...
    王童孟阅读 4,606评论 0 2
  • 主要还是自己看的,所有内容来自官方文档。 介绍 Vue.js 是什么 Vue (读音 /vjuː/,类似于 vie...
    Leonzai阅读 8,677评论 0 25