(二)VUE指令

   指令带有前缀 v-,以表示它们是 Vue 提供的特殊特性,它们会在渲染的 DOM 上应用特殊的响应式行为。

一、文本指令

  • v-cloak:保持在元素上直到关联实例结束编译
    <style>
        [v-cloak]{
            display: none;
        }
    </style>

	<p v-cloak>{{ message }}</p>

   和 CSS 规则如 [v-cloak] { display: none } 一起用时,这个指令可以隐藏未编译的 Mustache 标签直到实例准备完毕,即解决网速慢时文本显示的闪烁问题。

  • v-text:更新元素的 textContent
	<p v-text="message">Overwritten content</p>

   v-text 指令会覆盖元素的 textContent,如果要更新部分的 textContent ,需要使用 {{ Mustache }} 插值。

  • v-html:更新元素的 innerHTML
    <div id="app" v-html="html_msg">
        <p>Overwritten content</p>
    </div>
    
    <script>
        var app = new Vue({
            el: '#app',
            data: {
                message: 'Hello Vue!',
                html_msg: '<p>Hello Vue</p>'
            },
        })
    </script>
</body>
</html>

   类似地,v-html 指令会覆盖元素的 innerHTML。

二、绑定指令

1、v-bind:

   动态地绑定一个或多个特性,或一个组件 prop 到表达式。

    <div id="app">
        <!-- 绑定一个属性 -->
        <input type="button" value="button1" v-bind:title="myTitle">
        <!-- 缩写形式:用 ":" 代替 "v-bind:" -->
        <input type="button" value="button2" :title="myTitle">
        <!-- 内联字符串拼接 -->
        <input type="button" value="button3" :title="myTitle + '123'">
    </div>

    <script>
        var app = new Vue({
            el: '#app',
            data: {
                myTitle:"This is my title."
            }
        })
    </script>

修饰符:

  • .prop - 被用于绑定 DOM 属性 (property);
  • .camel - (2.1.0+) 将 kebab-case 特性名转换为 camelCase;
  • .sync (2.3.0+) 语法糖,会扩展成一个更新父组件绑定值的 v-on 侦听器。
(1)绑定class样式

   在绑定class样式时,可以使用数组,也可以使用对象。

i、使用数组:
  • 数组中可以直接引用样式名称,但是名称要加上单引号,否则会被认为是变量;
  • 数组中也可以嵌套对象;
  • 在数组中还可以使用三元表达式,以便利用变量控制样式的显示。
ii、使用对象:
  • 在使用对象时,属性名称为样式名,属性值为控制显示的布尔值。
iii、示例:
    <style>
        .red {
            color: red;
        }

        .thin {
            font-weight: 200;
        }

        .italic {
            font-style: italic;
        }
    </style>

    <div id="app">
        <!--数组中使用三元表达式-->
        <h1 :class="['red', 'thin', flag?'italic':'']">This is a paragraph of text1.</h1>
        <!--数组中使用对象-->
        <h1 :class="['red', 'thin', {italic:flag}]">This is a paragraph of text2.</h1>
        <!--使用对象-->
        <h1 :class="classObj">This is a paragraph of text3.</h1>
    </div>

    <script>
        var vm = new Vue({
            el: "#app",
            data: {
                flag: false,
                classObj: {red: true, thin: true, italic: false}
            }
        })
    </script>
(2)绑定内联样式

   类似地,在绑定 style 样式时,可以使用数组,也可以使用对象。对象的属性名称为内联样式名称,属性值为内联样式值,属性需要加上引号。

    <div id="app">
        <!--使用对象-->
        <h1 :style="styleObj2">This is a paragraph of text1.</h1>
        <!--使用数组,数组中元素为对象-->
        <h1 :style="[styleObj1, styleObj2]">This is a paragraph of text2.</h1>
    </div>

    <script>
        var vm = new Vue({
            el: "#app",
            data: {
                styleObj1: {color: 'red', 'font-weight': 200},
                styleObj2: {'font-style': 'italic'}
            }
        })
    </script>
