vue3 项目笔记

112 阅读2分钟

解决import { ref , reactive ... } 引入的问题

// 安装
npm i unplugin-auto-import -D
// 配置
import AutoImport from 'unplugin-auto-import/vite';
export default defineConfig({
    plugins: [
		vue(),
		AutoImport({
		  	imports:['vue','vue-router']
		})
	]
});

使用

<script lang="ts" setup name="OrderList"> 
// 不用import,直接使用ref 
const count = ref(0)
onMounted(
    () => { console.log('mounted===')
}) 
</script>

如遇报错

// 安装
npm i vue-global-api -D

配置

// eslintrc.js 
module.exports = {
    extends: [ 'vue-global-api' ]
}

全局挂载问题

  • vue2
Vue.prototype.$test = 50 or import something //定义全局变量test的值为50
// 使用
alert(this.$test)
  • vue3
// 配置1
import 'fun'
...
const app = createApp(App)
app.config.globalProperties.$fun1 = fun
app.mount('#app')
// 使用1
import { getCurrentInstance } from 'vue'
...
const { proxy } = getCurrentInstance()
proxy.$fun1()

↑ 报错:...类型“ComponentInternalInstance | null”

解决1:添加ts忽略

// 
// @ts-ignore
const { proxy } = getCurrentInstance()

解决2:获取上下文和全局挂载实例的时候会用到getCurrentInstance, 新建 hooks\useCurrentInstance.ts

import { ComponentInternalInstance, getCurrentInstance } from 'vue'
...
export default function useCurrentInstance() {
    const { appContext } = getCurrentInstance() as ComponentInternalInstance
    const globalProperties = appContext.config.globalProperties
    return {
        globalProperties
    }
}

组件中使用

// 先引入文件
import useCurrentInstance from "@/hooks/useCurrentInstance";
...
// 在setup 中使用处理
const { globalProperties } = useCurrentInstance();

不要在getCurrentInstance() 中获取ctx来使用element等,生成环境下结构就不一样,会报undefined。可以使用proxy.

// 配置2 挂载方式
import 'fun'

app.provide('$myFun', fun)
// 使用2
const proxy: any = inject('$myFun')
proxy()

watchEffect

在响应式地跟踪其依赖项时立即运行一个函数,并在更改依赖项时重新运行它

  • watch- 显式指定依赖源,依赖源更新时执行回调函数
  • watchEffect - 自动收集依赖源,依赖源更新时重新执行自身
watchEffect(
  () => { /* 依赖源同时是回调函数 */ }
)
watch(
  () => { /* 依赖源收集函数 */ },
  () => { /* 依赖源改变时的回调函数 */ }
)

基本等价

watchEffect(
  () => console.log(counter.value)
)

watch(
  () => counter.value,
  () => console.log(counter.value),
  { immediate: true }
)

watch 不同的一点,在 watchEffect 中依赖源会被重复执行,动态新增加的依赖也会被收集,例如

const counter = ref(0)
const enabled = ref(false)

watchEffect(() => {
  if (enabled.value)
    console.log(counter.value)
})

// (以下忽略 nextTick)

// watchEffect 会被立即执行,因为 “enabled“ 为 false, 此时仅收集到 “enabled“ 依赖
counter.value += 1 // 无反应

enabled.value = true // Effect 触发,控制台出 "1"
counter.value += 1 // “counter“ 被作为新的依赖被收集,控制台出 "2"

enabled.value = false // 函数被重新执行,无输出
counter.value += 1 // 函数被重新执行,无输出 (虽然 counter 已经没有用了,但是作为依赖还是会触发函数)

Vue3 中 watch 与 watchEffect 有什么区别? - Anthony Fu的回答 - 知乎

使用emit

  • vue2
this.$emit('xxx') //不带参数
this.$emit('xxx',arg) //带参数
  • vue3
setup(props: any, context: any) {
    context.emit('xxx') //不带参数
    context.emit('xxx',arg) //带参数
}

ref && 自定义输出

image.png

image.png

image.png

setup标签

<script lang="ts">
    // setup(props: 外部传入属性, context: 上下文对象) {
    setup(props, 
    {
        attrs: 包含-组件外部传递过来,但没有在props配置中声明的属性,
        slots: 插槽内容,
        emit: 自定义函数
    }) {
        return{}
    }
</script>
↓↓
<script setup lang='ts'>
    // props
    const props = defineProps({ foo: String })
    const emit = defineEmits(['change', 'delete'])
</script>

ref.value

npm i @vitejs/plugin-vue
// vite.config.js
import vue from '@vitejs/plugin-vue'; 
<script setup>
    let count = ref(1)
    function add() {
        count.value++
    }
    /** ↓ **/ 
    let count = $ref(1)
    function add() {
        count++
    }
</script>

编译

import { ref as _ref } from 'vue'

const __sfc__ = {
  setup(__props) {
  let count = _ref(1)

  function add() {
    count.value++
  }
}