vue

149 阅读7分钟

⭐⭐vue生命周期

20210106142128940.png

vue指令

1.v-if

2.v-for

3.v-once 只渲染一次

4.v-html 插入html片段

5.v-on

6.v-bind

動態參數
<img v-bind:[imageUrl]="a" />

...
data(){
    return{
        imageUrl:'url'
    }
}
v-on、v-bind縮寫
    <!-- 完整语法 --> 
    <a v-bind:href="url">...</a>
    <!-- 缩写 -->
    <a :href="url">...</a>
    <!-- 完整语法 --> 
    <a v-on:click="doSomething">...</a>
    <!-- 缩写 --> 
    <a @click="doSomething">...</a>

⭐⭐vue計算屬性與侦听器

計算屬性computed

computed與method 不同的是method沒有緩存機制,每次都會調用該函數,浪費性能,而computed卻有是基于它们的响应式依赖进行缓存的緩存機制,所以我們大量運算表達式可以用計算屬性進行計算。黨應用data數據發生變化時,computed會重新進行計算。

    <template>
        <p>Original message: "{{ message }}"</p> 
        <p>Computed reversed message: "{{ reversedMessage }}"</p>
    </template>
    
    <script>
        export default{
            name:'component1',
            data(){
                return {
                    message:'1111'
                }
            },
            computed:{
                reversedMessage(){
                    return this.message+'2222'
                }
            }
        }
    </script>
偵聽器watch

偵聽器監聽頁面響應式數據,數據變化會觸發偵聽器,可以利用偵聽器去觸發一些所需動作,需要一些開銷比較大的函數或異步函數,可以用偵聽器

    <template>
        <p>Original message: "{{ message }}"</p> 
    </template>
    
    <script>
        export default{
            data(){
                return{
                    message:'aa'
                }
            },
            methods:{
                a(){
                    this.message = 'sss';
                },
                b(){
                    for(let i = 0; i <= 10e8; i++){
                        console.log(i);
                    }
                },
            },
            watch:{
                message(newVal,oldVal){
                    if(newVal == 'ss'){
                        this.b()
                    }
                }
            }
        }
    </script>

⭐⭐class綁定

<template>
    <div v-bind:class="{a:true,b:lc}">111</div>
</template>

<script>
    export default{
        data(){
            return {
                lc:false
            }
        }
    }
</script>

上面渲染的結果

    <div class="a">111</div>
<template>
    <div :class="a">2222</div>
</template>
<script>
    export default{
        name:'try',
        data(){
            return {
                a:{
                    b:true,
                    'vv':true
                }
            }
        },
    }
</script>

也可以利用計算屬性

<template>
    <div :class="classObject">2222</div>
</template>
<script>
    export default{
        name:'try',
        data(){
            return {
                a:{
                    b:true,
                    'vv':true
                }
            }
        },
        computed:{
            classObject(){
                return {
                    active-class: a.b
                    lll:a['vv']
                }
            }
        }
    }
</script>

數組語法

<template>
    <div :class="[classObjec, errClass]"></div>
</template>
<script>
    data(){
        return{
            classObject:'aaa',
            errClass:'bbb'
        }
    }
</script>

渲染結果

<div class="aaa bbb"></div>
<div :class=[true?isAvtice]:'',errClass>222</div>
<script>
    data(){
        return{
            isAvtice:'sss',
            errClass:'lll'
        }
    }
</script>

渲染結果

<div class="sss lll"></div>

⭐⭐ style綁定

對象語法

<template>
    <div :style="{color:styleColor, fontSize:styleFont}">222</div>
    <div :style="styleObject">222</div>
</template>
<script>
    export default{
        data(){
            return{
                styleColor:'red',
                styleFont:'12px',
                styleObject:{
                   color:'red',
                   fontSize:'32px'
               }
                
            }
        }
    }
</script>

數組語法

<template>
    <div :style="[styleColor,styleFont]">222</div>
</template>
<script>
    export default{
        name:'a',
        data(){
            styleColor:'green',
            styleFont:'24px'
        }
    }
</script>

自動添加兼容前缀

vue會自動檢測css樣式是否需要加上前缀值

多重值

你可以添加重複前缀值,系統會自動幫你檢測那個合適,留下最適合值。

⭐⭐ 條件渲染 v-if 與 v-show

😋用key管理元素復用

vue會用已有元素進行復用這種高效的方法,但是這種通常元素上的值會保持不變。可以給元素加上key值來控制不復用。(注意label沒加也還是采用復用機制)

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

v-show

這個指令只是簡單對dom元素進行display設置css樣式切換而已,實際不想v-if是直接刪除頁面元素

v-if與v-for一起使用

v-for比v-if更先優先級,在項目中v-if不能跟v-for同用一個元素上,不然檢測出錯誤。

⭐⭐ v-for

v-for基礎

不要使用對象或者數組做為key,得使用字符串作爲key

v-for采用的是就地更新,如果數據項順序改變,vue不會移動dom元素順序,而是就地更新每個元素。(這種用index作爲key只適合少量dom元素)

如果大量dom元素需要渲染,需要采用唯一key值,以免造成大量dom元素反復渲染影響性能

數組更新檢測

能檢測更新數組方法

1.push

2.pop

3.shift

4.unshift

5.splice

6.sort

7.reverse

檢測不了數組方法

1.filter

2.concat

3.slice

這三個方法會生成返回新的數組,可用新的數組賦予舊的數組變量值,來彌補檢測不了數組方法以至於視圖無法更新的bug

** 显示过滤/排序后的结果** 這種情況可以采用計算屬性computed和方法method

computed

<template>
    <div v-for="n of zjArr">{{n}}</div>
</template>
<script>
    export default{
        data(){
            return{
                l:[3,5,100,4,1,2]
            }
        },
        computed:{
            zjArr(){
                return this.l.filter(number=>{
                    return number%2 === 0
                })
            }
        }
    }
</script>

method

<template>
    <div v-for="n of zjArr(n)">{{n}}</div>
</template>
<script>
    export default{
        data(){
            return{
                l:[[ 1, 2, 3, 4, 5 ], [6, 7, 8, 9, 10]]
            }
        },
        method:{
            zjArr(n){
                return this.n.filter(number=>{
                    return number%2 === 0
                })
            }
        }
    }
</script>

⭐⭐ v-on

事件修飾符
  • .stop 阻止单击事件继续传播
  • .prevent 阻止默認事件發生
  • .capture
  • .self 觸發當前元素事件
  • .once
  • .passive
  • once 事件只觸發一次
鼠標修飾符
  • .left
  • .right
  • .middle
按鍵修飾符

image.png

image.png

image.png

image.png

⭐⭐ v-model

修飾符
  • .lazy 將v-model默認的input事件換成change事件進行同步雙向綁定
  • .number 將輸入的字符串轉換數字類型
  • trim 將輸入的内容去除空格
<input v-model.lazy="msg">
<input v-model.number="age" type="number">
<input v-model.trim="msg">

⭐⭐ 组件基础

data必须是个函数

因为组件复用的原因,所以data必须是一个函数,每次复用都会返回一份独立拷贝的数据。如果是对象的话就会发生浅拷贝现象

在组件使用v-model

image.png

组件写法

image.png

单向数据流

父级直接改变子组件数据是被允许的,但是子组件直接改变父组件的数据是不被允许,如果直接改变父级组件数据,从而导致你的应用的数据流向难以理解。(会报错),可以利用emit进行改变。

Vue.component('my-component', 
{ props: { 
// 基础的类型检查 (`null` 和 `undefined` 会通过任何类型验证) 
propA: Number,
// 多个可能的类型 
propB: [String, Number],
// 必填的字符串 
propC: { type: String, required: true }, 
// 带有默认值的数字 
propD: { type: Number, default: 100 },
// 带有默认值的对象 
propE: { 
type: Object, 
// 对象或数组默认值必须从一个工厂函数获取 
default: function () { 
    return { message: 'hello' }
  }
},
// 自定义验证函数 
propF: { validator: function (value) {
// 这个值必须匹配下列字符串中的一个
return ['success', 'warning', 'danger'].indexOf(value) !== -1 
    } 
}
} 
}
)

禁用 Attribute 继承

image.png

image.png

.async修饰符

image.png

⭐⭐插槽

具名插槽

组件内部可以利用及外部可以使用 来传进你所需的HTML片段,如果没有 没有name属性,外部可以用default或者直接写入传进组件内部

// 组件内部
<div class="container">
    <header>
        <slot name="header"></slot>
    </header>
    <main>
        <slot></slot>
    </main>
    <footer>
        <slot name="footer"></slot>
    </footer>
</div>
<base-layout>
    <template v-slot:header>
        <h1>aaaaa</h1>
    </template>
    <template v-slot:default>
        <p>bbbbbb</p>
        <p>cccccc</p>
    </template>
    <template v-slot:footer>
        <p>dddddd</p>
    </template>
</base-layout>
⭐⭐ 作用域插槽

插槽里面的值往父级外面传

// 插槽内部
<span>
    <slot name="aa" :user="user">
        {{user.name}}
    </slot>
</span>

// 父级 slotVal是所有插槽带出来所有值,可以解构你所需要的相应值
<case-div>
    <template v-slot:aa="slotVal">
        {{slotVal.user.name}}
    </template>
</case-div>
具名插槽缩写
// 插槽内部 
<span> 
    <slot name="aa" :user="user"> {{user.name}} </slot>
</span> 
// 父级 slotVal是所有插槽带出来所有值,可以解构你所需要的相应值 
<case-div> 
    <template #aa="slotVal"> {{slotVal.user.name}} </template> 
</case-div>

⭐⭐ 混入

如果混入变量名函数名等与本身组件变量名函数名等相同,会以组件本身为主(选项合并)。

var myMixin = {
    data(){
        return {
            a;'22'
        }
    },
    method:{
        b(){
            console.log('0000')
        }
    }
}

var componet = vue.extend({
    mixins:[myMixin]
})

⭐⭐ 自定义指令

全局注册自定义指令
// 注册一个全局自定义指令 `v-focus`
Vue.directive('focus',{
// 当被绑定元素插入dom时执行
    inserted:function(el){
        //聚焦元素
        el.focus()
    }
})
局部注册自定义指令

组件接受一个选项directive

directive:{
    focus:{
        inserted:function(el){
            el.focus()
        }
    }
}
指令钩子

bind

只调用一次,第一次绑定到元素进行调用,在这里可以进行一次性的初始化配置。

inserted

被绑定元素插入父级元素调用(仅保证父元素存在,但不一定已插入文档中)

update

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

componentUpdate

指令所在组件vnode及其子vnode更新之后调用

unbind

只调用一次,指令与组件解绑之后调用

钩子参数

image.png

image.png

对象字面量

image.png

⭐⭐ 过滤器

过滤器可以用在双花括号和v-bind表达式

// 在双花括号中
{{message | capitalize}}

// 在v-bind中
<div v-bind:id="message | capitalize"></div>

image.png

过滤器还可以串联及传入参数

image.png

⭐⭐ 响应式原理

当你把一个普通对象传入vue中选项data中时,vue会利用object.defineProperty将这个对象里面的属性遍历变成gettersetter

Object.defineProperty 是 ES5 中一个无法 shim 的特性,这也就是 Vue 不支持 IE8 以及更低版本浏览器的原因。

每个组件实例都对应一个 watcher 实例,它会在组件渲染的过程中把“接触”过的数据 property 记录为依赖。之后当依赖项的 setter 触发时会通知 watcher,从而使它关联的组件重新渲染。

image.png

检测变化的注意事项

由于 JavaScript 的限制,Vue 不能检测数组和对象的变化。尽管如此我们还是有一些办法来回避这些限制并保证它们的响应性。

对象

vue无法侦察object添加/移除属性

// 可以使用this.$set(改变对象,'属性名','赋予新值')
this.$set(this.a,objectName,value)

image.png

数组

不能检测两种情况

  1. 当你利用索引直接设置一个数组项时,例如:vm.items[indexOfItem] = newValue
  2. 当你修改数组的长度时,例如:vm.items.length = newLength
// this.$set(数组项,下标,赋予的新值)
this.$set(this.items, indexOfItem, newValue)

// 使用splice修改长度
this.items.splice(newLength)

⭐⭐ 异步更新队列 nextTick

当我们需要访问渲染过后的vue时,可以使用nextTick来访问

method:{
    a(){
        this.$nextTick(()=>{
            // 访问dom渲染后的vue
            ......
        })
    }
}

因为nextTick 会返回一个promise对象,所以可以使用async/await语法完成相同事情

method:{
    async a(){
        await this.$nextTick(()=>{})
        console.log('aaaaaaaaaa')
    }
}

⭐⭐keep-alive

include :字符串、数组、或者正则表达式。只有名称匹配得组件会被缓存。 exclude :字符串、数组、或者正则表达式。符合名称匹配得组件不会被缓存。 max :数字。最多可以缓存多少组件实例。

image.png

image.png