2、v-on:

   绑定事件监听器,事件类型由参数指定,表达式可以是一个方法的名字或一个内联语句,如果没有修饰符也可以省略。

    <div id="app">
        <!-- 绑定点击事件 -->
        <input type="button" value="button1" v-on:click="show">
        <!-- 缩写形式:用 "@" 代替 "v-on:" -->
        <input type="button" value="button2" @click="show">
    </div>

    <script>
        var app = new Vue({
            el: '#app',
            methods: {
                show: function(){
                    alert("Hello World!");
                }
            }
        })
    </script>

修饰符:

  • .stop - 调用 event.stopPropagation();
  • .prevent - 调用 event.preventDefault();
  • .capture - 添加事件侦听器时使用 capture 模式;
  • .self - 只当事件是从侦听器绑定的元素本身触发时才触发回调;
  • .{keyCode | keyAlias} - 只当事件是从特定键触发时才触发回调;
  • .native - 监听组件根元素的原生事件;
  • .once - 只触发一次回调;
  • .left - (2.2.0) 只当点击鼠标左键时触发;
  • .right - (2.2.0) 只当点击鼠标右键时触发;
  • .middle - (2.2.0) 只当点击鼠标中键时触发;
  • .passive - (2.3.0) 以 { passive: true } 模式添加侦听器。
3、v-model:

   在表单控件(input、select、textarea…)或者组件上创建双向绑定

    <div id="app">
        <p>{{msg}}</p>
        <!--在修改text输入框值时,msg同步修改-->
        <input type="text" v-model="msg">
    </div>

    <script>
        var app = new Vue({
            el: '#app',
            data: {
                msg: "This is a message."
            }
        })
    </script>

修饰符:

  • .lazy - 取代 input 监听 change 事件;
  • .number - 输入字符串转为有效的数字;
  • .trim - 输入首尾空格过滤。

三、流程指令

1、v-for:

   基于源数据多次渲染元素或模板块,即对元素进行循环或迭代。此指令之值,必须使用特定语法 alias in expression ,为当前遍历的元素提供别名。

(1)循环普通数组
	<div v-for="item in items">
	  {{ item }}
	</div>
(2)循环对象数组
	<div v-for="item in items">
	  {{ item.text }}
	</div>
(3)循环对象
	<div v-for="(value,key) in items">
	  {{ item.key}}--{{ item.value}}
	</div>
(4)迭代数字
	<div v-for="count in 5">
	  {{ count }}
	</div>
(5)key 属性

   当 Vue 正在更新使用 v-for 渲染的元素列表时,它默认使用“就地更新”的策略。如果数据项的顺序被改变,Vue 将不会移动 DOM 元素来匹配数据项的顺序,而是就地更新每个元素,并且确保它们在每个索引位置正确渲染。

   这个默认的模式是高效的,但是只适用于不依赖子组件状态或临时 DOM 状态 (例如:表单输入值) 的列表渲染输出。

   为了给 Vue 一个提示,以便它能跟踪每个节点的身份,从而重用和重新排序现有元素,你需要为每项提供一个唯一 key 属性(string / number 类型):

	<div v-for="item in items" :key="item.id">
	  {{ item.text }}
	</div>
(6)示例代码
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
    <script src="../vue.min.js"></script>
</head>
<body>
    <div id="app">
        <p>1、循环普通数组</p>
        <p v-for="item in list1">{{item}}</p>
        <p>2、循环对象数组</p>
        <p v-for="(item, i) in objList">{{i}}--{{item.name}}--{{item.age}}</p>
        <p>3、循环对象</p>
        <p v-for="(value, key, i) in obj">{{i}}--{{key}}--{{value}}</p>
        <p>4、迭代数字</p>
        <p v-for="count in 5">{{count}}次计数</p>
    </div>

    <script>
        var vm = new Vue({
            el: "#app",
            data: {
                list1: [1, 2, 3, 4],
                objList: [{name: 'Tom', age: 20}, {name: 'Alice', age: 19}],
                obj: {
                    name: "Sam",
                    age: 20,
                    tel: '123456'
                }
            }
        })
    </script>
</body>
</html>
2、v-show:

   根据表达式之真假值,切换元素的 display CSS 属性。所以,它有较高的初始渲染消耗,如果元素涉及到频繁的切换,则推荐使用 v-show。

	<p v-show="flag">content</p>
3、v-if:

   根据表达式的值的真假条件渲染元素,在切换时元素及它的数据绑定 / 组件被销毁并重建。所以, v-if 有较高的切换性能消耗,如果元素很大概率不会被渲染或重复渲染,则推荐使用 v-if 。

	<p v-if="flag">content</p>
4、v-else:

   v-else ,表示 v-if 的“else 块”,v-else 元素必须紧跟在带 v-if 或者 v-else-if 的元素的后面,否则它将不会被识别。

	<div v-if="Math.random() > 0.5">
	  Now you see me
	</div>
	<div v-else>
	  Now you don't
	</div>
5、v-else-if:

   v-else-if,充当 v-if 的“else-if 块”,可以连续使用。类似于 v-else,v-else-if 也必须紧跟在带 v-if 或者 v-else-if 的元素之后。

	<div v-if="type === 'A'">
	  A
	</div>
	<div v-else-if="type === 'B'">
	  B
	</div>
	<div v-else-if="type === 'C'">
	  C
	</div>
	<div v-else>
	  Not A/B/C
	</div>

四、自定义指令

   除了核心功能默认内置的指令,Vue 也允许注册自定义指令。

1、注册指令
(1)注册或获取全局指令
	// 注册
	// {string} id 注册指令的名称
	// {Function | Object} [definition] 属性为钩子函数的对象
	Vue.directive('my-directive', {
		bind: function () {},
	  	inserted: function () {},
	  	update: function () {},
	  	componentUpdated: function () {},
	  	unbind: function () {}
	})
	
	// 注册 简写形式 默认被 `bind` 和 `update` 调用
	Vue.directive('my-directive', function () {
		
	})
	
	// getter,返回已注册的指令
	var myDirective = Vue.directive('my-directive')
  • 使用示例:
    <div id="app">
        <input type="text" v-focus>
    </div>
    <script>
        // 自定义全局获取焦点指令
        Vue.directive('focus', {
            inserted: function (el) {
                el.focus()
            },
            update: function () {console.log("222");},
        })

        // 注意:只有在Vue实例控制区域内,才能使用指令
        var vm = new Vue({
            el: "#app"
        })
    </script>
