这篇博客记录实习的所见所闻2

8.在react native中使用context和使用DeviceEventEmitter的区别

  • React Native 中的 ContextDeviceEventEmitter 都是用于在组件之间共享数据和通信的工具,但它们的使用场景和特点略有不同。
  • ContextReact 的核心特性之一,它可以让我们在组件树中传递数据而无需手动逐级传递。通过创建一个 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>
);
}

在这个例子中,我们首先定义了一个名为CounterContextContext 对象,并在MyComponent中使用 Provider 组件将 count setCount 值传递给子组件。然后,在 ChildComponent 中,我们使用 useContext 钩子来获取 count setCount 值,并在渲染组件时使用它们。

  • 相比之下,DeviceEventEmitterReact Native 中用于在原生平台和 JavaScript 代码之间进行通信的工具。通过在原生代码中发送事件消息,我们可以在 JavaScript 代码中监听并处理这些事件。在 React Native 中,DeviceEventEmitter 通常用于实现与原生模块之间的通信或跨原生模块的通信。
  1. addListener 发起监听

    // 语法 addListener( eventType: string, listener: (...args: any[]) => any, context?: any)

    this.subscription = DeviceEventEmitter.addListener('UserEnvChangedNoti', fetchData)
    // 可以把特定的函数放到监听器里面,哪里有需要哪里使用emit调用,复制代码
  2. emit 事件触发

    // 语法 emit(eventType: string, ...params?: any[]): void; 

    DeviceEventEmitter.emit('UserEnvChangedNoti')
    // 触发监听事件的时候调用可以传参数复制代码
  3. removeSubscription 移除特定监听

    /*
    这个使用就相当于remove()的使用 例如 上面的监听 可以直接 this.subscription.remove()
    语法 removeSubscription(subscription: EmitterSubscription)
    */
    DeviceEventEmitter.removeSubscription(this.subscription)
  4. removeAllListeners 移除所有监听

    // 语法 removeAllListeners(eventType?: string)
    DeviceEventEmitter.removeAllListeners()
  5. removeCurrentListener 移除当前监听

    /*
    要在当前事件的生命周期内调用反之它会抛出
    语法 removeCurrentListener()
    */

    const subscription = emitter.addListenerMap({
    someEvent: function(data, event) {
    console.log(data);
    emitter.removeCurrentListener();
    }
    });
    emitter.emit('someEvent', 'abc'); // logs 'abc'
    emitter.emit('someEvent', 'def'); // does not log anything
  6. removeListener 移除指定事件的监听

    // 语法 removeListener( eventType: string, listener: (...args: any[]) => any)
    DeviceEventEmitter.removeListener('UserEnvChangedNoti',fetchData)
  7. once 一次性监听

    // 语法 once(eventType: string, listener: (...args: any[]) => any, context: any)
    DeviceEventEmitter.once('UserEnvChangedNoti', fetchData)
  8. listeners 返回一个当前事件

    // 语法 listeners(eventType: string)
    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(() => {
// 在 1 秒后添加一个新元素
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(() => {
// 在 1 秒后修改 "name" 属性的值
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 需要等待当前的代码执行完成,并且需要将多个更新合并成一个批处理操作,以便提高性能和效率。
  • 如果您想要在下一个“事件循环”中访问已经更新的DOMVue组件,应该使用 nextTick 方法。nextTick 方法可以在下一个“事件循环”时执行一个回调函数,并确保当回调函数被调用时,Vue.js 已经完成了所有的异步更新操作。

nextTick 方法在 Vue.js 中非常常用,在以下几个场景下尤其有用:

  1. 在修改数据后,需要访问已经更新的 DOM 元素。例如,您可能想要获取某个元素的宽度或高度,并根据它们进行其他操作。
  2. 在异步更新 DOM 后,需要执行一些额外的操作。例如,您可能希望在列表中添加一个新项目后,滚动到该项目所在的位置。
  3. 在父组件监听子组件中的事件时,需要等待 Vue.js 重新渲染子组件之后才能访问子组件的数据或方法。
  4. 在使用第三方库或插件时,需要确保 Vue.js 已经完成了所有的异步更新操作,以避免出现意料之外的问题。

    除了上述场景外,nextTick 方法还可以用于优化性能和提高用户体验。例如,在加载大量数据或执行复杂计算时,您可以使用 nextTick 方法将这些操作推迟到下一个“事件循环”时执行,以避免阻止主线程并提高应用程序的响应速度。

基本使用

  • Vue2
<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!'

// 在下一个“事件循环”时更新 DOM
nextTick(() => {
console.log(this.$refs.message.textContent) // 输出:'Hello, World!'
})
}
}
})
</script>
  • Vue3
<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!'

// 等待组件渲染完成后再更新 DOM
await nextTick()
console.log(this.$refs.message.textContent) // 输出:'Hello, World!'
}
}
})
</script>