Vue2 基础一指令

代码下载

Vue (读音 /vjuː/,类似于 view) 是一套用于构建用户界面的渐进式框架,官网

Vue基本使用

如何利用Vue将hello world 渲染到页面上
1、需要提供标签用于填充数据,在标签中使用插值语法的形式 即 {{}} 进行填充数据,插值表达式支持基本的计算操作。

2、引入vue.js库文件,一定要先引入Vue文件 在使用Vue语法 因为存在作用域的问题。

3、使用vue的语法做功能,使用 new Vue() 创建一个Vue的实例,在构造函数中以对象的形式做一些配置:

  • el: 元素的挂载位置(值可以是CSS选择器或者DOM元素)
  • data:模型数据(值是一个对象)

4、利用Vue将数据渲染到页面上,数据写在data里面。

    <h2>Hello world!</h2>
    <div id="app1">
        <div>{{msg}}</div>
        <div>{{1 + 2}}</div>
        <div>{{msg + 'a' + 'b'}}</div>
    </div>

    <script src="../js/vue.js"></script>
    <script>
        let vm = new Vue({
            el: '#app1',
            data: {
                msg: 'Hello Vue!'
            }
        });
    </script>

编译过程(Vue语法→原生语法)

Vue模板语法

前端渲染方式:

  • 原生js拼接字符串——(缺点:不同开发人员的代码风格差别很大,随着业务的复杂,后期的维护变得逐渐困难起来。)
  • 使用前端模板引擎——(优点:大家都遵循同样的规则写代码,代码可读性明显提高了,方便后期的维护。缺点:没有专门提供事件机制。)
  • 使用vue特有的模板语法

指令

指令的本质就是自定义属性,指令的格式:以v-开始(比如:v-cloak)

v-cloak指令

插值表达式存在“闪动”的问题,使用v-cloak指令可以解决该问题,原理就是先通过属性选择器隐藏,替换好值之后 v-cloak 属性会被自动去除再显示最终的值。

        <div v-cloak>{{msg}}</div>
数据绑定指令

v-text 指令 填充纯文本:

  • 用于将数据填充到标签中,作用于插值表达式类似,但是没有闪动问题
  • 如果数据中有HTML标签会将html标签一并输出

注意:此处为单向绑定,数据对象上的值改变,插值会发生变化;但是当插值发生变化并不会影响数据对象的值

v-html 指令 填充HTML片段:

  • 存在安全问题
  • 本网站内部数据可以使用,来自第三方的数据不可以用
  • 它与v-text区别在于v-text输出的是纯文本,浏览器不会对其再进行html解析,但v-html会将其当html标签解析 后输出

v-pre 指令 填充原始信息:

  • 显示原始信息,跳过这个元素和它的子元素的编译过程(分析编译过程)
    <div class="main" id="app">
        <div>{{msg1}}</div>
        <div v-text="msg1"></div>
        <div v-html="msg1"></div>
        <div v-pre>{{msg1}}</div>
    </div>
       
    <script src="../js/vue.js"></script> 
    <script>
        let vm = new Vue({
            el: '#app',
            data: {
                msg1: '<h1>Hello Vue</h1>'
            }
        });
    </script>
响应式
  • html5中的响应式(屏幕尺寸的变化导致样式的变化)
  • 数据的响应式(数据的变化导致页面内容的变化)

v-once 只编译一次:

  • 显示内容之后不再具有响应式功能
        <div v-once>{{msg1}}</div>

mvvm:
MVVM是前端视图层的概念,主要关注于视图层分离,也就是说MVVM把前端的视图层,分为了三部分 Model, View , ViewModel:

  • m model,数据层 Vue 中 数据层 都放在 data 里面
  • v view 视图,Vue 中 view 即 HTML页面
  • vm (view-model) 控制器 将数据和视图层建立联系,vm 即 Vue 的实例 就是 vm
双向数据绑定

v-model指令,限制在 <input><select><textarea>components 中使用

        <input type="text" v-model="msg">
