vue3 项目实践总结

一、挂载全局变量

1.1 main.js 中挂载
// 引入全局变量
import api from '@/api';

const app = createApp(App);

// 挂载全局变量
app.config.globalProperties.$API = api;

app.use(store)
  .use(router)
  .use(ElementPlus)
  .use(Vant)
  .mount('#app');
1.2 组件中获取
  • 方法一 推荐使用proxy
    1. 使用 ctx ,经过测试后,打包到dist以后,ctx下面的值是拿不到的,即只能在开发环境使用。所以。推荐使用proxy

    2. proxy, ctx可直接访问全局变量,但无法像globalProperties这样查看有哪些数据,只是一个Proxy对象。

    3. 如果想要通过 proxy, ctx 访问当前组件的变量,需要在onBeforeMount 和 mounted生命周期中,即在组件挂载之后才可访问,否则访问不了;

    4. 注意:在vue3中,created相关的生命周期已经被废弃,由setup()代替

import { getCurrentInstance, onMounted } from 'vue';   // 需要调用vue3内置的方法
setup(props, context) {
    // 直接解构出 proxy 和 ctx
    const { proxy, ctx } = getCurrentInstance();
    
	// 使用方法1 : 如果想要通过 proxy, ctx 访问当前组件的变量,需要在onBeforeMount 和 mounted生命周期中    
    onMounted(() => {
      console.log('----ctx', ctx['当前组件的data变量']);
      console.log('----proxy', proxy['当前组件的data变量']);
    });
    
  	// 使用方法2 :直接调用全局变量,但此时无法访问当前组件的变量
    proxy.$API.xxx   // 调用具体的方法
}

在这里插入图片描述在这里插入图片描述

  • 方法二 麻烦但详细
import { getCurrentInstance } from 'vue';   // 需要调用vue3内置的方法
setup(props, context) {
    // 这样获取可以获取到所有的全局变量,包含UI组件库或者其他方法注入的。并且可以形象的查看有哪些数据
    const { appContext: { config: { globalProperties } } } = getCurrentInstance();
    globalProperties.$API.xxx   // 调用具体的方法
}

在这里插入图片描述

1.3 全局挂载 store 和 router

在第九章中阐述了怎么在页面中去使用storerouter,但在实际项目开发中,storerouter 的使用频率是很高的,每个组件(页面)都去这么引入/调用,会显得很麻烦。

1. 挂载到window上

但是你要忍受它的全局污染

2. 挂载到全局上

在我的实际开发中,总会有几个东西会挂载到全局变量上:比如 ajax 或者APImoment等,再将 storerouter 挂载上去,使用成本对于我来说并没有增加多少。

  • main.js
const app = createApp(App);

// 将store、router挂载到全局变量上
import { useStore } from "vuex";
import { useRoute } from "vue-router";
app.config.globalProperties.$store = useStore();
app.config.globalProperties.$router = useRoute();

app.use(router).use(store).mount('#app')
  • 组件(页面)中
<template>
    <span> {{ count }} </span>
	
	<!-- 
    	下面这种vue2的旧写法,依旧可用,但是可能编辑器会报警告;
		并且$store并不需要在组件中return处理,它是挂载到每个实例上的
    -->
	<span>{{ $store.state.count }}</span>
</template>
<script>
    import { getCurrentInstance, computed, ref } from 'vue';
    export default {
      name: 'Home',
      setup() {
        const { proxy } = getCurrentInstance();
        // 使用store
        const count = computed(() => proxy.$store.state.count);

        const handleSkip = () => {
          // 使用router
          proxy.$router.push('/about');
        }

        return {
          count: ref(count),
          handleSkip
        }
      }
    }
</script>
3. 使用Provide & Inject => 不推荐,使用成本较高

注意:使用 Provide & Inject 最好配置 readonly 或者 shallowRef ,限制 孙子组件修改一级组件的数据。避免造成数据混乱。

  • app.vue
<script setup>
import { useStore } from "vuex";
import { useRoute } from "vue-router";

import { provide } from "vue";

// 组合式的API provide 没有提供批量方法,只能每个变量写一句
provide("store", useStore());
provide("router", useRoute());
</script>
  • 组件(页面)中
<script setup>
import { inject } from "vue";

// 使用 inject 获取到 store 和 router
const store = inject("store");
const router = inject("router");

