vue(API下)

552 阅读8分钟

实例 property

1、vm.$data

  • 类型: Object
  • 详细: Vue实例观察的数据对象

2、vm.$props

  • 类型: Object
  • 详细: 当前组件接收到的props对象

3、vm.$el

  • 类型: Element
  • 只读
  • 详细: Vue 实例使用的根 DOM 元素

4、vm.$options

  • 类型: Object
  • 只读
  • 详细: 用于当前 Vue 实例的初始化选项。需要在选项中包含自定义 property 时会有用处:

实例方法 / 数据

1、vm.$watch

  • 参数

    • {string | Function} expOrFn
    • {Function | Object} callback
    • {Object} [options]
      • {boolean} deep
      • {boolean} immediate
  • 用法

    • 观察 Vue 实例上的一个表达式或者一个函数计算结果的变化。回调函数得到的参数为新值和旧值。
    export default {
     data() {
         return {
             count: 1      
         }
     },
     created() {
         this.$watch('count', function(){
             console.log('count 新值:'+newVal)
         })
     }
    }
    
    • watch作用一样,但这种方式使定义数据观察更灵活,而且 $watch 会返回一个取消观察函数,用来停止触发回调
    let watchFn = this.$watch('count', function(){
      console.log('count 新值:'+newVal)
    })
    this.count = 2 // log: count 新值:2
    watchFn() // 调用之后取消观察
    this.count = 3 // 什么都没有发生...
    
    • $watch 第三个参数接收一个配置选项:
    this.$watch('count', function(){
      console.log('count 新值:'+newVal)
    }, {
      immediate: true // 立即执行watch
    })
    
    // 为了发现对象内部值的变化,可以在选项参数中指定 deep: true。注意监听数组的变更不需要这么做。
    this.$watch('count', function(){
     console.log('count 新值:'+newVal)
    }, {
     deep: true 
    })
    

    注意在带有 immediate 选项时,你不能在第一次回调时取消侦听给定的 property。

    // 这会导致报错
    var unwatch = vm.$watch(
      'value',
      function () {
        doSomething()
        unwatch()
      },
      { immediate: true }
    )
    

♕ 模板语法

1、插值

  • 文本:大括号的形式{{ }}

    <span>{{ msg }}</span>
    
  • 原始HTML:使用v-html指令

    <span v-html="rawHtml"></span>
    
  • 使用js表达式:在模板中,对于所有的数据绑定,Vue.js 都提供了完全的 JavaScript 表达式支持。

    {{ ok ? 'YES' : 'NO' }}
    
    {{ message.split('').reverse().join('') }}
    
    <div v-bind:id="'list-' + id"></div>
    

    注意:每个绑定都只能包含单个表达式

2、指令

指令是带有 v- 前缀的特殊 attribute

① v-text

  • 插入数据:string
  • 示例
<div v-text="msg"></div>
<!-- 和下面的一样 -->
<div>{{msg}}</div>

② v-html

  • 插入数据:string
  • 示例
 <div v-html="html"></div>

注意事项:在单文件组件里,scoped 的样式不会应用在 v-html 内部,因为那部分 HTML 没有被 Vue 的模板编译器处理。 如果你希望针对 v-html 的内容设置带作用域的 CSS,你可以替换为 CSS Modules 或用一个额外的全局 <style> 元素 手动设置类似 BEM 的作用域策略。

③ v-show

  • 插入数据:any
<div v-html="html"></div>
  • 用法

带有 v-show 的元素始终会被渲染并保留在 DOM 中。v-show 只是简单地切换元素的 CSS property display

设置为 0、-0、null、""、false、undefined 或 NaN,则该对象设置为 false。否则设置为 true(即使 value 参数是字符串 "false")。

  • 实例
<div v-show="ok">Hello!</div>

注意事项:v-show 不支持 <template>元素,也不支持 v-else

④ v-if

  • 插入数据:any
  • 用法

在切换时元素及它的数据绑定 / 组件被销毁并重建。如果元素是 <template>,将提出它的内容作为条件块。

  • 示例
 <div v-if="ok">Hello!</div>

注意事项
在2.x中:当在同一元素上使用v-if和v-for时,v-for将优先使用;
在3.x中,v-if优先级始终高于v-for

⑤ 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>

⑥ v-else-if

  • 插入数据:any
  • 限制:前一兄弟元素必须有 v-if 或 v-else-if。
  • 示例
 <div v-if="type === 'A'">
   A
 </div>
 <div v-else-if="type === 'B'">
   B
 </div>
 <div v-else>
   Not A/B/C
 </div>

⑦ v-for

  • 插入数据:Array | Object | number | string | Iterable (2.6 新增)
  • 用法

v-for 的默认行为会尝试原地修改元素而不是移动它们。要强制其重新排序元素,你需要用特殊 attribute key 来提供一个排序提示

另外也可以为数组索引指定别名 (或者用于对象的键):

  • 示例
 <!--  string --- item:值,index:索引值 -->
 <div v-for="(item, index) in string" :key="index"></div>

 <!-- Array --- val:值,key:索引值 -->
 <div v-for="(val, key) in array" :key="key"></div>

 <!-- Object --- val:值,name:键,index:索引值 -->
 <div v-for="(val, name, index) in object" :key="index"></div>

⑧ v-on

  • 插入数据:Function | Inline Statement | Object
  • 缩写:@
  • 示例
 <!-- 方法处理器 -->
<button @click="doThis"></button>

<!-- 动态事件 (2.6.0+) -->
<button @[event]="doThis"></button>

<!-- 内联语句 -->
// 如果使用内联语句,语句可以访问一个 $event property
<button @click="doThat('hello', $event)"></button>

<!-- 阻止默认行为,没有表达式 -->
<form @submit.prevent></form>

<!--  串联修饰符 -->
<button @click.stop.prevent="doThis"></button>

<!-- 对象语法 (2.4.0+) -->
// 注意当使用对象语法时,是不支持任何修饰器的。
<button v-on="{ mousedown: doThis, mouseup: doThat }"></button>

⑨ v-bind

  • 插入数据:any (with argument) | Object (without argument)

  • 缩写::

  • 修饰符:

    • . prop:该修饰符的作用是防止暴露标签自定义属性,美化HTML结构。没有添加prop的属性是直接暴露在外的。作为一个 DOM property 绑定而不是作为 attribute 绑定。 打开chrome Elements的properties属性面板查看该元素属性可以看到

    • . sync:vue中我们经常会用v-bind(缩写为:)给子组件传入参数。或者我们会给子组件传入一个函数,子组件通过调用传入的函数来改变父组件的状态。

    即:父组件改变数据可以改变子组件, 但是子组件的内容改变并不会影响到父组件,可以通过2.3.0新增的sync修饰符来达到双向绑定的效果

    🎬 前景:

    //父组件给子组件传入一个函数
    <MyFooter :ages="age" @setAge="(res)=> age = res"/>
    
    //子组件通过调用这个函数来实现修改父组件的状态。
    <script>
      props: {
        ages: ''
      },
      mounted () {
        console.log(this.$emit('setAge',1234567));
      }
    </script>
    

    这时子组件触发了父组件的修改函数使父组件的age修改成了1234567,这种情况比较常见并且写法比较复杂。

    ⏳ 优化:

    于是我们引出今天的主角 .sync

    这里注意我们的事件名称被换成了update:age

    update:是被固定的也就是vue为我们约定好的名称部分;

    age是我们要修改的状态的名称,是我们手动配置的,与传入的状态名字对应起来

    //父组件将age传给子组件并使用.sync修饰符。
    <MyFooter :ages.sync="age"/>
    //子组件触发事件
    <script>
       props: {
        ages: ''
       },
       mounted () {
        console.log(this.$emit('update:ages',1234567));
       }
    </script>
    

    注意:带有 .sync 修饰符的 v-bind 不能和表达式一起使用 (例如 v-bind:title.sync=”doc.title + ‘!’” 是无效的)。
    👉 取而代之的是,你只能提供你想要绑定的 property 名,类似 v-model。

    • .camel :(2.1.0+) 将 kebab-case attribute 名转换为 camelCase。(从 2.1.0 开始支持)

    待研究。。。

  • 示例

<!-- 缩写 -->
<img :src="imageSrc">

<!-- 动态 attribute 名缩写 (2.6.0+) -->
<button :[key]="value"></button>

<!-- 内联字符串拼接 -->
<img :src="'/path/to/images/' + fileName">

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

<!-- style 绑定 -->
<div :style="{ fontSize: size + 'px' }"></div>
<div :style="[styleObjectA, styleObjectB]"></div>
  
<!-- 通过 prop 修饰符绑定 DOM attribute -->
<div v-bind:text-content.prop="text"></div>

<!-- prop 绑定。“prop”必须在 my-component 中声明。
父传子数值-->
<my-component :prop="someThing"></my-component>

<!-- 通过 $props 将父组件的 props 一起传给子组件 -->
<child-component v-bind="$props"></child-component>

⑩ v-model

  • 插入数据:随表单控件类型不同而不同。

  • 限制:

    • <input>
    • <select>
    • <textarea>
    • components
  • 用法:

    • 基本用法

    你可以用 v-model 指令在表单 <input>、<textarea> 及 <select> 元素上创建双向数据绑定。它会根据控件类型自动选取正确的方法来更新元素。尽管有些神奇,但 v-model 本质上不过是语法糖。它负责监听用户的输入事件以更新数据,并对一些极端场景进行一些特殊处理。

    v-model 在内部为不同的输入元素使用不同的 property 并抛出不同的事件:

    • input 和 textarea 元素使用 value property 和 input 事件;

    • checkbox 和 radio 使用 checked property 和 change 事件;

    • select 字段将 value 作为 prop 并将 change 作为事件。

    • 在组件上使用v-model

    v-model本质是一个语法糖,v-bind和v-on的整合

    • 2.x语法


      在2.x中,v-model在组件上使用等效于传递value值并发出 input 事件:

      <!-- 父组件 -->
      <ChildComponent v-model="pageTitle" />
      
      <!-- 等价于 -->
      
      <ChildComponent :value="pageTitle" @input="pageTitle = $event" />
      

      如果我们想将属性名称或事件名称更改为其他名称,则需要向ChildComponent组件添加一个选项:
      <!-- 父组件 -->
      <ChildComponent v-model="pageTitle" />
      
      <!-- 等价于 -->
      
      <ChildComponent :title="pageTitle" @change="pageTitle = $event" />
      
      <!-- 子组件 -->
      export default {
        model: {
          prop: 'title',
          event: 'change'
        },
        props: {
          title: {
            type: String,
            default: 'Default title'
          }
        }
      }
      
    • 3.x语法


    在3.x v-model在组件上使用等效于传递modelValue值并发出update:modelValue事件:

    <ChildComponent v-model="pageTitle" />
    
    <!-- 等价于: -->
    
    <ChildComponent
    :modelValue="pageTitle"
    @update:modelValue="pageTitle = $event"/>
    


    如果我们想改属性名称

    <ChildComponent v-model:title="pageTitle" />
    
     <!-- 等价于: -->
    
    <ChildComponent :title="pageTitle" @update:title="pageTitle = $event" />
    


    这也可以作为.sync修饰符的替代,并允许我们v-model在自定义组件上使用多个。

    <ChildComponent v-model:title="pageTitle" v-model:content="pageContent" />
    
     <!-- 等价于: -->
    
    <ChildComponent
       :title="pageTitle"
       @update:title="pageTitle = $event"
       :content="pageContent"
       @update:content="pageContent = $event"
    />
    
  • 修饰符:

    • .lazy : 取代 input 监听 change 事件

      原本监听input事件

       <input v-model="value"/>
       //等同于
       <input :value="value" @input="value=$event.target.value"/>
      

      使用.lazy修饰符后监听change事件:

       <input v-model.lazy="value"/>
       //等同于
       <input :value="value"  @change="value=$event.target.value"/>
      
    • .number : 输入字符串转为有效的数字,这通常很有用,因为即使在 type="number" 时,HTML 输入元素的值也总会返回字符串,它主要是用来限制用户输入的时候只能是数字

    • .trim : 输入首尾空格过滤

  • 示例

 <input v-model="value"></input>

⑪ v-slot

  • 插入数据:
  • 缩写: #

待研究更新。。。

⑫ v-pre

  • 不需要表达式
  • 用法: 跳过这个元素和它的子元素的编译过程。可以用来显示原始 Mustache 标签。跳过大量没有指令的节点会加快编译。
  • 示例:
<div id="app">
   {{ str }}
   <span v-pre>{{ str }}</span>
</div>
<script>
   const vm = new Vue({
       el: '#app',
       data: {
           msg: '天气真好!'
       }
   })
</script>

编译结果:

⑬ v-cloak

  • 不需要表达式
  • 用法: 这个指令保持在元素上直到关联实例结束编译。
  • 示例:
<div id="app" v-cloak>
   <div>
       {{message}}
   </div>
</div>
<script type="text/javascript">
   new Vue({
     el:'#app',
     data:{
       message:'hello world'
     }
   })
</script>

在页面加载时会闪烁,先显示

<div>
   {{message}}
</div>

然后才会编译为:

<div>
   hello world!
</div>

⑭ v-once

  • 不需要表达式
  • 用法:只渲染元素组件一次。随后的重新渲染,元素/组件及其所有的子节点将被视为静态内容并跳过。这可以用于优化更新性能。
  • 示例
<!-- 单个元素 -->
<span v-once>This will never change: {{msg}}</span>

<!-- 组件 -->
<my-component v-once :comment="msg"></my-component>

<!-- `v-for` 指令-->
<ul>
  <li v-for="i in list" v-once>{{i}}</li>
</ul>

3、特殊attribute

Ⅰ. key

  • 语法:number | string | boolean (2.4.2 新增) | symbol (2.5.12 新增)

  • 用法:有相同父元素的子元素必须有独特的 key。重复的 key 会造成渲染错误。主要是为了vue精准的追踪到每一个元素,高效的更新虚拟DOM。

最常见的用例是结合 v-for:

<ul>
  <li v-for="item in items" :key="item.id">...</li>
</ul>

它也可以用于强制替换元素/组件而不是重复使用它。
当 text 发生改变时, 没有key的情况下diff算法可以对节点就地复用<span> 会被修改。
有key的情况下<span> 会被替换。

<transition>
  <span :key="text">{{ text }}</span>
</transition>

vue中在使用相同标签名元素的过渡切换时,也会使用到key属性,其目的也是为了让vue可以区分它们。否则vue只会替换其内部属性而不会触发过渡效果。

<template v-if="loginType === 'username'">
 <label>Username</label>
 <input placeholder="Enter your username" key="username-input">
</template>
<template v-else>
 <label>Email</label>
 <input placeholder="Enter your email address" key="email-input">
</template>

Ⅱ. ref

  • 语法:string

  • 用法:

    • ref 被用来给元素或子组件注册引用信息。引用信息将会注册在父组件的 $refs 对象上。
    <!-- `vm.$refs.p` 在普通的 DOM 元素上使用,引用指向的就是 DOM 元素; -->
    <p ref="p">hello</p>
    
    <!-- `vm.$refs.child` 在子组件上,引用就指向组件实例 -->
    <child-component ref="child"></child-component>
    
    • 当 v-for 用于元素或组件的时候,引用信息将是包含 DOM 节点或组件实例的数组。

    这里之前遇到一个问题:使用this.$refs.xx在mounted中获取DOM元素为undefined)

    * 原因:在 DOM 结构中的某个 DOM 节点使用了 `v-if``v-show` 或者 `v-for` `(即根据获取到的后台数据来动态操作 DOM,即响应式)`,那么这些 DOM 在 mounted 阶段他们根本不存在。动态加载回来的数据是不会在这个阶段更新到 DOM 中的。
    * 解决:
    
    ① 在`updated` 函数中获取:updated 阶段是完成了数据更新到 DOM 的阶段
    
    ② 使用`$nextTick`:$nextTick 是在下次 DOM 更新循环结束之后执行延迟回调,在修改数据之后使用 $nextTick,则可以在回调中获取更新后的 DOM。
    

Ⅲ. is

  • 语法:string | Object (组件的选项对象)
  • 作用:

有些 HTML 元素,诸如 <ul>、<ol>、<table> 和 <select>里面嵌套的写法是HTML语法的固定写法,里面添加自己写的组件,html在渲染dom时,<my-component>并不是有效的dom,自定义组件<my-component>会被作为无效的内容提升到外部,并导致最终渲染结果出错。

<ul>
    <my-component></my-component>
</ul>

于是就诞生了is解决html模板的限制

<ul>
    <li is='my-component'></li>
</ul>
  • 使用:
    • 动态切换不同组件
    <div id="app">
      <button @click="changeComponent('component1')">A</button>
      <button @click="changeComponent('component2')">B</button>
       <!-- 通过is特性,可以动态切换当前组件  -->
      <div :is="currentView"></div>
        <!-- v-bind:动态绑定属性  -->
    </div>
    //引入组件
    <script>
    import component1 from '../....';
    import component2 from '../....';
    export default {
      data(){
        return {
          //当前组件
          currentView:'component1'
        } 
      },
     components:{
       component1,
       component2
     }
     methods:{
       changeComponent(component){
          //点击按钮,动态切换不同的组件
          this.currentView=component;
       }
     }
    }
    </script>
    
    • 解析DOM模板 : 解除限制元素
    <!-- 这个自定义组件<my-component>会被作为无效的内容提升到外部,并导致最终渲染结果出错。 -->
    <table>
        <my-component></my-component>
    </table>
    
    <!--增加is特性来扩展,从而达到可以在这些受限制的html元素中使用 -->
    <table> 
       <tr is="my-component"></tr>
    </table> 
    

3、内置组件

Ⅰ. component

  • Props:
    • is - string | ComponentDefinition | ComponentConstructor`
    • inline-template - boolean
  • 用法: 渲染一个“元组件”为动态组件。依 is 的值,来决定哪个组件被渲染。
<!-- 动态组件由 vm 实例的 `componentId` property 控制 -->  
<component :is="componentId"></component>  
  
<!-- 也能够渲染注册过的组件或 prop 传入的组件 -->  
<component :is="$options.components.child"></component>

待续。。。