(2)注册局部指令
	var vm = new Vue({
		directives: {
			my-directive: {
				bind: function () {},
				...
			}
		}
	}
  • 使用示例:
    <div id="app">
        <input type="text" v-focus>
    </div>
    <script>
        var vm = new Vue({
            el: "#app",
            directives: {
                // 自定义局部获取焦点指令
                focus: {
                    inserted: function (el) {
                        el.focus();
                    },
                }
            }
        })
    </script>
2、钩子函数
(1)钩子函数

   一个指令定义对象可以提供如下几个钩子函数 (均为可选):

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

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

  • update:所在组件的 VNode 更新时调用,但是可能发生在其子 VNode 更新之前。

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

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

(2)钩子函数参数
  • 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 编译生成的虚拟节点。
  • oldVnode:上一个虚拟节点,仅在 update 和 componentUpdated 钩子中可用。

综合案例

  • 走马灯效果
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
    <script src="./vue.min.js"></script>
</head>
<body>
    <div id="app">
        <input type="button" value="浪起来" @click="lang">
        <input type="button" value="低调" @click="stop">
        <h4>{{msg}}</h4>
    </div>

    <script>
        var vm = new Vue({
            el: "#app",
            data: {
                msg: "猥琐发育,别浪~",
                intervalId: null
            },
            methods: {
                lang: function(){
                    // 定时器已开启,则直接返回
                    if(this.intervalId != null) return;
					
					// 在定时器中,将字符串的第一个字符放到最后
                    this.intervalId = setInterval(() => {
                        var start = this.msg.substring(0,1);
                        var end = this.msg.substring(1);
                        this.msg = end + start;
                    }, 400);
                },
                stop: function(){
                    clearInterval(this.intervalId);
                    // 清除定时器的开启状态
                    this.intervalId = null;
                }
            }
        })
    </script>
</body>
</html>
  • 简易计算器
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
    <script src="./vue.min.js"></script>
</head>
<body>
    <div id="app">
        <input type="text" v-model="num1">
        <select v-model="opt">
            <option value="+">+</option>
            <option value="-">-</option>
            <option value="*">*</option>
            <option value="/">/</option>
        </select>
        <input type="text" v-model="num2">

        <input type="button" value="=" @click="calc"></button>

        <input type="text" v-model="result">
    </div>

    <script>
        var vm = new Vue({
            el: "#app",
            data: {
                num1: 0,
                num2: 0,
                result: 0,
                opt: "+"
            },
            methods: {
                calc: function(){
                    this.result = eval("parseInt(this.num1)" + this.opt + "parseInt(this.num2)");
                }
            }
        })
    </script>
</body>
</html>
  • 商品管理案例:
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
    <script src="../vue.min.js"></script>
    <link href="https://cdn.staticfile.org/twitter-bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet">
</head>
<body>
    <div id="app">
        <div class="panel panel-primary">
            <div class="panel-heading">
                <h3 class="panel-title">添加品牌</h3>
            </div>

            <div class="panel-body form-inline">
                <label>
                    Id:
                    <input type="text" class="form-control" v-model="id">
                </label>
                <label>
                    <!-- 注册键盘回车事件 -->
                    Name:
                    <input type="text" class="form-control" v-model="name" @keyup.enter="add">
                </label>
                

                <input type="button" value="添加" class="btn btn-primary" @click="add">

                <label>
                    搜索名称关键字:
                    <input type="text" class="form-control" v-model="keywords" v-focus>
                </label>
            </div>
        </div>

        <table class="table table-bordered table-hover table-striped">
            <thead>
                <tr>
                    <th>Id</th>
                    <th>Name</th>
                    <th>Ctime</th>
                    <th>Operation</th>
                </tr>
            </thead>
            <tbody v-for="item in search(keywords)" :key="item.id">
                <tr>
                    <td>{{ item.id }}</td>
                    <td>{{ item.name }}</td>
                    <td>{{ item.ctime | dateFormat }}</td>
                    <td>
                        <!-- 阻止默认行为 -->
                        <a href="" @click.prevent="del(item.id)">删除</a>
                    </td>
                </tr>
            </tbody>   
        </table>
    </div>

    <script>
        // 注意:全局过滤器必须定义在要使用的Vue实例前
        Vue.filter('dateFormat', function(dateStr){
            var dt = new Date(dateStr);

            var y = dt.getFullYear();
            var m = (dt.getMonth() + 1).toString().padStart(2, '0');
            var d = dt.getDate().toString().padStart(2, '0');

            return y + '-' + m + '-' + d
        });

        Vue.directive('focus', {
            inserted: function (el) {
                el.focus()
            }
        })

        var vm = new Vue({
            el: "#app",
            data: {
                id: '',
                name: '',
                keywords: '',
                list: [
                    {id: 1, name: '奔驰', ctime: new Date()},
                    {id: 2, name: '宝马', ctime: new Date()},
                    {id: 3, name: '五菱', ctime: new Date()},
                ]
            },
            methods: {
                add: function(){
                    var car = {id: this.id, name: this.name, ctime: new Date()}
                    this.list.push(car)
                    this.name = this.id = ''
                },
                del: function(id){
                    this.list.some((item, i) => {
                        if(item.id == id){
                            this.list.splice(i, 1)
                            return true
                        }
                    })

                },
                search: function(keywords){
                    var newlist = []

                    this.list.forEach(item => {
                        if(item.name.indexOf(keywords) != -1){
                            newlist.push(item);
                        }
                    });

                    return newlist;
                }
            },
        })
    </script>
</body>
</html>

参考链接:

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值