您的位置:首页 > Web前端 > Vue.js

Vue.js(三) 指令(Directive)

2018-12-18 17:22 489 查看
版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/vbirdbest/article/details/85015403

一: 指令(Directive):

  • 是Vue对HTML标签新增加的、拓展的属性(也称之为特性), 这些属性不属于标准的html属性,只有Vue认为是有效的,能够处理它。

  • 指令的职责是当表达式的值改变时,将其产生的连带影响,响应式(Reactive)地作用于 DOM。也就是双向数据绑定。

  • 指令以"v-"作为前缀,Vue提供的指令有:v-model、v-if、v-else、v-else-if、v-show、v-for、v-bind、v-on、v-text、v-html、v-pre、v-cloak、v-once等。指令也可以自定义

  • 指令既可以用于普通标签也可以用在

    <template>
    标签上。

  • 指令的值是表达式,指令的值和在文本插值表达式{{ }} 的写法是一样的。

二:ES6 语法扫盲

ES5和ES6中增加了很多语法糖,就是出一些新的语法,来简化之前的写法,如果你不了解ES6看现代前端的代码,你会发现有很多语法都没有见过。

2.1 省略分号

在ES6中每行代码结尾都可以省略分号;

let foo = 'bar'

2.2 对象函数

JavaScript中对象使用{ } 表示,使用key作为属性名,使用value作为属性值。其中属性值可以是任意类型(数值、布尔、数组、字符串、对象),也可以是函数类型。函数分为命名函数和匿名函数(没有名称的函数),当对象中的属性值是函数类型,通常以函数名作为key,匿名函数作为value,这是标准的形式,也有简化的写法,就是省去function关键字,也不需要属性名,直接就是函数名() { }, 这种方式和标准形式其实是一样的,只不过写法看起来奇怪 。

{
// key: value 标准形式,key为函数名,value为匿名函数
foo: function() {
// function body
},
// 简化形式
bar() {
// function body
}
}

理解了ES6对象中的函数简化语法再去看Vue脚本中导出的对象的data函数语法看起来就明白了。只不过data函数有返回值,返回值是一个对象。

<script>
export default {
data () {
return {
username: ''
}
}
}
</script>

2.3 对象中使用变量值来添加属性

在JavaScript中对象是以大括号{ }形式定义的,对象中包括多个 属性名和属性值,其中属性名和属性值都冒号分隔。

在ES6中可以省略属性名,直接使用属性值,当只有属性值时此时的属性名就是属性值对应的变量名。

// 传统定义对象,属性名:属性值
{
username: 'mengday',
age: 20
}

// ES6中使用属性值,省略属性名,此时属性名就是该变量名
var age = 20
{
username: 'mengday',
age
}

2.4 箭头函数

箭头函数是匿名函数的另一种新写法,在写法上箭头函数比匿名函数更加简洁,类似于其它语言中的代码块的概念。箭头函数使用箭头=>将函数的参数和函数体分开。

箭头函数的参数列表同样使用小括号()括住,同时支持可变参数(可变参数就是数组),可变参数在参数名前使用三个点表示(例如 …args), 如果参数列表只有一个参数可以省略(), 如果参数列表没有参数不能省略()

函数体同样使用一对大括号{}括住, 如果函数体只有一行代码可以直接省略掉大括号语法和return关键字。如果是返回的一个js对象{},此时的函数体大括号不能省略。

(arg1, arg2, arg...) => {
// function body
}
<script type="text/javascript">

// 匿名函数 使用function关键字
let double = function (x) {
if (x > 0) {
return x * x;
}

return x;
}

// 箭头函数
let double2 = x => {
if (x > 0) {
return x * x;
}

return x;
}

// 一个参数,省略参数列表中的小括号(),
// 方法体一行代码, 省略方法体中的大括号{}, 省略return关键字
let double3 = x => x > 0 ? x * x : x;

// 无参
let pai = () => 3.15

// 可变参数
let sum = (x, y, ...others) => {
let sum = x+y;
for (let i = 0; i < others.length;i++){
sum += others[i];
}
return sum;
}

// 返回一个对象即使函数体是一行代码也不能省略大括号{}
let obj = x => {{foo: x}}

// 注意:this在箭头函数中使用是指的是Window对象,不是指所在的对象
let foo = {
name: 'mengday',
sayHello () {
console.log(this.name)
}
}
foo.sayHello()
</script>