console.log('=====>>>>', store.state);
console.log('=====>>>>', router);
</script>

注意 : inject()只能放在setup()生命周期里运行,即不能放在别的周期里运行,也不能放在事件周期里运行。

个人理解:只能在同步代码中使用,不能再异步代码中使用,所以,一般先在setup()周期中取值。

放在 setTimeout 或者 Promise.then() 是不可以的,但是下面这种用法是可以的:

function xx() {
  console.log(inject("abc"))
}
xx()

二、封装 getCurrentInstance

在上一章的 挂载全局变量 中有提到:想要获取全局变量,一般都是从getCurrentInstance() 解构出 proxyglobalProperties,但是:

  • 解构出的 proxy ,包含所有的全局变量,但是 是Proxy对象,不能清楚的在控制台查看
  • globalProperties 里面全部的全局变量,并且不是Proxy对象,可以在控制台清楚查看

而每个组件里面都去解构一次 globalProperties 是很繁琐的,所以,我们可以封装一下,实现步骤如下:

  1. 新建文件 hooks / useCurrentInstance.ts
import { ComponentInternalInstance, getCurrentInstance } from 'vue'
export default function useCurrentInstance() {
  // 如果解构出 proxy ,里面也包含所有的全局变量,但是 是Proxy对象,不能清楚的在控制台查看
  const { appContext } = getCurrentInstance() as ComponentInternalInstance;
  // 这里有全部的全局变量,并且不是Proxy对象,可以在控制台清楚查看
  const globalProperties = appContext.config.globalProperties;
  return {
    globalProperties
  }
}
  1. 组件中使用
// 先引入
import useCurrentInstance from '@/hooks/useCurrentInstance';

// 再使用
export default {
    setup() {
        const { globalProperties } = useCurrentInstance();
        // 这里面的全局变量可以清楚的在控制台去查看
    	console.log('-------globalProperties', globalProperties)
    }
}
  1. 挂载在windows上,方便全局使用
// mian.js
import useCurrentInstance from '@/hooks/useCurrentInstance';

window.useCurrentInstance = useCurrentInstance;  // 挂载到windows上,方便使用;=》其实这种方式不好(污染全局),但暂无找到其他好的方法

// todo....
// app.use(ElementPlus)
//   .use(router)
//   .use(store)
//   .mount('#app');
// 组件中使用

<script>
  export default {
    setup() {
      const globalPros = useCurrentInstance()
       console.log('-------globalPros', globalPros )
    },
  }
</script>

注意 :不能再封装文件里面直接调用函数并直接导出全局变量,会报错!!

 
3. 扩展
为了避免在每个需要使用 useCurrentInstance 的组件中都去引入一遍,我们将 @/hooks/useCurrentInstance 进行全局引入

  • main.js 中
import useCurrentInstance from '@/hooks/useCurrentInstance';

// 将全局变量结构操作放到window上,这样不用再使用的组件中去单独引入 => 目前没找到其他更好的方法
// app.mixin({
//   methods: {
//     globalProperties: useCurrentInstance,
//   }
// })
window.globalProperties = useCurrentInstance;


// ... todo
  • 组件中使用
<script setup>
  // script setup 语法糖会自动根据文件名生成name属性

  
  console.log('------globalProperties', globalProperties())
  const that = globalProperties();

  const toAboutPage = () => {
    that.$router.push('/about')
  }
</script>

 
 

三、vue3中使用ref

// ------------ 官网实例 ------------
<template> 
  <div ref="root">This is a root element</div>
</template>

<script>
  // 引入ref API
  import { ref, onMounted } from 'vue'

  export default {
    setup() {
      const root = ref(null)

      onMounted(() => {
        // DOM 元素将在初始渲染后分配给 ref
        console.log(root.value) // <div>This is a root element</div>
      })

      return {
        root   // 暴露出来的变量名必须和template 里面ref的值相同
      }
    }
  }
</script>



// ------------ 实际使用 ------------
<template>
    // publish 是一个子组件
	<publish ref="pubRef"></publish>

    <div @click="handleAddPublish">点击</div>
</template>

<script lang="ts">
  // 引入ref API
  import { ref } from 'vue'

  export default {
    setup() {
      	const root = ref(); // 如果是在 ts 环境下,不能传入null作为参数,否则root.value将提示结果为null, 不能调用子组件的方法;在js环境可以传null
        const handleAddPublish = () => {
          root.value.init();  // init 是子组件return出来的一个方法
        };

        return {
            handleAddPublish,
            pubRef: root   // 暴露出来的变量名必须和template 里面ref的值相同
        }
    }
  }
