Vue3使用$refs获取节点生产环境undefined-使用getCurrentInstance-ctx应改用proxy

  

vue3项目,在使用refs获取节点,开发环境正常,生产环境报错

console.log(getCurrentInstance())

internalInstance.ctx,

internalInstance.proxy

开发环境正常-生产环境报错

 internalInstance.ctx

生产环境获取不到值

ctx打包后在生产环境下是获取不到

<script setup>
import {
  defineProps,
  getCurrentInstance,
  reactive,
  ref,
  nextTick,
  onMounted,
} from "vue";

let internalInstance = "";

onMounted(() => {
  internalInstance = getCurrentInstance();
  // { proxy } = getCurrentInstance()
  console.log(
    "internalInstance",
    internalInstance,
    internalInstance.ctx,
    internalInstance.proxy
  );
});


let nums = reactive(["", "", "", "", "", ""]);


// nextTick(() => {
//   // input0.value.focus();
//   currentInput.value++;
//   // console.log(["input" + currentInput.value].value, "123");
//   // console.log(input0.value.value);
// });

let activeIndex = 0;

const onKeyDown = (index, e) => {
  // console.log(index, e, activeIndex, 888);
  switch (e.keyCode) {
    case 8: // backspace键
      e.preventDefault();
      if (nums[index]) {
        nums[index] = "";
        if (index > 0) {
          nextTick(() => {
            activeIndex = index - 1;
            const prevInput = internalInstance.ctx.$refs[`input${index - 1}`];
            console.log("prevInput", prevInput);
            prevInput.focus();
          });
        }
      } else if (index === 0) {
        activeIndex = 0;
      }
      break;
    default:
      break;
  }
};

const handleInput = (index) => {
  // console.log(index, activeIndex, 999);
  if (nums[index]) {
    activeIndex = index;
    if (index < 5) {
      nextTick(() => {
        const nextInput = internalInstance.ctx.$refs[`input${index + 1}`];
        console.log("nextInput", nextInput);
        nextInput.focus();
      });
    }
  }
};
</script>

修复bug

将internalInstance.ctx

替换成 internalInstance.appContext.config.globalProperties或者internalInstance.proxy

方式一 

<script setup>
import { reactive,ref,onMounted,onBeforeMount,getCurrentInstance,} from "vue";

const { proxy } = getCurrentInstance();


onMounted(async () => {
  proxy.$toast.clear();
  service = Service.getInstance();
  service.mmtg.backButtonClick(backButtonClicked);
  state.address = service.user.address;
  state.tokenList = service.getTokenList();
  loadBalnace();
});

const agree = async () => {
  proxy.$toast.loadingAll("Logging in");
  await service.login();
  proxy.$toast.clear();
  data.showBottom = true;
};
</script>

 方式二

<script setup>
import {
  defineProps,
  getCurrentInstance,
  reactive,
  ref,
  nextTick,
  onMounted,
} from "vue";

let internalInstance = "";

onMounted(() => {
  internalInstance = getCurrentInstance();
  // { proxy } = getCurrentInstance()
  console.log(
    "internalInstance",
    internalInstance,
    internalInstance.ctx,
    internalInstance.proxy
  );
});


let nums = reactive(["", "", "", "", "", ""]);


// nextTick(() => {
//   // input0.value.focus();
//   currentInput.value++;
//   // console.log(["input" + currentInput.value].value, "123");
//   // console.log(input0.value.value);
// });

let activeIndex = 0;

const onKeyDown = (index, e) => {
  // console.log(index, e, activeIndex, 888);
  switch (e.keyCode) {
    case 8: // backspace键
      e.preventDefault();
      if (nums[index]) {
        nums[index] = "";
        if (index > 0) {
          nextTick(() => {
            activeIndex = index - 1;
            const prevInput = internalInstance.proxy.$refs[`input${index - 1}`];
            console.log("prevInput", prevInput);
            prevInput.focus();
          });
        }
      } else if (index === 0) {
        activeIndex = 0;
      }
      break;
    default:
      break;
  }
};

const handleInput = (index) => {
  // console.log(index, activeIndex, 999);
  if (nums[index]) {
    activeIndex = index;
    if (index < 5) {
      nextTick(() => {
        const nextInput = internalInstance.proxy.$refs[`input${index + 1}`];
        console.log("nextInput", nextInput);
        nextInput.focus();
      });
    }
  }
};
</script>

在获取上下文和全局挂载实例的时候会用到这个getCurrentInstance,那我们来新建 hooksuseCurrentInstance.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();

defineExpose 

<script setup>
import { ref } from '@vue/reactivity';

let message = ref('子元素').value

const alertMessage = function () {
    alert(message)
}

defineExpose({
    message,
    alertMessage
})
</script>

通过<script setup>语法糖的写法,其组件是默认关闭的,也就是说如果是通过$refs或者$parents来访问子组件中定义的值是拿不到的,必须通过defineExpose向外暴露你想获取的值才行

posted @ 2023-07-03 09:58  JackieDYH  阅读(647)  评论(0编辑  收藏  举报  来源