事件绑定

v-on 用来绑定事件的,形式如: v-on:click 缩写为 @click:

    <div class="main" id="app">
        <!-- 在 html 中使用 data 里面的数据不需要使用 this -->
        <button v-on:click="num++">按钮1</button>
        <button @:click="num++">按钮1</button>
    </div>
        
    <script src="../js/vue.js"></script>
    <script>
        let vm = new Vue({
            el: '#app',
            data: {
                num: 0
            }
        });
    </script>

事件函数的调用方式,可以直接绑定函数名称或者调用函数, Vue的实例的 methods 中主要定义函数:

    <div class="main" id="app">
        <button @click="say">按钮3</button>
        <button @click="say()">按钮4</button>
    </div>
        
    <script src="../js/vue.js"></script>
    <script>
        let vm = new Vue({
            el: '#app',
            methods: {
                say: function() {
                    // 在函数中 使用data里面的数据 一定要加this 
                    console.log('num: ', this.num);
                }
            }
        });
    </script>

事件函数参数传递:

  • 如果事件直接绑定函数名称,那么默认会传递事件对象作为事件函数的第一个参数
  • 如果事件绑定函数调用,那么事件对象必须作为最后一个参数显示传递,并且事件对象的名称必须是$event
    <div class="main" id="app">
        <button @click="handle1">按钮5</button>
        <button @click="handle2(1, 2, $event)">按钮6</button>
    </div>
        
    <script src="../js/vue.js"></script>
    <script>
        let vm = new Vue({
            el: '#app',
            methods: {
                handle1: function(e) {
                    console.log(e.target.innerHTML);
                },
                handle2: function(p1, p2, e) {
                    console.log('p1: ', p1);
                    console.log('p2: ', p2);
                    console.log(e.target.innerHTML);
                }
            }
        });
    </script>
事件修饰符

在事件处理程序中调用 event.preventDefault() 或 event.stopPropagation() 是非常常见的需求。 Vue 不推荐我们操作DOM 为了解决这个问题,Vue.js 为 v-on 提供了事件修饰符 修饰符是由点开头的指令后缀来表示的

  • .stop 阻止冒泡
  • .prevent 阻止默认行为
  • .self 只有事件从元素本身发出才触发处理函数
        <div @click="handle" style="background-color: red;">
            <button @click="handle1">按钮1</button>
            <a href="https://www.baidu.cn/" @click.prevent="handle">百度</a>
            <button @click.stop="handle1">按钮2</button>
        </div>
        <div @click.self="handle" style="background-color: cyan;">
            <button @click="handle1">按钮3</button>
        </div>

使用修饰符时,顺序很重要;相应的代码会以同样的顺序产生。因此,用 v-on:click.prevent.self 会阻止所有的点 击,而 v-on:click.self.prevent 只会阻止对元素自身的点击。

在监听键盘事件时,经常需要检查详细的按键。Vue 允许为 v-on 在监听键盘事件时添加按键修饰符,常用的按键修饰符:

  • .enter 回车键
  • .esc 退出键
  • .tab tab键
  • .delete 删除键(捕获“删除”和“退格”按键)
  • .space 空格键
  • .up 上
  • .down 下
  • .left 左
  • .right 右
  • .keyCode 监听特定 keyCode 值对应的按键(例如 .65-a)
        <input type="text" v-on:keyup.enter.delete.left.up="handle">
        <input type="text" v-on:keyup.65="handle">

在Vue中可以通过全局 config.keyCodes 对象,自定义按键修饰符别名:

    <div class="main" id="app">
        <input type="text" v-on:keyup.kbA="handle">
    </div>
        
    <script src="../js/vue.js"></script>
    <script>
        Vue.config.keyCodes.kbA = 65;
        let vm = new Vue({
            el: '#app',
            methods: {
                handle: function() {
                    // 在函数中 使用data里面的数据 一定要加this 
                    console.log('num: ', this.num);
                }
            }
        });
    </script>
简单计算器案例

