当前位置:   article > 正文

Vue3.x API_app.config.performance

app.config.performance

一、Application Config(app.config)

config是一个包含Vue应用程序全局配置的对象。可以在挂载应用程序之前修改下面列出的属性:

const app = Vue.createApp({})
app.config = {...}
  • 1
  • 2

1、devtools

  • 类型: boolean
  • 默认值: true (false in production builds)
  • 使用:
app.config.devtools = true
  • 1

配置是否允许vue-devtools检查。此选项的默认值在开发版本中为true,在生产版本中为false。您可以将其设置为true以启用对生产版本的检查。

2、errorHandler

  • 类型: Function
  • 默认值: undefined
  • 使用:
app.config.errorHandler = (err, vm, info) => {
  // handle error
  // info是Vue特定的错误信息,例如 在哪个生命周期挂钩中发现错误
}
  • 1
  • 2
  • 3
  • 4

为组件渲染功能和观察程序期间的未捕获错误分配处理程序。

3、warnHandler

  • 类型: Function
  • 默认值: undefined
  • 使用:
app.config.warnHandler = function(msg, vm, trace) {
  // trace是组件层次结构跟踪
}
  • 1
  • 2
  • 3

为运行时Vue警告分配自定义处理程序。这仅在开发期间有效,在生产中将被忽略。

4、globalProperties 全局属性

  • 类型: [key: string]: any
  • 默认值: undefined
  • 使用:
app.config.globalProperties.foo = 'bar'

app.component('child-component', {
  mounted() {
    console.log(this.foo) // 'bar'
  }
})
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

冲突时,组件的属性将具有优先权

在 vue2.x 中是 Vue.prototype

// 2.x
Vue.prototype.$http = () => {}

// 3.x
const app = Vue.createApp({})
app.config.globalProperties.$http = () => {}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

5、isCustomElement

  • 类型: (tag: string) => boolean
  • 默认值: undefined
  • 使用:
app.config.isCustomElement = tag => tag.startsWith('ion-')
  • 1

指定一种方法来识别在Vue之外定义的自定义元素(例如,使用Web组件API)。 如果component符合此条件,则不需要本地或全局注册,并且Vue不会发出有关Unknown自定义元素的警告。

此功能不需要匹配所有HTML和SVG标签,Vue解析器会自动执行此检查

6、optionMergeStrategies

  • 类型: { [key: string]: Function }
  • 默认值: {}
  • 使用:
const app = Vue.createApp({
  mounted() {
    console.log(this.$options.hello)
  }
})
app.config.optionMergeStrategies.hello = (parent, child, vm) => {
  return `Hello, ${child}`
}
app.mixin({
  hello: 'Vue'
})
// 'Hello, Vue
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

自定义选项定义合并策略。

合并策略将分别在父实例和子实例上定义的该选项的值作为第一个参数和第二个参数。 上下文应用程序实例作为第三个参数传递。

7、performance

  • 类型: boolean
  • 默认值: false
  • 使用:
app.config.performance = true
  • 1

将其设置为true可在浏览器devtool性能/时间线面板中启用组件初始化,编译,渲染和补丁性能跟踪。 仅在开发模式和支持Performance.mark API的浏览器中工作。

二、Application API(app.xxx)

在Vue 3.x,全局改变Vue行为的API都在createApp方法所创建的应用程序实例中

import { createApp } from 'vue'
const app = createApp({})
  • 1
  • 2

1、component

  • 参数:
    • {string} name
    • {Function | Object} definition (optional)
  • 返回值:
    • 如果传递定义参数,则为应用程序实例
    • 如果没有传递定义参数,则为组件
  • 使用:
    • 注册或检索全局组件。 注册还会使用给定的name参数自动设置组件的名称。
import { createApp } from 'vue'
const app = createApp({})
// 注册一个 options 对象
app.component('my-component', {
  /* ... */
})

// 检索注册的组件
const MyComponent = app.component('my-component')
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

2、config

包含应用程序配置的对象。(往上翻)

3、directive

  • 参数:

    • {string} name
    • {Function | Object} definition (optional)
  • 生命周期:

app.directive('my-directive', {
  // 挂载前
  beforeMount() {},
  // 挂载后
  mounted() {},
  // 更新前
  beforeUpdate() {},
  // 更新后
  updated() {},
  // 卸载前
  beforeUnmount() {},
  // 卸载后
  unmounted() {}
})
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
生命周期钩子函数所具有的参数
1、el

绑定的DOM元素

2、binding
  • instance:使用伪指令的组件的实例。
  • value:传递给指令的值。
  • oldValue:以前的值,仅在beforeUpdate和updated中可用。
  • arg:传递给指令的参数。
  • modifiers:包含修饰符的对象。
  • dir:一个对象,在注册指令时作为参数传递。
3、vnode

绑定的DOM所对应的虚拟节点

4、prevNode

之前的虚拟节点,仅在beforeUpdate和updated中可用

除el之外,您应该将这些参数视为只读,并且永远不要修改它们。

示例 自定义 drag 拖动指令
import { createApp } from 'vue'
import App from './App.vue'
let app = createApp(App)

app.directive('drag', {
  beforeMount (el, binding) {
    console.log(el, binding)
    let oDiv = el;   //当前元素
    oDiv.onmousedown = function (e) {
     //鼠标按下,计算当前元素距离可视区的距离
      let disX = e.clientX - oDiv.offsetLeft;
      let disY = e.clientY - oDiv.offsetTop;
      document.onmousemove = function (e) {
        //通过事件委托,计算移动的距离 
        let l = e.clientX - disX;
        let t = e.clientY - disY;
        //移动当前元素  
        oDiv.style.left = l + 'px';
        oDiv.style.top = t + 'px';
         //将此时的位置传出去
        binding.value({x:e.pageX,y:e.pageY}, el)
      };
      document.onmouseup = function () {
        document.onmousemove = null;
        document.onmouseup = null;
      };
    };
  }
})
app.mount('#app')
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30

template中使用

<template>
    <div v-drag="dragFun" class="div1"></div>
</template>
<script>
export default {
    setup() {
        let dragFun = (val, e) => {
            console.log(val, e)
            // val 是 在binging.value 的值
            // e 是对应的element元素
        }
        return {
            dragFun
        }
    }
}
</script>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17

4、mixin

  • 参数: {Object} mixin
  • 使用:

在整个应用范围内应用mixin。一旦注册,它们就可以在当前应用程序中任何组件的模板中使用。

5、mount

  • 参数:
    • {Element | string} rootContainer
    • {boolean} isHydrate (optional)

挂载到跟组件上

import { createApp } from 'vue'
const app = createApp({})
app.mount('#app')
  • 1
  • 2
  • 3

6、provide

  • 参数:
    • {string | Symbol} key
    • value

设置一个可以注入到应用程序内组件中的值。组件应使用注入来接收提供的值。

provide 和 inject 不是反应性的

import {provide} from 'vue'
setup() {
    provide('city', '杭州')
    provide('person', {
        name: 'Bob',
        age: 18
    })
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

7、inject

  • 参数:
    • {string | Symbol} key
    • 没有获取到时的默认值
import {inject} from 'vue'
setup() {
    let city = inject('city')
    let person = inject('person')
	let noProvide = inject('noProvide', 'noProvide hah')
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

8、unmount

  • 参数: {Element | string} rootContainer

卸载

import { createApp } from 'vue'
const app = createApp({})
app.mount('#app')
// 5 秒钟之后卸载
setTimeout(() => app.unmount('#app'), 5000)
  • 1
  • 2
  • 3
  • 4
  • 5

9、use

  • 参数:
    • {Object | Function} plugin
    • …options (optional)

使用 Vue 其他插件

//2.x
Vue.use(router)

//3.x
import { createApp } from 'vue'
const app = createApp({})
app.use(router)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

三、Global API(全局API)

1、createApp

返回一个组件实例

const app = Vue.createApp({})
  • 1

接收根组件选项对象作为第一个参数:

const app = Vue.createApp({
  data() {
    return {}
  },
  methods: {},
  computed: {}
})
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

第二个参数,我们可以将根 props 传递给应用程序

const app = Vue.createApp(
  {
    props: ['username']
  },
  { username: 'Evan' }
)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
<div id="app">
  {{ username }}
</div>
  • 1
  • 2
  • 3

2、h

返回一个返回的“虚拟节点”,通常缩写为VNode。

render() {
  return Vue.h('h1', {}, 'Some title')
}
  • 1
  • 2
  • 3
参数
  • tag
    • 类型:String | Object | Function | null
    • 具体值:一个HTML的标签名、组件、异步组件、null;此参数是必须的。
  • props
    • 类型:Object
    • 具体值:模版中将使用到的属性、props或者元素
  • children
    • 类型:String | Array | Object
    • 具体值:子虚拟节点,使用h()返回的值,或者一个插槽
h('div', {}, [
  'Some text comes first.',
  h('h1', 'A headline'),
  h(MyComponent, {
    someProp: 'foobar'
  })
])
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

3、defineComponent

参数
  • 类型 一个 component options 的 对象
import { defineComponent } from 'vue'
const MyComponent = defineComponent({
  data() {
    return { count: 1 }
  },
  methods: {
    increment() {
      this.count++
    }
  }
})
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

4、defineAsyncComponent

异步组件

参数
对于基本用法,defineAsyncComponent可以接受返回Promise的工厂函数。
import { defineAsyncComponent } from 'vue'

const AsyncComp = defineAsyncComponent(() =>
    import('./components/AsyncComponent.vue')
)

app.component('async-component', AsyncComp)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
使用本地注册时,您还可以直接提供一个返回Promise的函数:
components: {
    AsyncComponent: defineAsyncComponent(() =>
        import('./components/AsyncComponent.vue')
    )
}
  • 1
  • 2
  • 3
  • 4
  • 5
对于高级用法,defineAsyncComponent可以接受一个对象:
const AsyncComp = defineAsyncComponent({
  // 工厂函数
  loader: () => import('./Foo.vue')
  // 加载异步组件时要使用的组件
  loadingComponent: LoadingComponent,
  // 加载失败时使用的组件
  errorComponent: ErrorComponent,
  // 显示加载组件之前的延迟。 默认值:200ms。
  delay: 200,
  // 如果提供并超过了超时,则将显示错误组件。 默认值:无穷大
  timeout: 3000,
  // 一个返回布尔值的函数,该值指示加载程序承诺拒绝时异步组件是否应重试
  retryWhen: error => error.code !== 404,
  // 允许的最大重试次数
  maxRetries: 3,
  // 定义组件是否
  suspensible: false
})
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18

5、resolveComponent

resolveComponent 只能在 render 或者 setup 中使用

参数

一个 component

import { resolveComponent } from 'vue'
render() {
  const MyComponent = resolveComponent('MyComponent')
}
  • 1
  • 2
  • 3
  • 4

6、resolveDynamicComponent

resolveDynamicComponent 只能在 render 或者 setup 中使用

参数

一个 component

import { resolveDynamicComponent } from 'vue'
render () {
  const MyComponent = resolveDynamicComponent('MyComponent')
}
  • 1
  • 2
  • 3
  • 4

7、resolveDirective

resolveDirective 只能在 render 或者 setup 中使用

参数

接收一个 指令名称

const app = Vue.createApp({})
app.directive('highlight', {})

import { resolveDirective } from 'vue'
render () {
  const highlightDirective = resolveDirective('highlight')
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

8、withDirectives

withDirectives 只能在 render 或者 setup 中使用

参数
  • 虚拟节点 使用h()创建的虚拟节点
  • 自定义指令 一个自定义指令数组
import { withDirectives, resolveDirective } from 'vue'
const foo = resolveDirective('foo')
const bar = resolveDirective('bar')

return withDirectives(h('div'), [
  [foo, this.x],
  [bar, this.y]
])
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
const MyDirective = resolveDirective('MyDirective')
const nodeWithDirectives = withDirectives(
  h('div'), 
  [ [MyDirective, 100, 'click', { prevent: true }] ]
)
  • 1
  • 2
  • 3
  • 4
  • 5

9、createRenderer

自定义渲染平台

参数
  • HostNode
  • HostElement
import { createRenderer } from 'vue'
const { render, createApp } = createRenderer<Node, Element>({
  patchProp,
  ...nodeOps
})
  • 1
  • 2
  • 3
  • 4
  • 5

10、nextTick

异步更新队列

import { createApp, nextTick } from 'vue'

const app = createApp({
  setup() {
    const message = ref('Hello!')
    const changeMessage = async newMessage => {
      message.value = newMessage
      await nextTick()
      console.log('Now DOM is updated')
    }
  },
  methods: {
    this.$nextTick(() => {
      // ...
    })
  }
})
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17

四、Options

1、Data

1. data

类型:Function

const data = { a: 1 }
const vm = Vue.createApp({
  data() {
    return data
  }
}).mount('#app')

//或者

data: vm => ({ a: vm.myProp })
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
2. props

类型:Array | Object

当使用 Object 的时候:

  • type: 传入的类型;[String, Number, Boolean, Array, Object, Date, Function, Symbol]
  • default: 默认值;[any]
  • required: 是否必须;[Boolean]
  • validator: 验证是否满足;[Function] 返回true和false
props: {
    age: {
        type: Number,
        default: 0,
        required: true,
        validator: value => {
            return value >= 0
        }
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
3. computed

计算属性

类型:{ [key: string]: Function | { get: Function, set: Function } }

计算的属性的值会被缓存,并且仅在响应性依赖项更改时重新计算。

computed: {
    aDouble() {
        return this.a * 2
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
4. methods

组件方法

类型:{ [key: string]: Function }

methods: {
    checkVal () {
        return true
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
5. watch

监听

类型:{ [key: string]: string | Function | Object | Array}

watch: {
    dataA (val, oldVal) {
        console.log(val, oldVal)
    },
    // 在 methods 里面的方法
    dataB: 'someMethod',
    // 深度监听
    dataC: {
        handler(val, oldVal) {
            console.log('c changed')
        },
        deep: true
    },
    // 立即执行
    dataD: {
        handler(val, oldVal) {
            console.log('d changed')
        },
        immediate: true
    },
    // 传入一个数组
    dataE: [
        'handle1',
        function handle2(val, oldVal) {
            console.log('handle2 triggered')
        },
        {
            handler: function handle3(val, oldVal) {
                console.log('handle3 triggered')
            }
        }
    ]
},
methods: {
    someMethod() {
        console.log('b changed')
    },
    handle1() {
        console.log('handle 1 triggered')
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41

不能使用箭头函数来定义watch

6. emits

自组件通过 emit 的事件列表

类型:Array | Object

当为对象时可以验证传入的值是否有效

const app = Vue.createApp({})
// 当为数组时
app.component('todo-item', {
  emits: ['check'],
  created() {
    this.$emit('check')
  }
})

// 当为一个对象时
app.component('reply-form', {
  emits: {
    click: null,
    submit: payload => {
      if (payload.email && payload.password) {
        return true
      } else {
        console.warn(`Invalid submit event payload!`)
        return false
      }
    }
  }
})
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23

2、生命周期钩子函数

1. beforeCreate

组件实例创建之前,data、event、watcher 不能调用

2. created

组件实例创建之后,data、event、watcher可以使用

$el属性不能调用,不能操作DOM

3. beforeMount

组件实例挂载之前立即被调用:render函数将被首次调用

在服务器端渲染期间不会调用此钩子函数。

4. mounted

组件实例挂载之后调用

mounted不能保证所有子组件也都已安装。 如果要等到整个视图渲染完毕,可以在mount的内部使用vm.$nextTick

在服务器端渲染期间不会调用此钩子函数。

5. beforeUpdate

组件实例更新之前

在服务器端渲染期间不会调用此钩子函数。

6. updated

组件更新之后

更新并不能保证所有子组件也都已重新呈现。如果要等到整个视图重新渲染后,可以在更新后使用vm.$nextTick

在服务器端渲染期间不会调用此钩子函数。

7. activated

kept-alive 组件激活时的钩子函数

在服务器端渲染期间不会调用此钩子函数。

8. deactivated

kept-alive 组件卸载时的钩子

在服务器端渲染期间不会调用此钩子函数

9. beforeUnmount

卸载之前调用

在服务器端渲染期间不会调用此钩子函数

10. unmounted

卸载之后调用,调用此钩子后,组件实例的所有指令均已解除绑定,所有事件侦听器均已删除,所有子组件实例也已卸载。

在服务器端渲染期间不会调用此钩子函数

11. errorCaptured

类型: (err: Error, instance: Component, info: string) => ?boolean

当捕获到任何后代组件的错误时调用。挂钩接收三个参数:错误,触发错误的组件实例以及包含有关捕获错误的位置信息的字符串。 挂钩可以返回false,以阻止错误进一步传播。

  • 默认情况下,所有错误仍将发送到全局config.errorHandler(如果已定义)。
  • 如果组件的继承链或父链上存在多个errorCaptured挂钩,则将在同一错误上调用所有它们。
  • 如果errorCaptured挂钩本身抛出错误,则此错误和原始捕获的错误都将发送到全局config.errorHandler。
  • errorCaptured挂钩可以返回false,以防止错误进一步传播。
12. renderTracked

虚拟dom 被 tracked 时调用

renderTracked({ key, target, type }) {}
  • 1
13. renderTriggered

触发虚拟DOM重新呈现时调用

renderTriggered({ key, target, type }) {}
  • 1

五、示例方法

1、$watch

参数
  • {string | Function} source
  • {Function | Object} callback
  • {Object} options (optional)
    • {boolean} deep
    • {boolean} immediate

$watch返回一个unwatch函数,该函数停止触发监听

const unwatch = vm.$watch('a', cb)
// 5秒钟之后停止监听
setTimeout(() => {
    unwatch()
}, 5000)
  • 1
  • 2
  • 3
  • 4
  • 5

2、$emit

参数
  • {string} eventName
  • …args (optional)
<button v-on:click="$emit('give-advice', adviceText)">
    Click but
</button>
  • 1
  • 2
  • 3

3、$forceUpdate

强制重新渲染组件实例。它不会影响所有子组件,只会影响实例本身和插入了插槽内容的子组件。

触发之后 会触发 updated() 钩子函数

4、$nextTick

参数
  • {Function} callback (optional)

在下一个DOM更新周期后执行的回调。

methods: {
    example() {
        this.$nextTick(() => {})
    }
  }
  • 1
  • 2
  • 3
  • 4
  • 5

六、反应性API

1、Reactivity APIs

1. reactive

返回一个对象的反应性拷贝数据

const person = reactive({
    name: 'Bob',
    age: 18
})
  • 1
  • 2
  • 3
  • 4

基于 ES6 的Proxy代理实现

2. readonly

返回一个只读的对象,或者只读的ref

const ref1 = ref(0)
const read1 = readonly({
	read: 'only'
})
const read2 = readonly(ref1)

read1.read = 'change'
// ⚠️ reactivity.esm-bundler.js?a1e9:301 Set operation on key "read" failed: target is readonly
read2.value = 10
// ⚠️ Set operation on key "value" failed: target is readonly.
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
3. isProxy

检查代理对象是由 reactive 还是 readonly 创建的,返回 true 和 false

const ref1 = ref(0)
const book = reactive({
	title: 'this is vue3'
})
const read1 = readonly({
	read: 'only'
})
console.log(isProxy(ref1), isProxy(book), isProxy(read1))
// false true true 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
4. isReactive

检查代理对象是否由 reactive 创建的,返回 true 和 false

const ref1 = ref(0)
const book = reactive({
	title: 'this is vue3'
})
const read1 = readonly({
	read: 'only'
})
console.log(isReactive(ref1), isReactive(book), isReactive(read1))
// false true false
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

如果一个对象是由 readonly 创建的 reactive 对象,则返回的也是 true

let react = reactive({
	name: 'Bob'
})
let react1 = readonly(react)
console.log(isProxy(react1), isReactive(react1))
// true true 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
5. isReadonly

检查代理对象是不是 readonly,返回 true 和 false

const ref1 = ref(0)
const read1 = readonly({
	read: 'only'
})
let react = reactive({
	name: 'Bob'
})
let react1 = readonly(react)
const ref2 = readonly(ref1)
console.log(isReadonly(react1), isReadonly(read1), isReadonly(ref2))
// true true true
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
6. toRaw

返回反应式或只读代理的原始原始对象。可用于临时读取而不会产生代理访问/跟踪开销,也可用于写入而不会触发更改。 不建议保留对原始对象的持久引用。 请谨慎使用。

let obj = {a: 1}
let reactObj = reactive(obj)

let toRawObj = toRaw(obj)

let toRawObj1 = toRaw(reactObj)

console.log(obj, reactObj, toRawObj, toRawObj1, toRawObj === obj, toRawObj1 === obj, toRawObj === toRawObj1)
// {a: 1} Proxy {a: 1} {a: 1} {a: 1} true true true

setTimeout(() => {
	obj.a = 2
	console.log(obj, reactObj, toRawObj, toRawObj1, toRawObj === obj, toRawObj1 === obj, toRawObj === toRawObj1)
	// {a: 2} Proxy {a: 2} {a: 2} {a: 2} true true true
}, 1000)

setTimeout(() => {
	reactObj.a = 3
	console.log(obj, reactObj, toRawObj, toRawObj1, toRawObj === obj, toRawObj1 === obj, toRawObj === toRawObj1)
	// {a: 3} Proxy {a: 3} {a: 3} {a: 3} true true true
}, 2000)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
7. markRaw

标记一个对象,使其永远不会转换为代理。 返回对象本身。

let obj = {a: 1}
let reactObj = reactive(obj)

let toRawObj = markRaw(obj)

let toRawObj1 = markRaw(reactObj)

console.log(obj, reactObj, toRawObj, toRawObj1, toRawObj === obj, toRawObj1 === obj, toRawObj === toRawObj1)
// {a: 1, __v_skip: true}a: 3__v_skip: true__proto__: Object Proxy {a: 1, __v_skip: true} {a: 1, __v_skip: true} Proxy {a: 1, __v_skip: true} true false false

setTimeout(() => {
	obj.a = 2
	console.log(obj, reactObj, toRawObj, toRawObj1, toRawObj === obj, toRawObj1 === obj, toRawObj === toRawObj1)
	// {a: 2, __v_skip: true}a: 3__v_skip: true__proto__: Object Proxy {a: 2, __v_skip: true} {a: 2, __v_skip: true}a: 3__v_skip: true__proto__: Object Proxy {a: 2, __v_skip: true} true false false
}, 1000)

setTimeout(() => {
	reactObj.a = 3
	console.log(obj, reactObj, toRawObj, toRawObj1, toRawObj === obj, toRawObj1 === obj, toRawObj === toRawObj1)
	// {a: 3, __v_skip: true} Proxy {a: 3, __v_skip: true} {a: 3, __v_skip: true} Proxy {a: 3, __v_skip: true} true false false
}, 2000)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
8. shallowReactive

创建一个反应式代理,该反应式代理跟踪其自身属性的反应性,但不执行嵌套对象的深度反应式转换。

const book = reactive({
	title: 'this is vue3',
	address: {
		city: 'hz',
		area: 'bj'
	}
})
console.log(isReactive(book.address))
// true
const obj = shallowReactive({
	name: 'Bob',
	age: 18,
	address: {
		city: 'hz',
		area: 'bj'
	}
})
console.log(isReactive(obj.address))
// false
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
9. shallowReadonly

创建一个代理,使其自身的属性为只读,但不执行嵌套对象的深度只读转换。

const book = readonly({
	title: 'this is vue3',
	address: {
		city: 'hz',
		area: 'bj'
	}
})
console.log(isReadonly(book.address))
// true
const obj = shallowReadonly({
	name: 'Bob',
	age: 18,
	address: {
		city: 'hz',
		area: 'bj'
	}
})
console.log(isReadonly(obj.address))
// false
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19

2、Refs

1. ref

接受一个值并返回一个反应性且可变的ref对象。ref对象具有指向内部值的单个属性.value。

const ref1 = ref(0)

__v_isRef: true
_rawValue: 0
_shallow: false
_value: 0
value: 0

const ref2 = ref({
	name: 'Bob',
	age: 18
})

__v_isRef: true
_rawValue: {name: "Alice", age: 18}
_shallow: false
_value: Proxy {name: "Alice", age: 18}
value: Proxy
[[Handler]]: Object
[[Target]]: Object
age: 18
name: "Alice"
__proto__: Object
[[IsRevoked]]: false
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24

一般使用 ref 定义基本类型

2. unref

如果参数是 ref 则返回内部的 value 值,否则返回 参数本身,是 val = isRef(val) ? val.value : val 的语法糖

const ref1 = ref(0)
const ref2 = ref({
	name: 'Bob',
	age: 18
})
const obj = reactive({
	name: 'Alice',
	age: 20
})
console.log(unref(ref1), unref(ref2), unref(obj))
// 0
// Proxy
// Proxy
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
3. toRef

创建一个 reactive 的对象的属性 做为 ref 的引用,保持反应性连接

const obj = reactive({
	name: 'Alice',
	age: 20
})

const toR1 = toRef(obj, 'name')
const notoR2 = obj.name

setTimeout(() => {
	obj.name = 'Jack'
}, 1000)

// 1000 毫秒之后 toR1.value 值为 Jack, notoR2 的值为 Alice
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
4. toRefs

将反应对象转换为普通对象,其中所得对象的每个属性都是指向原始对象相应属性的ref。

const obj = reactive({
	name: 'Alice',
	age: 20
})

const refs1 = toRefs(obj)
console.log(refs1)
{name: ObjectRefImpl, age: ObjectRefImpl}
    age: ObjectRefImpl
        __v_isRef: true
        _key: "age"
        _object: Proxy {name: "Jack", age: 20}
        value: 20
        __proto__: Object
    name: ObjectRefImpl
        __v_isRef: true
        _key: "name"
        _object: Proxy {name: "Jack", age: 20}
        value: "Jack"
        __proto__: Object

setTimeout(() => {
	obj.name = 'Jack'
}, 1000)
// 1000 毫秒之后 refs1.name.value 的值也变为 Jack
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
5. isRef

检查是否是 ref 对象

const ref1 = ref(0)
const ref2 = ref({
	name: 'Bob',
	age: 18
})
const obj = reactive({
	name: 'Alice',
	age: 20
})

console.log(isRef(ref1), isRef(ref2), isRef(obj))
// true true false
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
6. customRef
<template>
	<div class="my-com2">
		<input v-model="text" />
	</div>
</template>

<script>
import {customRef} from 'vue'

	function useDebouncedRef(value, delay = 200) {
		let timeout
		return customRef((track, trigger) => {
			return {
				get() {
					console.log(value)
					track()
					return value
				},
				set(newValue) {
					console.log(newValue)
					clearTimeout(timeout)
					timeout = setTimeout(() => {
						value = newValue
						trigger()
					}, delay)
				}
			}
		})
	}
	export default{
		setup () {
			return {
				text: useDebouncedRef('hello')
			}
		}
	}
</script>

<style scoped>
	
</style>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
7. shallowRef
const ref1 = ref(0)
const ref2 = ref({
	name: 'Bob',
	age: 18
})
const obj = reactive({
	name: 'Alice',
	age: 20
})

const a1 = shallowRef(ref1)
const a2 = shallowRef(ref2)
const a3 = shallowRef(obj)

console.log(isReactive(a1), isReactive(a2), isReactive(a3))
// false false false
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
8. triggerRef
const s1 = shallowRef({
	name: 'Bob'
})
s1.value.name = 'Alice'
triggerRef(s1)
console.log(s1.value.name)
// Alice
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/小蓝xlanll/article/detail/239403
推荐阅读
相关标签
  

闽ICP备14008679号