草庐IT

Vue 内置指令以及自定义指令

半糖也很甜吖 2023-03-28 原文

1. 内置指令

  • v-show :

    • 说明:根据条件展示元素,true展示元素,false隐藏元素
<template>
    <div>
        <button v-show="isShow"></button>
    </div>
</template>
<script>
export default {
    name: 'HomeView',
    data() {
        return {
            isShow: false
        };
    }
};
</script>

注意:v-show 不支持写在 template 元素标签上,也不支持同时写在 v-else 标签中

v-show 是采用切换css属性display:block,display:none来控制显示或隐藏dom,所以初始页面render时,此dom就会渲染至页面中,只不过是隐藏状态。

  • v-if:

    • 说明:根据条件展示元素,true在dom树中渲染元素,false从dom树中移除元素
<template>
    <div>
        <button v-if="isShow"></button>
    </div>
</template>
<script>
export default {
    name: 'HomeView',
    data() {
        return {
            isShow: false
        };
    }
};
</script>

v-if可以作用于template中,如果表达式为true,那么template标签块中的代码都会渲染,反之都不渲染

v-if也是惰性的:如果在初始渲染时条件为假,则什么也不做——直到条件第一次变为真时,才会开始渲染条件块

  • v-else

    • 说明:表示 v-if 的“else 块”
<template>
    <div>
        <button v-if="isShow">按钮1</button>
        <button v-else>按钮2</button>
    </div>
</template>

<script>
export default {
    name: 'HomeView',
    data() {
        return {
            isShow: false
        };
    }
};
</script>

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

  • v-else-if

    • 说明:表示 v-if 的“else 块”
<template>
    <div>
        <button v-if="type === 'a'">按钮a</button>
        <button v-else-if="type === 'b'">按钮b</button>
        <button v-else-if="type === 'c'">按钮c</button>
        <button v-else="type === 'd'">按钮d</button>
    </div>
</template>

<script>
export default {
    name: 'HomeView',
    data() {
        return {
            type: 'a'
        };
    }
};
</script>

类似于 v-elsev-else-if 也必须紧跟在带 v-if 或者 v-else-if 的元素之后。

  • v-bind

    • 说明:动态地绑定一个或多个 attribute,或一个组件 prop 到表达式
    • 缩写::

a. 绑定一个 attribute

<template>
    <div>
        <img v-bind:src="imgSrc" />
        <img :src="imgSrc" />
    </div>
</template>

<script>
export default {
    name: 'HomeView',
    data() {
        return {
            imgSrc: 'https://picsum.photos/200/300/?random'
        };
    }
};
</script>

b. class 绑定

<template>
    <div>
        <div :class="{ red: isRed }"></div>
        <div :class="[classA, classB]"></div>
        <div :class="[classA, { classB: isB, classC: isC }]"></div>
    </div>
</template>

<script>
export default {
    name: 'HomeView',
    data() {
        return {
            isRed: true,
            classA: 'classA',
            classB: 'classB',
            isB: true,
            isC: true
        };
    }
};
</script>

c. style 绑定

<template>
    <div>
        <div :style="{ fontSize: size + 'px' }"></div>
        <div :style="[styleObjectA, styleObjectB]"></div>
    </div>
</template>

<script>
export default {
    name: 'HomeView',
    data() {
        return {
            size: 20,
            styleObjectA: {
                color: 'red',
                fontSize: '20px'
            },
            styleObjectB: {
                color: 'blue',
                fontSize: '30px'
            }
        };
    }
};
</script>

d. 组件传值

<template>
    <div>
        <child-component :title="text" />
    </div>
</template>

<script>
export default {
    name: 'HomeView',
    components: {
        'child-component': {
            props: {
                title: String
            },
            template: '<div>{{ title }}</div>'
        }
    },
    data() {
        return {
            text: 'test'
        };
    }
};
</script>

e. 传递当前所有 props

<template>
    <div>
        <child-component v-bind="$props" />
    </div>
</template>

<script>
export default {
    name: 'HomeView',
    components: {
        'child-component': {
            props: {
                title: String
            },
            template: '<div>{{ title }}</div>'
        }
    },
    props: {
        propsValue: String
    },
    data() {
        return {
            text: 'test'
        };
    }
};
</script>
  • v-text

    • 说明:更新元素的 textContent
<template>
    <div>
        <span v-text="text"></span>
        <!-- 和下面的一样 -->
        <span>{{ text }}</span>
    </div>
</template>

<script>
export default {
    name: 'HomeView',
    data() {
        return {
            text: 'test'
        };
    }
};
</script>
  • v-html

    • 说明:更新元素的 innerHTML
    • 版本:vue2,vue3
<template>
    <div>
        <p v-html="innerHTML"></p>
    </div>
</template>

<script>
export default {
    name: 'HomeView',
    data() {
        return {
            innerHTML: '<button>click</button>'
        };
    }
};
</script>

页面展示:

  • v-for

    • 说明:遍历数据
<template>
    <div class="container">
        <ul>
            <li v-for="(item, index) in list" :key="item.name">{{ item.name }}{{ index }}</li>
        </ul>

        <ol>
            <li v-for="(item, index) of list" :key="item.version">{{ item.version }}{{ index }}</li>
        </ol>
    </div>
</template>

<script>
export default {
    name: 'HomeView',
    data() {
        return {
            list: [
                {
                    name: 'vue',
                    version: '2'
                },
                {
                    name: 'react',
                    version: '17'
                }
            ]
        };
    }
};
</script>

注意:请不要将 v-forv-if 一起使用,当和 v-if 一起使用时,v-for 的优先级比 v-if 更高,v-for 可以与 v-show 一起使用,如果需要带条件渲染,请考虑使用 computed 属性
最佳建议,在使用 v-for 时,使用 key 属性,来保证内部 diff 算法更新 dom 时最佳优化,不推荐使用 index 属性

页面展示:

  • v-model

    • 说明:在表单控件或者组件上创建双向绑定
<template>
    <div class="container">
        <p>
            <span>input-</span>
            <span>v-model:</span>
            <span>{{ inputVal }}</span>
            <input type="text" v-model="inputVal" />
        </p>
        <p>
            <span>textarea-</span>
            <span>v-model:</span>
            <span>{{ textareaVal }}</span>
            <textarea type="text" v-model="textareaVal"></textarea>
        </p>
    </div>
</template>

<script>
export default {
    name: 'HomeView',
    data() {
        return {
            inputVal: '',
            textareaVal: ''
        };
    }
};
</script>

页面展示:

2. 自定义指令

  • 注册全局指令
import Vue from 'vue';

Vue.directive('directiveName', {
    bind(el, binding, vnode, oldVnode) {},
    inserted(el, binding, vnode, oldVnode) {},
    update(el, binding, vnode, oldVnode) {},
    componentUpdated(el, binding, vnode, oldVnode) {},
    unbind(el, binding, vnode, oldVnode) {}
});
<template>
    <div class="container" v-directiveName></div>
</template>
  • 局部注册指令
<template>
    <input class="container" v-focus />
</template>

<script>
export default {
    name: 'HomeView',
    directives: {
        focus: {
            bind(el, binding, vnode, oldVnode) {},
            inserted(el, binding, vnode, oldVnode) {},
            update(el, binding, vnode, oldVnode) {},
            componentUpdated(el, binding, vnode, oldVnode) {},
            unbind(el, binding, vnode, oldVnode) {}
        }
    }
};
</script>
  • 钩子函数

    • bind : 只调用一次,指令第一次绑定到元素时调用。在这里可以进行一次性的初始化设置。
    • inserted : 被绑定元素插入父节点时调用 (仅保证父节点存在,但不一定已被插入文档中)。
    • update : 所在组件的 VNode 更新时调用,但是可能发生在其子 VNode 更新之前。指令的值可能发生了改变,也可能没有
    • componentUpdated : 指令所在组件的 VNode 及其子 VNode 全部更新后调用。
    • unbind : 只调用一次,指令与元素解绑时调用。
  • 钩子函数参数

    • el : 指令所绑定的元素,可以用来直接操作 DOM。
    • binding : 一个对象,包含以下 property
      • 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 钩子中可用。
  • 指令完整参数写法

<template>
    <input v-focus:mount.foo.bar="1 + 1" />
</template>

<script>
export default {
    name: 'HomeView',
    directives: {
        focus: {
            bind(el, binding, vnode, oldVnode) {
                console.log(binding);
            },
            inserted(el, binding, vnode, oldVnode) {},
            update(el, binding, vnode, oldVnode) {},
            componentUpdated(el, binding, vnode, oldVnode) {},
            unbind(el, binding, vnode, oldVnode) {}
        }
    }
};
// [object Object]
{
  "name": "focus",
  "rawName": "v-focus:mount.foo.bar",
  "value": 2,
  "expression": "1 + 1",
  "arg": "mount",
  "modifiers": {
    "foo": true,
    "bar": true
  },
  "def": {}
}
</script>
  • 动态参数
<template>
    <input v-focus:[dynamic].foo.bar="1 + 1" />
</template>

<script>
export default {
    name: 'HomeView',
    data() {
        return {
            dynamic: [1, 2, 3, 4, 5]
        };
    },
    directives: {
        focus: {
            bind(el, binding, vnode, oldVnode) {
                console.log(binding);
            },
            inserted(el, binding, vnode, oldVnode) {},
            update(el, binding, vnode, oldVnode) {},
            componentUpdated(el, binding, vnode, oldVnode) {},
            unbind(el, binding, vnode, oldVnode) {}
        }
    }
};
</script>
// [object Object]
{
  "name": "focus",
  "rawName": "v-focus:[dynamic].foo.bar",
  "value": 2,
  "expression": "1 + 1",
  "arg": [
    1,
    2,
    3,
    4,
    5
  ],
  "modifiers": {
    "foo": true,
    "bar": true
  },
  "def": {}
}
  • 自定义指令示例
    • v-drag
<template>
    <div class="container" v-drag></div>
</template>

<script>
export default {
    name: 'HomeView',
    data() {
        return {
            dynamic: [1, 2, 3, 4, 5]
        };
    },
    directives: {
        drag: {
            bind(el, binding, vnode, oldVnode) {
                el.onmousedown = e => {
                    const disX = e.clientX - el.offsetLeft;
                    const disY = e.clientY - el.offsetTop;
                    document.onmousemove = e => {
                        el.style.left = e.clientX - disX + 'px';
                        el.style.top = e.clientY - disY + 'px';
                    };
                    document.onmouseup = () => {
                        document.onmousemove = null;
                        document.onmouseup = null;
                    };
                };
            },
            inserted(el, binding, vnode, oldVnode) {},
            update(el, binding, vnode, oldVnode) {},
            componentUpdated(el, binding, vnode, oldVnode) {},
            unbind(el, binding, vnode, oldVnode) {}
        }
    }
};
</script>

<style scoped>
.container {
    width: 500px;
    height: 300px;
    border: 1px solid red;
    position: fixed;
    left: 0;
    top: 0;
}
.container:hover {
    cursor: pointer;
}
</style>

有关Vue 内置指令以及自定义指令的更多相关文章

  1. ruby - Facter::Util::Uptime:Module 的未定义方法 get_uptime (NoMethodError) - 2

    我正在尝试设置一个puppet节点,但ruby​​gems似乎不正常。如果我通过它自己的二进制文件(/usr/lib/ruby/gems/1.8/gems/facter-1.5.8/bin/facter)在cli上运行facter,它工作正常,但如果我通过由ruby​​gems(/usr/bin/facter)安装的二进制文件,它抛出:/usr/lib/ruby/1.8/facter/uptime.rb:11:undefinedmethod`get_uptime'forFacter::Util::Uptime:Module(NoMethodError)from/usr/lib/ruby

  2. ruby - 什么是填充的 Base64 编码字符串以及如何在 ruby​​ 中生成它们? - 2

    我正在使用的第三方API的文档状态:"[O]urAPIonlyacceptspaddedBase64encodedstrings."什么是“填充的Base64编码字符串”以及如何在Ruby中生成它们。下面的代码是我第一次尝试创建转换为Base64的JSON格式数据。xa=Base64.encode64(a.to_json) 最佳答案 他们说的padding其实就是Base64本身的一部分。它是末尾的“=”和“==”。Base64将3个字节的数据包编码为4个编码字符。所以如果你的输入数据有长度n和n%3=1=>"=="末尾用于填充n%

  3. ruby-on-rails - Rails 3.2.1 中 ActionMailer 中的未定义方法 'default_content_type=' - 2

    我在我的项目中添加了一个系统来重置用户密码并通过电子邮件将密码发送给他,以防他忘记密码。昨天它运行良好(当我实现它时)。当我今天尝试启动服务器时,出现以下错误。=>BootingWEBrick=>Rails3.2.1applicationstartingindevelopmentonhttp://0.0.0.0:3000=>Callwith-dtodetach=>Ctrl-CtoshutdownserverExiting/Users/vinayshenoy/.rvm/gems/ruby-1.9.3-p0/gems/actionmailer-3.2.1/lib/action_mailer

  4. ruby-on-rails - form_for 中不在模型中的自定义字段 - 2

    我想向我的Controller传递一个参数,它是一个简单的复选框,但我不知道如何在模型的form_for中引入它,这是我的观点:{:id=>'go_finance'}do|f|%>Transferirde:para:Entrada:"input",:placeholder=>"Quantofoiganho?"%>Saída:"output",:placeholder=>"Quantofoigasto?"%>Nota:我想做一个额外的复选框,但我该怎么做,模型中没有一个对象,而是一个要检查的对象,以便在Controller中创建一个ifelse,如果没有检查,请帮助我,非常感谢,谢谢

  5. ruby - 主要 :Object when running build from sublime 的未定义方法 `require_relative' - 2

    我已经从我的命令行中获得了一切,所以我可以运行rubymyfile并且它可以正常工作。但是当我尝试从sublime中运行它时,我得到了undefinedmethod`require_relative'formain:Object有人知道我的sublime设置中缺少什么吗?我正在使用OSX并安装了rvm。 最佳答案 或者,您可以只使用“require”,它应该可以正常工作。我认为“require_relative”仅适用于ruby​​1.9+ 关于ruby-主要:Objectwhenrun

  6. ruby - 在 Ruby 中有条件地定义函数 - 2

    我有一些代码在几个不同的位置之一运行:作为具有调试输出的命令行工具,作为不接受任何输出的更大程序的一部分,以及在Rails环境中。有时我需要根据代码的位置对代码进行细微的更改,我意识到以下样式似乎可行:print"Testingnestedfunctionsdefined\n"CLI=trueifCLIdeftest_printprint"CommandLineVersion\n"endelsedeftest_printprint"ReleaseVersion\n"endendtest_print()这导致:TestingnestedfunctionsdefinedCommandLin

  7. ruby - 定义方法参数的条件 - 2

    我有一个只接受一个参数的方法:defmy_method(number)end如果使用number调用方法,我该如何引发错误??通常,我如何定义方法参数的条件?比如我想在调用的时候报错:my_method(1) 最佳答案 您可以添加guard在函数的开头,如果参数无效则引发异常。例如:defmy_method(number)failArgumentError,"Inputshouldbegreaterthanorequalto2"ifnumbereputse.messageend#=>Inputshouldbegreaterthano

  8. ruby - 如何在 Grape 中定义哈希数组? - 2

    我使用Ember作为我的前端和GrapeAPI来为我的API提供服务。前端发送类似:{"service"=>{"name"=>"Name","duration"=>"30","user"=>nil,"organization"=>"org","category"=>nil,"description"=>"description","disabled"=>true,"color"=>nil,"availabilities"=>[{"day"=>"Saturday","enabled"=>false,"timeSlots"=>[{"startAt"=>"09:00AM","endAt"=>

  9. ruby - 获取模块中定义的所有常量的值 - 2

    我想获取模块中定义的所有常量的值:moduleLettersA='apple'.freezeB='boy'.freezeendconstants给了我常量的名字:Letters.constants(false)#=>[:A,:B]如何获取它们的值的数组,即["apple","boy"]? 最佳答案 为了做到这一点,请使用mapLetters.constants(false).map&Letters.method(:const_get)这将返回["a","b"]第二种方式:Letters.constants(false).map{|c

  10. ruby - 这两个 Ruby 类初始化定义有什么区别? - 2

    我正在阅读一本关于Ruby的书,作者在编写类初始化定义时使用的形式与他在本书前几节中使用的形式略有不同。它看起来像这样:classTicketattr_accessor:venue,:datedefinitialize(venue,date)self.venue=venueself.date=dateendend在本书的前几节中,它的定义如下:classTicketattr_accessor:venue,:datedefinitialize(venue,date)@venue=venue@date=dateendend在第一个示例中使用setter方法与在第二个示例中使用实例变量之间是

随机推荐