实现简单的加法计算,分别输入数值a和数值b,点击计算按钮,结果显示在下面:

  • 通过v-model指令实现数值a和数值b的绑定
  • 给计算按钮绑定事件,实现计算逻辑
  • 将计算结果绑定到对应位置
    <div class="main" id="app">
        <h4>简单计算器案例</h4>
        <div>
            <span>数值A:</span>
            <input type="text" v-model="a"> <br />
            <span>数值B:</span>
            <input type="text" v-model="b"> <br />
            <button v-on:click="plus">相加计算</button> <br />
            <span>结果:</span>
            <span v-text="result"></span>
        </div>
    </div>

    <script>
        let vm = new Vue({
            el: '#app',
            data: {
                a: '',
                b: '',
                result: ''
            },
            methods: {
                plus: function() {
                    this.result = parseInt(this.a) + parseInt(this.b);
                }
            }
        });
    </script>
属性绑定

v-bind 指令被用来响应地更新 HTML 属性,v-bind:href 可以缩写为 :href

    <div class="main" id="app">
        <a v-bind:href="baiduUrl">百度</a>
        <a :href="baiduUrl">百度1</a>
    </div>
        
    <script>
        Vue.config.keyCodes.kbA = 65;
        let vm = new Vue({
            el: '#app',
            data: {
                baiduUrl: 'https://www.baidu.cn/'
            }
        });

v-model的低层实现原理是使用 v-bind 绑定 value 属性,使用 v-on 将输入域中的最新的数据覆盖原来的数据:

    <div class="main" id="app">
        <!-- v-model原理 -->
        <div>{{msg}}</div>
        <input type="text" v-bind:value="msg" v-on:input="inputHandle">
        <input type="text" :value="msg" @input="msg = $event.target.value;">
    </div>

    <script src="../js/vue.js"></script>
    <script>
        let vm = new Vue({
            el: '#app',
            data: {
                msg: 'Hello Vue!'
            },
            methods: {
                inputHandle: function(e) {
                     this.msg = e.target.value;
                }
            }
        });
    </script>
class 样式绑定

class 样式处理有对象绑定和数组绑定两种:

    <style>
        .active {
            border: 1px solid red;
            width: 100px;
            height: 100px;
        }
        .err {
            background-color: orange;
        }
        .text {
            font-size: 18;
            color: cyan;
        }
        .default {
            border-radius: 10px;
        }
    </style>
    
    <div class="main" id="app">
        <!-- 绑定对象 -->
        <div v-bind:class="{active: isActive, err: isErr}">绑定对象</div>
        <!-- 绑定数组 -->
        <div v-bind:class="[activeClass, errClass]">绑定数组</div>
        <!-- 对象绑定和数组绑定可以结合使用 -->
        <div v-bind:class="[activeClass, errClass, {text: isText}]">对象绑定和数组绑定可以结合使用</div>
        <!-- class绑定的值可以简化操作 -->
        <div :class="objClasses">class绑定的值可以简化操作</div>
        <div :class="arrClasses">class绑定的值可以简化操作</div>
        <!-- 默认的class会保留 -->
        <div class="default" :class="objClasses">默认的class会保留</div>
        <button v-on:click="classHandle">切换</button>
    </div>

    <script src="../js/vue.js"></script>
    <script>
        let vm = new Vue({
            el: '#app',
            data: {
                isActive: true,
                isErr: true,
                isText: true,
                activeClass: 'active',
                errClass: 'err',
                textClass: 'text',
                arrClasses: ['active', 'err', 'text'],
                objClasses: {active: true, err: true, text: true}
            },
            methods: {
                classHandle: function() {
                    this.isActive = !this.isActive;
                    this.isErr = !this.isErr;
                    this.isText = !this.isText;
                    if (this.activeClass === '') {
                        this.activeClass = 'active';
                    } else {
                        this.activeClass = '';
                    }
                    if (this.errClass === '') {
                        this.errClass = 'err';
                    } else {
                        this.errClass = '';
                    }
                    this.objClasses.active = !this.objClasses.active;
                    this.objClasses.err = !this.objClasses.err;
                    this.objClasses.text = !this.objClasses.text;
                    if (this.arrClasses.length > 0) {
                        this.arrClasses = [];
                    } else {
                        this.arrClasses = [this.activeClass, this.errClass, this.textClass];
                    }
                }
            }
        });

绑定对象和绑定数组 的区别:

  • 绑定对象的时候 对象的属性 即要渲染的类名 对象的属性值对应的是 data 中的数据(表示是否渲染的布尔值)
  • 绑定数组的时候数组里面存的是 data 中的数据(表示类名)

样式绑定相关语法细节:

  • 对象绑定和数组绑定可以结合使用
  • class绑定的值可以简化操作
  • 默认的class如何处理?默认的class会保留
style样式绑定

style 样式处理也有对象绑定和数组绑定两种:
CSS 属性名可以用驼峰式
组语法可以将多个样式对象应用到同一个元素

    <div class="main" id="app">
        <div :style="{border: borderStyle, width: widthStyle, height: heightStyle}"></div>
        <div :style="objStyles"></div>
        <div :style="[objStyles, overrideStyles]"></div>
        <button @click="styleHandle">切换</button>
    </div>

    <script src="../js/vue.js"></script>
    <script>
        let vm = new Vue({
            el: '#app',
            data: {
                borderStyle: '1px solid blue',
                widthStyle: '100px',
                heightStyle: '200px',
                objStyles: {
                    border: '1px solid green',
                    width: '200px',
                    height: '100px'
                },
                overrideStyles: {
                    border: '5px solid orange',
                    backgroundColor: 'blue'
                }
            },
            methods: {
                styleHandle: function() {
                    if (this.heightStyle === '100px') {
                        this.heightStyle = '200px';
                    } else {
                        this.heightStyle = '100px';
                    }
                    if (this.objStyles.width === '100px') {
                        this.objStyles.width = '200px';
                    } else {
                        this.objStyles.width = '100px';
                    }
                }
            }
        });
分支结构

v-ifv-elsev-else-ifv-show

v-if与v-show的区别:

  • v-if控制元素是否渲染到页面,是动态的向DOM树内添加或者删除DOM元素,v-if切换有一个局部编译/卸载的过程,切换过程中合适地销毁和重建内部的事件监听和子组件。
  • v-show控制元素是否显示(已经渲染到了页面),本质就是标签display设置为none,控制隐藏,v-show只编译一次,后面其实就是控制css,而v-if不停的销毁和创建,故v-show性能更好一点。
    <div class="main" id="app">
        <!-- 分支结构 -->
        <div v-if="score>=90">优秀</div>
        <div v-else-if="score<90&&score>=80">良好</div>
        <div v-else-if="score<80&&score>=60">一般</div>
        <div v-else>差</div>
        <div v-show="flag">v-show</div>
        <button @click="showHandle" v-text="flag ? '隐藏' : '显示'"></button>
    </div>

    <script src="../js/vue.js"></script>
    <script>
        let vm = new Vue({
            el: '#app',
            data: {
                score: 99,
                flag: true
            },
            methods: {
                showHandle: function() {
                    this.flag = !this.flag;
                }
            }
        });
循环结构

v-for 用于循环的数组、对象里面的值可以是对象,也可以是普通元素:

  • 不推荐同时使用 v-if 和 v-for,当 v-if 与 v-for 一起使用时, v-for 具有比 v-if 更高的优先级。
  • key 给每个节点做一个唯一标识(一般使用数据的id或者遍历序号),key的作用主要是帮助Vue区分不同的元素,从而提高性能,高效的更新虚拟DOM。
    <div class="main" id="app">
        <!-- 循环结构 -->
        <div :key="value.id" v-for="(value, index) in fruits">
            <div v-if="value.id>1" :key="i" v-for="(v, k, i) in value" v-text="k + ': ' + v"></div>
        </div>
    </div>

    <script src="../js/vue.js"></script>
    <script>
        let vm = new Vue({
            el: '#app',
            data: {
                fruits: [{
                    id: 1,
                    ename: 'apple',
                    cname: '苹果'
                },{
                    id: 2,
                    ename: 'orange',
                    cname: '橘子'
                },{
                    id: 3,
                    ename: 'banana',
                    cname: '香蕉'
                }]
            }
        });