2.5 解构

解构:就是将一个对象或者数组结构解开拆开, 其实就是其它语言中的元组tuple类型

<script type="text/javascript">
var obj = {age: 28, name: 'mengday', sayHello () { return '解构语法' }}
var {age, name, sayHello} = obj
// 28
console.log(age)
// mengday
console.log(name)
// 解构语法
console.log(sayHello())

var array = [1, 2, 3];
var [a, b, c] = array;
// 1
console.log(a)
// 2
console.log(b)
// 3
console.log(c)
</script>

2.6 对象展开运算符 …

对象展开运算符就是将将没有匹配到解构的值都赋值给对象展开运算符对应的变量。

语法:在变量前使用三个点

<script type="text/javascript">
let arr = [1,2,3]
// 1 2 3
console.log(...arr)

console.log('-------------')

let { x, y, ...z } = { x: 1, y: 2, a: 3, b: 4 };
// 1
console.log(x)
// 2
console.log(y)
// {a: 3, b: 4}
console.log(z)
</script>

2.7 数组常用的几个方法

array api : http://www.runoob.com/jsref/jsref-obj-array.html

  • push() : 向数组的末尾添加一个或更多元素,并返回新的长度
  • filter() : 检测数值元素,并返回符合条件所有元素的数组。
  • splice(index, ): 从数组中添加或删除元素。 index 必需。规定从何处添加/删除元素。该参数是开始插入和(或)删除的数组元素的下标,必须是数字。
  • howmany 必需。规定应该删除多少元素。必须是数字,但可以是 “0”。如果未规定此参数,则删除从 index 开始到原数组结尾的所有元素。
<script type="text/javascript">
var array = [10, 26, 18, 17]
// [10, 26, 18, 17, 30]
array.push(30)
var result = array.filter((item, index) => {
console.log(index)
return item >= 18
})
// [26, 18, 39]
console.log(result)
// [10, 26, 18, 30]
array.splice(3, 1)
console.log(array)
</script>

三:指令示例

1. v-text 和 v-html

用于更新绑定元素中的内容,相当于jQuery的text()方法,等同于JS的text属性。v-text="foo"和插值表达式{{ foo }} 效果是完全一样的。

注意:v-text会把变量的值作为普通文本,即使变量的值是html也会作为普通文本来展示,如果要作为html元素显示需要使用v-html, 类似于jQuery的html()方法

<template>
<div>
v-text: <span v-text="foo"></span><br/>
v-html: <span v-html="foo"></span><br/>
{{}}: <span>{{foo}}</span>
</div>
</template>

<script>
export default {
name: 'HelloWorld',
data () {
return {
foo: "<font color='red'>Hello Vue!</font>"
}
}
}
</script>

2. v-if 、v-else-if、v-else

  • v-if=“bool表达式”:根据表达式的值的真假条件渲染元素,true则显示,false则不显示。v-if 可单独使用也可和v-else-if、v-else结合使用。
  • v-else-if: 充当 v-if 的“else-if 块”,可以连续使用。必须紧跟在带 v-if 或者 v-else-if 的元素之后。
  • v-else: 表示 v-if的“else块,v-else元素必须紧跟在带v-if或者v-else-if的元素的后面。
<template>
<div>
<span v-if="orderStatus == 0">春天</span>
<span v-else-if="orderStatus == 1">夏天</span>
<span v-else-if="orderStatus == 2">秋天</span>
<span v-else>冬天</span>
</div>
</template>

<script>
export default {
name: 'HelloWorld',
data () {
return {
orderStatus: 2
}
}
}
</script>

3. v-show

用于根据表达式的值的真假条件显示隐藏元素,v-show 只是简单地切换元素的CSS属性display。v-show表达式为true, 则设置style=“display: none;” 为false不设置样式。

<template>
<div>
v-if="{{isAdmin}}" <span v-if="isAdmin">删除</span> <br>
v-show="{{isAdmin}}" <span v-show="isAdmin">删除</span> <br>
v-show="{{!isAdmin}}" <span v-show="!isAdmin">删除</span>
</div>
</template>

<script>
export default {
name: 'HelloWorld',
data () {
return {
isAdmin: false
}
}
}
</script>

v-if 和 v-show 的区别:

可以看到当v-if="false"时整个span元素就没有被加载,而v-show=“false”会渲染span元素,只不过该元素被隐藏起来了(style=“display: none;”), 从视觉的效果来说两者是完全一样的,都不能看到。一般来说,v-if 有更高的切换开销,而 v-show 有更高的初始渲染开销。因此,如果需要非常频繁地切换,则使用 v-show 较好;如果在运行时条件很少改变,则使用 v-if 较好。如果不考虑性能两个用哪个都行。

4. v-bind:属性名

动态绑定html中的属性值,因v-bind比较常用提供了缩写语法,此指令可以省略"v-bind",直接使用 “:属性名”。

v-bind:后面可以跟任意标准的HTML属性如href、class、style、display等任意属性。

<template>
<div>
<button v-bind:disabled="isAdmin">删除</button> <br>
<a :href="url">删除</a> <br>
<span :class="{red: isAdmin, size: !isAdmin}">:class</span>
<div :style="{ color: orangeColor, fontSize: fontSize + 'px' }">v-bind:style</div> <br>
</div>
</template>

<script>
export default {
name: 'HelloWorld',
data () {
return {
isAdmin: true,
url: 'http://www.baidu.com',
orangeColor: 'orange',
fontSize: 30
}
}
}
</script>

<style scoped>
.red {
color: red;
}

.size {
font-size:3.75em
}
</style>

v-bind:class 用法稍微特别 {样式:布尔表达式} 当布尔表达式为true的时候就使用样式。

5. v-for

用于遍历数组或者对象(遍历对象的所有属性,在遍历对象时,是按Object.keys()的结果遍历,但是不能保证它的结果在不同的JavaScript引擎下是一致的),可以使用in或者of方式,也可以使用(item, index), 其中index从0开始的索引, 在使用v-for是最好提供:key, 2.2.0+ 的版本里,当在组件中使用 v-for 时,:key 现在是必须的。v-for也可以遍历一个区间范围内的数字,如 1到10

<template>
<div>
<ul>
<li v-for="item in programes" :key="item.value">{{ item.text }}</li>
</ul>
<hr>
<ul>
<li v-for="item of programes" :key="item.value">{{ item.text }}</li>
</ul>
<hr>
<ul>
<li v-for="(item, index) in programes" :key="item.value">{{ index + "-" +  item.text }}</li>
</ul>
<hr>

<ul>
<li v-for="(item, index) in programes" :key="item.value">{{ index + "-" +  item.text }}</li>
</ul>
<hr>
<ul>
<li v-for="(value, key) in user" :key="user.id">{{ key }}={{ value }}</li>
</ul>
<hr>
<ul>
<li v-for="(value, key, index) in user" :key="user.id">{{index}} : {{ key }}={{ value }}</li>
</ul>
<span v-for="n in 10">{{ n }} </span>
<hr>
</div>
</template>

<script>
export default {
name: 'HelloWorld',
data () {
return {
programes: [
{value: 0, text: 'Java'},
{value: 1, text: 'iOS'},
{value: 2, text: 'Vue'},
],
user: {
id: 1,
username: 'mengday',
age: 28,
gender: '男'
}
}
}
}
</script>

6. v-model

v-model: 表单输入和应用状态之间的双向绑定。v-model 会忽略所有表单元素的 value、checked、selected 特性的初始值而总是将Vue实例的数据作为数据来源。你应该通过JavaScript在组件的data选项中声明初始值。

修饰符: 使用.操作符追加在指令后面,修饰符的作用是对值进行再次处理。

  • . trim : 去掉输入的值的首尾空格
  • .number 将输入的值转为数值类型(一般情况下data中初始化的数据为空文本"",此时是字符串类型,如果输入了值就会转为数值类型)
  • .lazy 懒更新,默认情况下当数据发生改变(oninput事件)时就会更改model,使用lazy是当光标离开表单时才会更新model
<template>
<div>
<form>
<input v-model="username" value="root" type="text" placeholder="请输入用户名"/><br>
<input v-model.trim="password" value="root" type="text" placeholder="请输入密码"/><br>
<input v-model.number="age" type="text" placeholder="请输入年龄"/><br>
<input v-model.lazy="hobby" type="text" placeholder="爱好"/><br>
{{username.split(" ")}}
</form>
</div>
</template>

<script>
export default {
name: 'HelloWorld',
data () {
return {
username: 'a d m i n',
password: '',
age: '',
hobby: ''
}
}
}
</script>

7. v-on:事件名称

v-on用于监听事件,如click、change、keyup等事件,由于比较常用有一个简写写法用@符号代替"v-on:", 在ES6中方法调用如果没有参数可以省略小括号,而方法的声明写在methods里。

.once 表示事件只会触发一次

<template>
<div>
<button v-on:click="handleClick">Click Me</button>
<button @click="handleClick">click me</button>
<button @click.once="handleClick">once</button>
</div>
</template>

<script>
export default {
name: 'HelloWorld',
data () {
return {

}
},
methods: {
handleClick() {
console.log('click me')
}
}
}
</script>

Vue允许为v-on在监听键盘事件(keyup、keydown、keypress)时添加按键修饰符, 修饰符可以是键盘按钮对应的keyCode,也可以keyCode对应的别名。可以通过

Vue.config.keyCodes.别名 = keyCode值
来自定义keyCode对应的别名。Vue也提供好了一些常用的别名

  • .enter
  • .tab
  • .delete (捕获“删除”和“退格”键)
  • .esc
  • .space
  • .up
  • .down
  • .left
  • .right
// 在main.js中注册一个全局的键盘按钮别名
Vue.config.keyCodes.f1 = 112

HelloVue.vue

<template>
<div>
<input type="button" @keyup.13="handleEnter(13)" value="13"> <br>
<input type="button" @keyup.enter="handleEnter('Enter')" value="Enter"> <br>
<input type="button" @keyup.f1="handleEnter('F1')" value="F1"> <br>
</div>
</template>

<script>
export default {
name: 'HelloWorld',
methods: {
handleEnter (value) {
console.log(value)
}
}
}
</script>

注意:需要光标先选中触发事件的按钮,然后再按快捷键才有效,13 就是enter键的码值keyCode,F1 对应的keyCode是112。这些值可以通过 键盘按钮keycode的对照表来查看。

四:自定义指令

1. Vue.directive(‘指令名称’, { }) )

除了核心功能默认内置的指令 (v-model 和 v-show),Vue 也允许注册自定义指令。

可以全局注册(注册在根Vue上 Vue.directive(‘指令名称’, { }) )也可以局部注册(在某个Vue导出选项中使用directives属性注册),在元素上通过"v-指令名称" 来使用自定义指令。

使用自定义指令的场景:需要对普通 DOM 元素进行底层操作。

2. 钩子函数

  • bind:只调用一次,指令第一次绑定到元素时调用。在这里可以进行一次性的初始化设置。

  • inserted:被绑定元素插入父节点时调用 (仅保证父节点存在,但不一定已被插入文档中)。

  • update:所在组件的VNode 更新时调用,但是可能发生在其子VNode更新之前。指令的值可能发生了改变,也可能没有。但是你可以通过比较更新前后的值来忽略不必要的模板更新。

  • componentUpdated:指令所在组件的VNode及其子VNode 全部更新后调用。

  • unbind:只调用一次,指令与元素解绑时调用。

3. 钩子函数参数

指令钩子函数会被传入以下参数:

  • el:指令所绑定的元素,可以用来直接操作 DOM 。
  • binding:一个对象,包含以下属性: 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 API 来了解更多详情。
  • oldVnode:上一个虚拟节点,仅在 update 和 componentUpdated 钩子中可用。
  • 除了 el 之外,其它参数都应该是只读的,切勿进行修改。如果需要在钩子之间共享数据,建议通过元素的 dataset 来进行。

    4. 根据用户权限隐藏菜单或者按钮

    main.js

    var user = {
    permissions: ["user:add", "user:view"]
    }
    
    Vue.directive('hasPermission', {
    inserted: function(el, binding) {
    var permission = binding.value
    var isContain = false
    for(var i = 0; i < user.permissions.length; i++) {
    if(user.permissions[i] === permission) {
    isContain = true
    break;
    }
    }
    
    if(!isContain) {
    el.parentNode.removeChild(el);
    }
    }
    })

    HelloWorld.vue

    <template>
    <div>
    <button v-hasPermission="'user:add'">添加用户</button>
    <button v-hasPermission="'user:del'">删除用户</button>
    <button v-hasPermission="'user:update'">修改用户</button>
    <button v-hasPermission="'user:view'">查看用户</button>
    </div>
    </template>
    
    <script>
    export default {
    name: 'HelloWorld',
    data () {
    return {
    
    }
    }
    }
    </script>

    内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
    标签: