vue查缺补漏

Object.freeze()

<template>
  <div class="hello">
    {{msg.name}}
      <input type="text" :value="msg.name" @change="(event) => {msg.name = event.target.value}">
  </div>  
</template>

<script>
export default {
  name: 'HelloWorld',
  data() {
    let a = {name:123}
    Object.freeze(a)
    return {
      msg:a
    }
  },
  methods: {}
}
</script>


[Vue warn]: Error in v-on handler: "TypeError: Cannot assign to read only property 'name' of object '#<Object>'"

计算属性

计算属性与方法

计算属性是基于他们响应式依赖进行缓存的,只有相关响应式依赖发生变化时他们才会重新求值,方法每次都需要调用

计算属性与监听方法

当某个变量是由多个变量响应式依赖的话,使用watch会造成代码的冗余;

修饰符

  • handler(str) {
      console.log(str)
    },
    
  • .stop: 阻止冒泡,即当子标签存在点击事件,父标签也存在点击事件,当点击子标签的时候,父标签的点击事件也会触发,因此使用.stop来阻止冒泡行为

    <!-- 使用  .stop  阻止冒泡 -->
    <div class="inner" @click="handler('div')">
        <input type="button" value="戳他" @click.stop="handler('btn')">
    </div>
    
  • .prevent 阻止默认行为,即如下例子,添加了.prevent修饰符,,会阻止页面跳转,使a标签失效

    <!-- 使用 .prevent 阻止默认行为 -->
    <a href="http://www.baidu.com" @click.prevent="linkClick">有问题,先去百度</a>
    
  • .capture

    <!-- 使用  .capture 实现捕获触发事件的机制 -->
        <div @click.capture="handler('div1')">
        <div class="inner" @click.capture="handler('div2')">
            <input type="button" value="戳他" @click="handler('btn')"/>
         </div>
    	</div>
    
    <!--
    不加.captrue时,结果为 btn, div2, div1
    加了.captrue时,结果为 div2 , btn , div1 
    -->
    
  • .self

    <!-- 使用 .self 实现只有点击当前元素时候,才会触发事件处理函数 -->
    <div class="inner" @click.self="handler('div1')">
        <input type="button" value="戳他" @click="handler('btn')">
    </div>
    <!-- 
    不加.self时,结果为: btn, btn1
    加了.self时,结果为: btn
    -->
    
  • .once

    <!-- 使用 .once 只触发一次事件处理函数 -->
    <a href="http://www.baidu.com" @click.prevent.once="linkClick">有问题,先去百度</a>
    
    <!--
    使.prevent修饰符,只成功一次,第二次a标签的默认动作,就会恢复
    -->
    
  • .passive

    <!--
      	passive这个修饰符会执行默认方法。你们可能会问,明明默认执行为什么会设置这样一个修饰符。这就要说一下这个修饰符的本意了。
    	【浏览器只有等内核线程执行到事件监听器对应的JavaScript代码时,才能知道内部是否会调用preventDefault函数来阻止事件的默认行为,所以浏览器本身是没有办法对这种场景进行优化的。这种场景下,用户的手势事件无法快速产生,会导致页面无法快速执行滑动逻辑,从而让用户感觉到页面卡顿。】
       	通俗点说就是每次事件产生,浏览器都会去查询一下是否有preventDefault阻止该次事件的默认动作。我们加上passive就是为了告诉浏览器,不用查询了,我们没用preventDefault阻止默认动作。
    	这里一般用在滚动监听,@scoll,@touchmove 。因为滚动监听过程中,移动每个像素都会产生一次事件,每次都使用内核线程查询prevent会使滑动卡顿。我们通过passive将内核线程查询跳过,可以大大提升滑动的流畅度
    	passive和prevent冲突,不能同时绑定在一个监听器上
    -->
    
  • .sync 修饰符

    
    

data 必须是一个函数

一个组件的 data 选项必须是一个函数,因此每个实例可以维护一份被返回对象的独立的拷贝:

非Prop的Attribute

Attribute继承

当组件返回的单个根节点时,非prop attribute 将自动添加到根节点的attribute中

app.component('date-picker', {
    template: `
        <div class="date-picker">
      <input type="datetime" />
        </div>
    `
})


<date-picker data-status="activated"></date-picker>

// 渲染
<div class="date-picker" data-status="activated">
  <input type="datetime" />
</div>

同样的规则使用于事件监听器

<date-select @change="showChange"></date-select>


let app = Vue.createApp({
  methods: {
    showChange(event) {
      console.log("event", event)
      console.log(event.target.value)
    }
  }
})

app.component('date-select', {
  template: `
    <select>
      <option value="1">Yesterday</option>
      <option value="2">Today</option>
      <option value="3">Tomorrow</option>
    </select>
  `
})