Tab选项卡案例

把tab栏 中的数替换到页面上:

  • 把 data 中 title 利用 v-for 循环渲染到页面上
  • 把 data 中 path 利用 currentIndex 序号取出渲染到页面上

默认的第一项tab栏高亮:

  • tab栏高亮 通过添加类名 current 来实现 (CSS current 的样式已经提前写好)
  • 在data 中定义一个 默认的 索引 currentIndex 为 0 给第一个li 添加 current 的类名
  • 通过动态绑定class 来实现 第一个li 的索引为 0 和 currentIndex 的值刚好相等
  • currentIndex === i 如果相等 则添加类名 current 否则添加 空 类名

点击每一个tab栏 当前的高亮 其他的取消高亮:

  • 给每一个li添加点击事件
  • 将 v-for 循环中的索引 i 赋值给 currentIndex

css:

        .tab > ul {
            list-style: none;
            margin: 0;
            padding: 0;
        }
        .tab > ul > li {
            float: left;
            width: 80px;
            height: 40px;
            line-height: 40px;
            text-align: center;
            border-top: 1px solid blue;
            border-left: 1px solid blue;
            box-sizing: border-box;
        }
        .tab > ul > li.current {
            background-color: orange;
        }
        .tab > ul > li:last-child {
            border-right: 1px solid blue;
        }
        .tab > div {
            clear: both;
        }

html:

    <div class="main" id="app">
        <div class="tab">
            <ul>
                <li :class="currentIndex === i ? 'current' : ''" :key="v.id" v-for="(v, i) in list" v-text="v.title" @click="currentIndex = i"></li>
            </ul>
            <div>
                <img v-bind:src="'../' + list[currentIndex].path" alt="">
            </div>
        </div>
    </div>

js:

    <script src="../js/vue.js"></script>
    <script>
        let vm = new Vue({
            el: '#app',
            data: {
                currentIndex: 0, // 选项卡当前的索引
                list: [{
                    id: 1,
                    title: 'apple',
                    path: 'img/apple.png'
                },{
                    id: 2,
                    title: 'orange',
                    path: 'img/orange.png'
                },{
                    id: 3,
                    title: 'lemon',
                    path: 'img/lemon.png'
                }]
            }
        });
<think>嗯,用户想了解Vue2中常用的自定义指令及其使用示例和场景。首先,我需要回顾一下Vue2的自定义指令相关知识。根据系统提供的引用内容,用户已经给出了一些相关的引用资料,我需要从中提取关键信息,并按照用户的要求整理回答。 首先,用户需要的是常用的自定义指令示例及其应用场景。根据引用[2],Vue的自定义指令可以用于动画、DOM操作、表单验证和交互增强等场景。比如v-longpress长按指令,这在移动端比较常见。还有v-focus自动聚焦输入框,这在表单处理中很实用。引用[3]中提到了v-rainbow这个例子,可以改变文字颜色,可能属于DOM操作的范畴。引用[4]和[5]提到Vue3和Vue2的区别,但用户关注的是Vue2,所以可能需要强调Vue2的写法。 接下来,我需要考虑如何组织这些信息。可能需要先解释自定义指令的基本结构,包括钩子函数如bind、inserted、update等,然后给出几个具体的例子,每个例子包括代码和场景说明。同时,要确保示例代码符合Vue2的语法,比如使用Vue.directive来注册指令,钩子函数的参数(el, binding, vnode等)。 然后,要列举常用的场景,比如表单自动聚焦、权限控制、防抖节流、拖拽等,这些都是常见的应用。每个场景对应一个示例,并说明为什么使用自定义指令能更好地实现这些功能。例如,权限控制可以通过v-permission指令来动态显示或隐藏元素,而无需在组件中写冗余的逻辑判断。 另外,需要注意用户提到的引用标记,在回答中正确引用对应的来源。比如,提到内置指令时引用[2],提到钩子函数时引用[2]中的生命周期部分,示例中的v-rainbow来自引用[3]。 还要检查是否有遗漏的重要点,比如自定义指令的参数传递,如何通过binding.value获取值,如何通过修饰符和参数来扩展指令的功能。比如在v-longpress中,可能需要传入延迟时间和回调函数,这时候需要在指令定义中处理这些参数。 最后,生成的相关问题需要与主题相关,比如如何传递参数,生命周期钩子的区别,与Vue3的不同等,这些都能帮助用户进一步学习。</think>### Vue2 常用自定义指令示例及场景说明 #### 一、自定义指令基础结构 Vue2 自定义指令通过 `Vue.directive()` 注册,包含以下核心钩子函数[^2]: - **bind**:指令第一次绑定到元素时调用 - **inserted**:元素插入父节点时调用 - **update**:组件更新时调用 - **componentUpdated**:组件及子组件更新后调用 - **unbind**:指令与元素解绑时调用 #### 二、常用指令案例 1. **自动聚焦指令 (v-focus)** ```javascript Vue.directive('focus', { inserted: function(el) { el.focus() } }) ``` **使用场景**:表单输入框自动获取焦点提升用户体验 **模板示例**: ```html <input v-focus placeholder="自动聚焦输入框"> ``` 2. **长按指令 (v-longpress)**[^4] ```javascript Vue.directive('longpress', { bind(el, binding) { let timer = null; el.addEventListener('mousedown', () => { timer = setTimeout(() => { binding.value() // 执行回调函数 }, 1000) }) el.addEventListener('mouseup', () => clearTimeout(timer)) } }) ``` **使用场景**:移动端长按触发菜单/删除操作 **模板示例**: ```html <button v-longpress="deleteItem">长按删除</button> ``` 3. **权限控制指令 (v-permission)** ```javascript Vue.directive('permission', { inserted(el, binding) { const permissions = ['admin', 'editor'] if (!permissions.includes(binding.value)) { el.parentNode.removeChild(el) } } }) ``` **使用场景**:动态控制功能模块的显示权限 **模板示例**: ```html <button v-permission="'admin'">管理员操作</button> ``` 4. **防抖指令 (v-debounce)**[^5] ```javascript Vue.directive('debounce', { inserted(el, binding) { let timer el.addEventListener('input', () => { clearTimeout(timer) timer = setTimeout(() => { binding.value() }, 500) }) } }) ``` **使用场景**:搜索框输入防抖处理 **模板示例**: ```html <input v-debounce="search" placeholder="输入关键词"> ``` #### 三、典型应用场景 | 场景类型 | 指令示例 | 实现效果 | |----------------|-------------------|------------------------------| | 表单交互 | v-focus | 自动聚焦输入元素 | | 性能优化 | v-debounce | 减少高频事件触发 | | 权限管理 | v-permission | 动态控制元素可见性 | | 特殊交互 | v-longpress | 实现长按触发机制 | | 视觉反馈 | v-highlight | 鼠标悬停元素高亮 | | 拖拽操作 | v-draggable | 实现元素拖拽功能 | #### 四、开发注意事项 1. **参数传递**:通过 `binding.value` 获取指令值,支持对象/函数传递 2. **动态更新**:在 `update` 钩子中处理数据变化后的逻辑 3. **内存管理**:在 `unbind` 钩子中移除事件监听防止内存泄漏 §§ 1. Vue2 自定义指令如何传递动态参数? 2. `bind` 和 `inserted` 钩子的具体区别是什么? 3. 如何实现自定义指令的局部注册? 4. Vue2Vue3 自定义指令的主要差异有哪些? 5. 自定义指令如何配合 Vuex 实现状态管理?
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值