2

【vue】Vue中的指令

 2 years ago
source link: https://segmentfault.com/a/1190000040768045
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

Vue中的指令

  1. v-text
  2. v-html
  3. v-show
  4. v-else
  5. v-else-if
  6. v-for
  7. v-bind
  8. v-model
  9. v-slot
  10. v-pre
  11. v-cloak
  12. v-once

1 v-text

更新元素的textContent
部分更新可以使用插值语法{{Mustache}}

2 v-hetml

更新元素的innerHTML
内容按普通HTML插入-不会作为Vue模板进行编译

在网站上动态渲染HTML很危险,容易导致XSS攻击

3 v-show v-if v-else v-else-if

条件渲染
v-show 相当于改变标签的display
v-if 是真实的条件渲染,值为falsy时会将元素从DOM结构中删除

v-else v-else-if 可以与v-if组成一个链式的条件渲染,与日常的if - else代码块有类似的逻辑

4 v-for

列表渲染
基于源数据多次渲染元素或模块,alias in expression
v-for的默认行为会尝试原地修改元素而不是移动它们。要强制重新排序元素,需要特殊的attribute key来提供一个排序的提示
expression:Array Object Number String Iterable

//数组
<template>
  <div id="app">
    <ul>
      <li v-for="(item, index) in list" :key="index">
        {{ item }}{{ index }}{{ list[index] }}
      </li>
    </ul>
  </div>
</template>

<script>
export default {
  name: "App",
  data() {
    return {
      list: ["张三", "李四", "王二"],
    };
  },
};
</script>
//对象
<template>
  <div id="app">
    <ul>
      <li v-for="(item, index) in list" :key="index">
        {{ item }}{{ index }}{{ list[index] }}
      </li>
    </ul>
  </div>
</template>

<script>
export default {
  name: "App",
  data() {
    return {
      list: {
        a: "张三",
        b: "李四",
        c: "王二",
      },
    };
  },
};
</script>
//对象数组
<template>
  <div id="app">
    <ul>
      <li v-for="(item, index) in list" :key="index">
        {{ item }}{{ index }}{{ item.name }}
      </li>
    </ul>
  </div>
</template>

<script>
export default {
  name: "App",
  data() {
    return {
      list: [{ name: "张三" }, { name: "李四" }, { name: "王二" }],
    };
  },
};
</script>

数据初始化:由模板->虚拟DOM->真实DOM
key作为虚拟DOM中的一个标签属性,如果使用index作为key,在数据更新后新的虚拟DOM会编排key不管更新的数据插入的位置,都是从0开始编排

数据更新:新模板->新虚拟DOM->Diff算法比较前后的虚拟DOM->真实DOM
在比较的过程中,如果使用index作为key,先根据key对比前后的DOM节点,由于key的重新编排,导致模板复用率低,并且在复用时还容易发生错误
如果使用数据的唯一标识作为key,生成新的虚拟DOM时根据key来对比,不会有太大变化,只更新变化的部分,无变化的部分容易在key比对后复用

v-for与v-if同时使用时,v-for的优先级高,这意味着会进行列表渲染然后再判断是否渲染
image.png

5 v-on

绑定事件监听器
普通标签:监听原生DOM事件
组件:监听自定义事件
表达式v-on:event="handle(param)"
缩写@
参数:事件处理函数中可以无参数,可以传入多个参数,参数$event为触发的事件,通常可以通过$event.target来获取触发事件的元素

v-on后可以是一个对象触发对个事件 v-on="{event1:handle1(),event2:handle2()}"

5.1 事件修饰符

  1. .stop:调用event.stopPropagation()

    阻止捕获和冒泡阶段中当前事件的进一步传播,不防止任何默认行为的发生

  2. .prevent:调用event.preventDefault()

    阻止默认事件,例如a标签href跳转,使用@click.prevent可以阻止跳转行为

  3. .capture:添加事件监听器时使用capture模式

    元素发生冒泡时,先触发带有该修饰符的元素,有多个该修饰符,由外而内触发

  4. .self:只当事件是从侦听器绑定的元素本身触发时才触发回调

    在冒泡阶段,从内触发的事件不会在拥有该修饰符的父元素上触发

  5. .{keyCode|keyAlias}:只当事件从特定键触发时才触发回调

    enter tab delete esc space up down left right ctrl alt shift meta

  6. .native:监听组件跟元素的原生事件

    组件上的事件默认为自定义事件,需要$emit触发

  7. .once:只触发一次
  8. .left:点击鼠标左键触发
  9. .right:点击鼠标右键触发
  10. .passive:以{passive:true}模式添加侦听器

    告知浏览器不阻止默认行为,可以提高性能,事件捕获->事件冒泡->默认事件

5.2 .sync修饰符

简化父子组件数据的双向绑定

6 v-bind

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

在组件上绑定时,需要在组件内使用props声明后才能使用

6.1 class与style绑定

动态的切换class与绑定内联样式
class

//对象形式
<div :class="{ active: isActive, base: isBase }"></div>
//数组形式 - 可用三元运算符与对象
<div :class="['active', isBase ? 'base' : '', { filter: isFilter }]"></div>

style

//对象形式 - 可以三元运算
<div
  :style="{
    width: activeWidth,
    height: activeHeight,
    background: isRed ? 'red' : '',
  }"
></div>
//数组形式 - 多个样式对象
<div :style="[baseStyle, activeStyle]"></div>

Vue会自动的添加浏览器引擎前缀
对象形式的属性值可以是一个数组,添加多个值

6.2 修饰符

  1. .prop
  2. .camel
  3. .sync

.prop:作为一个DOM property绑定而不是作为attribute绑定

<div :textContent.prop="foo"></div>

.camel:将kebab-case attribute名转换为camelCase,将-连接的属性名改为驼峰式

.sync:扩展成一个更新父组件绑定值的v-on侦听器

//不使用.sync的方式
//父组件
<template>
  <div id="app">
    <Child :msg="msg" @changeVal="change"></Child>
    <span>{{ msg }}</span>
  </div>
</template>

<script>
import Child from "./components/Child.vue";
export default {
  name: "App",
  data() {
    return {
      msg: "你好",
    };
  },
  methods: {
    change(val) {
      this.msg = val;
    },
  },
  components: {
    Child,
  },
};
</script>
//子组件
<template>
  <div>
    <input type="text" :value="msg" @input="change($event.target.value)" />
  </div>
</template>

<script>
export default {
  props: ["msg"],
  methods: {
    change(e) {
      this.$emit("changeVal", e);
    },
  },
};
</script>

父组件传递数据,并在组件上绑定自定义的事件,子组件props接收数据,触发事件

//父组件
<template>
  <div id="app">
    <Child :msg.sync="msg"></Child>
    <span>{{ msg }}</span>
  </div>
</template>

<script>
import Child from "./components/Child.vue";
export default {
  name: "App",
  data() {
    return {
      msg: "你好",
    };
  },
  components: {
    Child,
  },
};
</script>
//子组件
<template>
  <div>
    <input type="text" :value="msg" @input="change($event.target.value)" />
  </div>
</template>

<script>
export default {
  props: ["msg"],
  methods: {
    change(e) {
      this.$emit("update:msg", e);
    },
  },
};
</script>

父组件在传递数据时加上.sync修饰符,不需要绑定事件
子组件触发update:data事件,data为监听的数据

7 v-model

表单控件或者组件上创建双向绑定

7.1 表单控件绑定

v-model本质是v-bind与事件绑定的语法糖

  • text和textarea元素使用value property和input事件
  • checkbox和radio使用checked property和change事件
  • select字段将value作为prop并将change作为事件
<template>
  <div id="app">
    <p>1.text</p>
    <div>
      <input type="text" v-model="text" /><br />
      <span>{{ text }}</span>
    </div>
    <p>2.textarea</p>
    <div>
      <textarea v-model="textarea"></textarea><br />
      <span>{{ textarea }}</span>
    </div>
    <p>3.checkbox</p>
    <div>
      <input type="checkbox" id="jack" value="jack" v-model="checkName" />
      <label for="jack">jack</label>
      <input type="checkbox" id="john" value="john" v-model="checkName" />
      <label for="john">john</label><br />
      <span>checked:{{ checkName }}</span>
    </div>
    <p>4.radio</p>
    <div>
      <input type="radio" id="one" value="One" v-model="pick" />
      <label for="one">One</label>
      <input type="radio" id="two" value="Two" v-model="pick" />
      <label for="two">Two</label><br />
      <span>picked:{{ pick }}</span>
    </div>
    <p>5.select</p>
    <div>
      <select v-model="selected">
        <option disabled value="">请选择</option>
        <option>A</option>
        <option>B</option>
        <option>C</option>
      </select>
      <br />
      <span>selected:{{ selected }}</span>
    </div>
  </div>
</template>

<script>
export default {
  name: "App",
  data() {
    return {
      text: "text",
      textarea: "textarea",
      checkName: [],
      pick: "",
      selected: "",
    };
  },
};
</script>

复选框的绑定可以有两个值true-valuefalse-value表示选中与未选中
value的值可以进行动态绑定

7.2 组件绑定

自定义组件的v-model

//父组件
<template>
  <div id="app">
    <Child v-model="msg" />
    <span>{{ msg }}</span>
  </div>
</template>

<script>
import Child from "./components/Child.vue";
export default {
  name: "App",
  data() {
    return {
      msg: "hello",
    };
  },
  components: {
    Child,
  },
};
</script>
//子组件
<template>
  <div>
    <input type="text" :value="msg" @input="inputVal($event.target.value)" />
  </div>
</template>

<script>
export default {
  model: {
    prop: "msg",
    event: "changeVal",
  },
  props: ["msg"],
  methods: {
    inputVal(val) {
      this.$emit("changeVal", val);
    },
  },
};
</script>

使用model选项可以声明绑定的数据与自定义的触发事件
可以避免复选框中绑定value与checked的冲突

可以与上面介绍的v-bing+事件绑定.sync修饰符实现的双向绑定对比

7.3 修饰符

.lazy:从input事件触发同步数据转为change事件后同步
.number:将用户输入的值转为数值类型
.trim:自动过滤用户输入的首尾空白符

8 v-slot

提供具名插槽或需要接收prop的插槽
缩写:#
vm.slots和vm.scopedSlots属性
插槽

9 v-pre

无表达式
跳过这个元素和它子元素的编译过程
跳过大量没有指令的节点会加快编译

10 v-cloak

无表达式
次指令保持在元素上直到关联实例结束编译
作为css的属性选择器,与display:none一起使用,可以避免在页面处出现插值语法的{{}}

11 v-once

无表达式
只对元素和组件渲染一次,随后的重新渲染,元素/组件及其所有的子节点将被视为静态内容并跳过

对于拥有大量静态内容在组件,可以在根元素上添加该指令,提升渲染的速度


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK