这篇博客记录实习的所见所闻2 8.在react native
中使用context
和使用DeviceEventEmitter
的区别
React Native
中的 Context
和 DeviceEventEmitter
都是用于在组件之间共享数据和通信的工具,但它们的使用场景和特点略有不同。
Context
是 React
的核心特性之一,它可以让我们在组件树中传递数据而无需手动逐级传递。通过创建一个 Context
对象,并使用 Provider
组件将值传递给子组件,我们可以轻松地实现跨组件传递数据。在 React Native
中,Context
通常用于管理全局状态或主题样式等应用级别的配置信息。以下是一个使用 Context
在 React Native
中共享全局状态的示例代码:
import React , { createContext, useState } from 'react' ;import { View , Text , Button } from 'react-native' ;const CounterContext = createContext ();function MyComponent ( ) { const [count, setCount] = useState (0 ); return ( <CounterContext.Provider value ={{ count , setCount }}> <View > <Text > Count: {count}</Text > <Button title ="Increment" onPress ={() => setCount(count + 1)} /> <ChildComponent /> </View > </CounterContext.Provider > ); } function ChildComponent ( ) { const { count, setCount } = useContext (CounterContext ); return ( <View > <Text > Count: {count}</Text > <Button title ="Decrement" onPress ={() => setCount(count - 1)} /> </View > ); }
在这个例子中,我们首先定义了一个名为CounterContext
的 Context
对象,并在MyComponent
中使用 Provider
组件将 count
和 setCount
值传递给子组件。然后,在 ChildComponent
中,我们使用 useContext
钩子来获取 count
和 setCount
值,并在渲染组件时使用它们。
相比之下,DeviceEventEmitter
是 React Native
中用于在原生平台和 JavaScript
代码之间进行通信的工具。通过在原生代码中发送事件消息,我们可以在 JavaScript
代码中监听并处理这些事件。在 React Native
中,DeviceEventEmitter
通常用于实现与原生模块之间的通信或跨原生模块的通信。
addListener
发起监听
this .subscription = DeviceEventEmitter .addListener ('UserEnvChangedNoti' , fetchData)
emit
事件触发
DeviceEventEmitter .emit ('UserEnvChangedNoti' )
removeSubscription
移除特定监听
DeviceEventEmitter .removeSubscription (this .subscription )
removeAllListeners
移除所有监听
DeviceEventEmitter .removeAllListeners ()
removeCurrentListener
移除当前监听
const subscription = emitter.addListenerMap ({ someEvent : function (data, event ) { console .log (data); emitter.removeCurrentListener (); } }); emitter.emit ('someEvent' , 'abc' ); emitter.emit ('someEvent' , 'def' );
removeListener
移除指定事件的监听
DeviceEventEmitter .removeListener ('UserEnvChangedNoti' ,fetchData)
once
一次性监听
DeviceEventEmitter .once ('UserEnvChangedNoti' , fetchData)
listeners
返回一个当前事件
DeviceEventEmitter .listeners ('UserEnvChangedNoti' )
9. $set方法的使用場景以及使用案例(Vue2,Vue3)
在 Vue.js
中,数据的响应式更新是通过侦听对象属性的变化来实现的。但是,在某些情况下,如果我们直接修改了数组或对象中的元素(深層次的數據結構或者該響應式數據中不存在的對象屬性和數組子項),Vue.js
将无法检测到这些变化,从而无法触发视图的重新渲染。为了解决这个问题,Vue.js
提供了 $set
方法,可以动态添加新的响应式属性,并通知 Vue.js
重新渲染相关的视图组件。具体来说,当您需要向已有的对象或数组中添加新的属性或元素时,应该使用 $set
方法进行操作。
Vue2 <div id ="app" > <ul > <li v-for ="(item, index) in list" :key ="index" > {{ item }}</li > </ul > </div > <script > new Vue ({ el : '#app' , data ( ) { return { list : ['apple' , 'banana' ] } }, mounted ( ) { setTimeout (() => { this .$set(this .list , 2 , 'orange' ) }, 1000 ) } }) </script >
在上述代码中,我们定义了一个名为 list
的数组,并在 mounted
钩子函数中使用 setTimeout
延迟 1 秒钟来添加一个新元素 ‘orange
‘。为了确保 Vue.js
能够正确检测到这个变化,我们使用 $set
方法来添加新元素。具体来说,我们传递了三个参数:数组对象、要添加的索引位置和新元素的值。这样,Vue.js
将自动检测到数组的变化,并重新渲染视图。
對象修改$set
(Vue2
) <div id ="app" > <p > {{ user.name }}</p > </div > <script > new Vue ({ el : '#app' , data ( ) { return { user : { name : 'Alice' , age : 18 } } }, mounted ( ) { setTimeout (() => { this .$set(this .user , 'name' , 'Bob' ) }, 1000 ) } }) </script >
在上述代码中,我们定义了一个名为 user
的对象,并在mounted
钩子函数中使用 setTimeout
延迟 1 秒钟来将 user
对象的 name
属性修改为 ‘Bob
‘。为了确保Vue.js
能够正确检测到这个变化,我们使用 $set
方法来修改该属性。具体来说,我们传递了三个参数:对象、要修改的属性名和新的属性值。这样,Vue.js
将自动检测到数据的变化,并重新渲染视图。
Vue3
中的$set
被更名爲set
使用方法与Vue2一致<template > <div > <ul > <li v-for ="(item, index) in list" :key ="index" > {{ item }}</li > </ul > <button @click ="addItem" > Add Item</button > </div > </template > <script > import { defineComponent, reactive, set } from 'vue' export default defineComponent ({ setup ( ) { const state = reactive ({ list : ['apple' , 'banana' ] }) const addItem = ( ) => { set (state.list , state.list .length , 'orange' ) } return { list : state.list , addItem } } }) </script >
10. Vue中nextTick的作用以及在開發中的使用場景
在 Vue.js
中,当您修改了组件的数据后,Vue.js
并不会立即更新视图。相反,Vue.js
会将这些更新推迟到下一个“事件循环”时才执行(也称为“异步更新”)。这是因为 Vue.js
需要等待当前的代码执行完成,并且需要将多个更新合并成一个批处理操作,以便提高性能和效率。
如果您想要在下一个“事件循环”中访问已经更新的DOM
或Vue
组件,应该使用 nextTick
方法。nextTick
方法可以在下一个“事件循环”时执行一个回调函数,并确保当回调函数被调用时,Vue.js
已经完成了所有的异步更新操作。
nextTick
方法在 Vue.js
中非常常用,在以下几个场景下尤其有用:
在修改数据后,需要访问已经更新的 DOM 元素。例如,您可能想要获取某个元素的宽度或高度,并根据它们进行其他操作。
在异步更新 DOM 后,需要执行一些额外的操作。例如,您可能希望在列表中添加一个新项目后,滚动到该项目所在的位置。
在父组件监听子组件中的事件时,需要等待 Vue.js 重新渲染子组件之后才能访问子组件的数据或方法。
在使用第三方库或插件时,需要确保 Vue.js 已经完成了所有的异步更新操作,以避免出现意料之外的问题。
除了上述场景外,nextTick
方法还可以用于优化性能和提高用户体验。例如,在加载大量数据或执行复杂计算时,您可以使用 nextTick
方法将这些操作推迟到下一个“事件循环”时执行,以避免阻止主线程并提高应用程序的响应速度。
基本使用
<template > <div > <p ref ="message" > {{ message }}</p > <button @click ="changeMessage" > Change Message</button > </div > </template > <script > import { defineComponent, nextTick } from 'vue' export default defineComponent ({ data ( ) { return { message : 'Hello, Vue!' } }, methods : { changeMessage ( ) { this .message = 'Hello, World!' nextTick (() => { console .log (this .$refs .message .textContent ) }) } } }) </script >
<template > <div > <p ref ="message" > {{ message }}</p > <button @click ="changeMessage" > Change Message</button > </div > </template > <script > import { defineComponent, nextTick } from 'vue' export default defineComponent ({ data ( ) { return { message : 'Hello, Vue!' } }, methods : { async changeMessage ( ) { this .message = 'Hello, World!' await nextTick () console .log (this .$refs .message .textContent ) } } }) </script >