</script>

四、vue3中的nextTick

// nextTick: 将回调推迟到下一个DOM更新周期之后执行,在更改了一些数据以等待DOM更新后立即使用它。

import { nextTick } from 'vue'
setup() {
    const changeMessage = newMessage => {
        nextTick(()=>{
            // to do list...
        })
    };

    return {
		changeMessage         
    }
}

五、详解单文件组件<script setup>

<script setup> 是在单文件组件(SFC)中使用组合式 API 的编译时语法糖。相比于普通的 <script> 语法,它具有更多优势。详情请阅读官方文档

  1. 基本语法
// 将 setup 属性添加到 script 标签上即可
<script setup>
	console.log('hello script setup')
</script>

setup里面的代码会被编译成组件 setup() 函数的内容。这意味着与普通的 <script> 只在组件被首次引入的时候执行一次不同,<script setup> 中的代码会在每次组件实例被创建的时候执行并且自带 return 功能,所有在里面声明的变量、函数都能在模板中直接使用!

  1. 使用 props、emit、useContext

    vue3中如果想要获取 props、emit、attr等参数,需要从setup(props, context) 的参数里面获取,但<script setup> 省略了这一步,所以获取方式也需要修改:

   <template>
     <p>{{type[0]}}</p>
     <button @click="emit('setData', Number.parseInt(Math.random() * 10))">添加数据</button>
   </template>
   
   <script setup>
       import { defineEmits, defineProps } from 'vue' // 这两个方法其实无需导入,他们是<script setup>里的编译器宏,会自动编译
       // 获取props => 注意:props不能结构,会失去响应式效果
       const props = defineProps({
         list: {
           type: Array,
           default: () => []
         }
       })
       
    	// 获取emit   
       const emit = defineEmits(['deleteData', 'setData'])
       
       // 获取slots、attrs 等其他组件
       const { slots , attrs } = useContext()
   </script>
  1. 自动注册指令与组件
<template>
  <!-- 使用指令 -->
  <div v-click-outside />

  <!-- 使用组件 -->
  <MyComponent />
</template>

<script setup>
  // 指令导入后即可直接使用, 无需注册
  import { directive as clickOutside } from 'v-click-outside';
    
  // 组件导入后也可直接使用, 无需注册
  import MyComponent from './MyComponent.vue'
</script>

<script setup> 是在单文件组件 (SFC) 中使用组合式 API 的编译时语法糖。相比于普通的 <script> 语法,它具有更多优势!



文章仅为本人学习过程的一个记录,仅供参考,如有问题,欢迎指出!

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
在VSCode中实战Vue项目有以下几个步骤: 1. 创建项目:打开VSCode后,按照老师的要求创建项目。你可以通过在VSCode中打开文件夹,然后在终端中使用命令`vue create 项目名`来创建Vue项目。 2. 安装插件:为了方便开发Vue项目,你可以安装一些插件。例如,可以安装Vue插件来提供更好的代码提示和语法高亮。另外,你也可以安装ESLint插件来进行代码规范检查。这些插件可以提高你的开发效率和代码质量。 3. 调整颜色:如果你对VSCode的颜色主题不满意,你可以根据自己的喜好进行调整。可以通过访问[VSCode颜色文档](https://code.visualstudio.com/api/references/theme-color)来查找并修改你喜欢的颜色。 4. 设置代码片段:为了提高开发效率,你可以设置Vue的用户代码片段。你可以在VSCode的设置中添加Vue代码片段,当你在Vue文件中输入特定的代码段快捷键后,按下Tab键或回车键就会自动生成对应的代码。可以参考[示例代码段](3)来设置自己的Vue代码片段。 5. 开发实战:在VSCode中打开你的Vue项目后,你可以开始进行实际的开发工作。你可以使用VSCode提供的丰富的功能,如代码自动补全、代码跳转、代码重构等来提高开发效率。同时,你还可以使用调试功能来调试你的Vue应用程序。 综上所述,以上是在VSCode中进行Vue项目实战的一些基本步骤和建议。通过合理利用VSCode的功能和插件,你可以更高效地开发Vue项目。<span class="em">1</span><span class="em">2</span><span class="em">3</span>

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值