vue3 组合式API体验 setup-script

474 阅读4分钟

vue3单文件组件组合式 API 语法糖 (<script setup>) 基础使用

vue文件中使用

  1. setup-script 无需 return
    <script setup></script>
    

响应式数据

  1. 使用前需引入;

    import { ref, reactive } from 'vue'
    
  2. 非Object数据类型使用ref,Object数据类型使用reactive

    var string = ref('');
    var bool = ref(false);
    var num = ref(1);
    var obj = reactive({});
    
  3. ref方法定义的数据需要使用.value属性值赋值;

    var string = ref('');
    string.value = '这样赋值';
    
  4. reactive方法定义的数组或对象,直接整个赋值不触发视图更新,需对单项下标/属性赋值;

    var arr = reactive([]);
    arr = [1];  //这样不触发视图更新
    arr[0] = 1;   //触发视图更新
    

生命周期使用

  1. 整个setup-script标签运行于created前,beforeCreated后,如需使用created之后的生命周期钩子,需要引入使用;

    import { onMounted } from 'vue';
    onMounted(() => {
        console.log('这是mounted~~~')
    })
    
  2. 具体有onBeforeMounted, onMounted, onBeforeUpdate, onUpdated, onBeforeUnmounte(原beforeDestory), onUnmounted

侦听器使用

  1. watchEffect
    watchEffect,立即执行传入的一个函数,同时响应式追踪其依赖,并在其依赖变更时重新运行该函数。

    import { watchEfect } from 'vue';
    var count = ref(0);
    watchEffect(() => {
        console.log(count)
    })
    
  2. watch监听ref

    import { watch } 'vue';
    var count = ref(0);
    watch(count, (newVal, oldVal) => {
        console.log(newVal, oldVal)
    })
    
  3. watch监听reactive

    var reObj = reactive({
        a: 1,
        b: {
            c: 2
        }
    })
    watch(reObj, (newVal, oldVal) => {
        //监听整个reactive可直接深度监听
        xxx
    })
    
  4. watch监听对象属性

    //监听对象属性这样写
    var count = ref(0);
    var countObj = ref({
        a: 0
    });
    var obj = { b: 0};
    watch(() => count.value, () => {});
    watch(() => countObj.a, () => {});
    watch(() => obj.b, () => {});
    
  5. watch深度监听

    var obj = { a: { b: 0 } };
    watch(obj, () => {}, {
        deep: true,
        lazy: true,     //初始化不监听
    })
    
  6. 主动清除侦听器
    在setup()函数内创建watch监听,会在当前组件被销毁才会停止,如果想明确的停止某个监听,可以调用watch的返回值即可。

    const stop = watch(count, () => {});
    if(xxx) {
        //调用stop后该侦听器就会停止监听
        stop();
    }
    
  7. 侦听器停止时终止异步方法
    页面销毁时侦听器停止监听,异步方法可能还在响应中,但这种响应已无必要。可以使用onInvalidate中止。

    watch(count, (newVal, oldVal, onInvalidate) => {
        const timer = setTimeout(() => {
            console.log(val);
        }, 3000);
        onInvalidate(() => {
            clearTimeout(timer);
        })
    })
    
  8. 监听多个数据

    var moreCount = ref(1);
    var moreStr = ref('what');
    watch([moreCount,moreStr], ([newCount, newStr], [oldCount, oldStr]) => {
        console.log(newCount, newStr, oldCount, oldStr);
    })
    

计算属性computed

根据依赖数据变化响应,返回处理后的新的数据;建议数据过滤采用计算属性。

  1. 只读computed

    import { computed } from 'vue';
    var a = ref(1);
    var b = computed(() => {
        return a+2;
    }) 
    
  2. 可读写computed

    import { computed } from 'vue';
    var a = ref(1);
    var b = computed({
        get() {
            return a+1;
        },
        set(val) {
            return a.value = val - 1;
        }
    }) 
    

组件使用

  1. 组件引入和使用;
    <script setup>标签内import后即可直接使用:

    <template>
        <tool></tool>
    </template>
    <script setup>
    import tool from '@/component/tool';
    </script>
    
  2. props使用,需要引入;

    import { defineProps } from 'vue';
    const props = defineProps({
        propsData: {
            type: String,
            default: '这是props'
        }
    })
    
  3. 组件通信,需引入;

    import { defineEmits } from 'vue';
    

路由跳转

  1. 页面跳转

    import { useRouter } from 'vue-router';
    const router = userRouter();
    router.push('/index');
    //query传参
    router.push({
        path: '/index',
        query: {
            id: 1
        }
    })
    //params传参,必须使用name,否则会报错
    router.push({
        name: 'index',
        params: {
            id: 1
        }
    })
    
  2. 参数接收

    import { useRoute } from 'vue-router';
    const route = userRoute();
    var id = route.query.id;
    

全局参数方法

  1. 注册全局参数方法
    main.js文件内导入全局变量和全局方法文件,使用app.config.globalProperties注册;

    import App from "./App.vue";
    import config from './utils/config';    //全局变量
    import axios from "./service/index";    //全局方法
    const app = createApp({
        ...App
    })
    app.config.globalProperties.$axios = axios;
    app.config.globalProperties.$config = config;
    
  2. 使用全局方法,需引入getCurrentInstance;

    import { getCurrentInstance } from 'vue';
    const { proxy } = getCurrentInstance();
    console.log(proxy.$config, proxy.$axios);
    

<style>中的v-bind

<style>可以使用js中的变量了

<script setup>
const theme = {
    color: 'red'
}
</script>

<template>
    <p>hello</p>
</template>

<style scoped>
p {
    color: v-bind('theme.color');
}
</style>

实际的值会被编译成 hash 的 CSS 自定义 property,CSS 本身仍然是静态的。自定义 property 会通过内联样式的方式应用到组件的根元素上,并且在源值变更的时候响应式更新

使用过程问题

路由与跨域代理冲突

  • 问题描述:
    创建adminManage文件夹存放admin相关vue文件,路由路径变为/adminManage/xxx.vue;主动刷新页面变为json返回字段页面,提示未登录。

  • 解决方法:
    路由名与跨域代理中的/admin冲突导致,修改路由名去除admin即可。

页面组件销毁监听器依旧生效(暂无法重现)

  • 问题描述:
    页面组件注册监听器监听路由,该页面组件未销毁时,页面切换都会触发该侦听器。该页面销毁后,侦听器仍然存在且切换页面仍可触发;再次打开该页面组件,此侦听器被重复注册,即当前存在两个相同功能的侦听器,且均可被触发。