禁用Attribute继承

app.component('date-picker', {
  inheritAttrs: false,
  template: `
    <div class="date-picker">
      <input type="datetime" v-bind="$attrs" />
    </div>
  `
})

<date-picker data-status="activated"></date-picker>

// 渲染
<div class="date-picker">
  <input type="datetime"  data-status="activated" />
</div>

多个根节点上的Attribute继承

与单个根节点组件不同,具有多个根节点的组件不具有自动attribute回退行为。如果未显式绑定$attrs,将发生运行时警告。

<custom-layout id="custom-layout" @click="changeValue"></custom-layout>

// 警告
app.component('custom-layout', {
  template: `
    <div class="one">one</div>
    <div class="two">two</div>
    <div class="three">three</div>
  `
})

// 没有警告,$attrs被传递到two元素
app.component('custom-layout', {
  template: `
    <div class="one">one</div>
    <div class="two" v-bind="$attrs">two</div>
    <div class="three">three</div>
  `
})

将原生事件绑定到组件

在组件上使用事件的时候,事件会默认绑定在组件内部最外城的根标签上面;

解决方案:

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script>
</head>

<body>
    <div id="app">
        <hello @change="handleChange"></hello>
    </div>
    <script>
        Vue.component('hello', {
            data: function () {
                return {
                    msg: ''
                }
            },
            template: '<div>{{msg}}<input type="text" v-model="msg"  v-on="inputListeners"></div>',
            computed: {
                inputListeners: function () {
                    var vm = this
                    // `Object.assign` 将所有的对象合并为一个新对象
                    return Object.assign({},
                        // 我们从父级添加所有的监听器
                        this.$listeners,
                        // 然后我们添加自定义监听器,
                        // 或覆写一些监听器的行为
                        {
                            // 这里确保组件配合 `v-model` 的工作
                            input: function (event) {
                                vm.$emit('input', event.target.value)
                            }
                        }
                    )
                }
            }
        })


        var app = new Vue({
            el: '#app',
            methods: {
                handleChange() {
                    console.log(123)
                }
            }
        })
    </script>
</body>

</html>

keep-alive

每次切换,组件不会重置

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script>
</head>

<body>
    <div id="app">
        <button @click="handleClick">切换</button>
        ```{{msg}}````
        <keep-alive>
        <component :is="com"></component>
    </keep-alive>
    </div>
    <script>
        Vue.component('hello', {
            data: function () {
                return {
                    msg: ''
                }
            },  
            template: '<div>{{msg}}<input type="text" v-model="msg" @change="handleChange"></div>',
            methods: {
                handleChange() {
                    this.$emit('heng',this.msg)
                }
            }
        })

        Vue.component('hello2', {
            data: function () {
                return {
                    msg: ''
                }
            },  
            template: '<div>{{123}}</div>',
            methods: {
                handleChange() {
                    this.$emit('heng',this.msg)
                }
            }
        })


        var app = new Vue({
            el: '#app',
            data: {
                msg:'123',
                com:'hello'
            },
            methods: {
                handleChange() {
                    console.log(123)
                },
                handleClick() {
                    this.com = this.com == 'hello' ?'hello2':'hello'
                }
            }
        })
    </script>
</body>

</html>

依赖注入

父传孙子的便捷方法

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script>
</head>

<body>
    <div id="app">
        <button @click="handleClick">切换</button>
        ```{{msg}}````
        <keep-alive>
        <component :is="com"></component>
    </keep-alive>
    </div>
    <script>
        Vue.component('hello', {
            data: function () {
                return {
                    msg: ''
                }
            },  
            template: '<div><hello2></hello2><input type="text" v-model="msg" @change="handleChange"></div>',
            methods: {
                handleChange() {
                    this.$emit('heng',this.msg)
                }
            }
        })

        Vue.component('hello2', {
            data: function () {
                return {
                    msg: ''
                }
            },  
            template: '<div>我是hello2{{test}}</div>',
            methods: {
                handleChange() {
                    this.$emit('heng',this.msg)
                }
            },
            inject:['test']

        })


        var app = new Vue({
            el: '#app',
            data: {
                msg:'123',
                com:'hello'
            },
            methods: {
                handleChange() {
                    console.log(123)
                },
                handleClick() {
                    this.com = this.com == 'hello' ?'hello2':'hello'
                }
            },
            provide: function() {
                return {
                    test:'--我是provide传递过来的--'
                }
            }
        })
    </script>
</body>

</html>

强制更新

$forceUpdate

过滤

{{ msg | capitalize}}

filters: {
    capitalize: function (value) {
        if (value == '123') return '我被锅炉了'
        return value
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值