跳至主要內容

扩展

Mr.Dylin...大约 4 分钟JavascriptD_Javascript4.Javascript基础系列数据类型

扩展

1. 全局变量的定义

// main.js
const app = createApp(App)

app.config.globalProperties.$test = 'test'

 
 
 
 
 

除了setup()需要先获得实例,其他地方可以直接通过$test使用:

<tempalte>
    <div>{{ $test }}</div>
</tempalte>
<script>
import { getCurrentInstance } from 'vue'

export default {
  setup() {
    const test = getCurrentInstance()?.appContext.config.globalProperties.$test
    console.log('test===') 
    console.log(test)
  },
}
</script>

 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

2. teleport

组件的作用主要用来将模板内的 DOM 元素移动到其他位置。

可以应用到像 Modal,toast 等这样的元素

eg:toast

index.html

    <div id="app"></div>
+   <div id="teleport-target"></div>

 
 
 

src/components/HelloWorld.vue 中,添加如下,留意 to 属性跟上面的 id 选择器一致

  <button @click="showToast" class="btn">打开 toast</button>
  <!-- to 属性就是目标位置 -->
  <teleport to="#teleport-target">
    <div v-if="visible" class="toast-wrap">
      <div class="toast-msg">我是一个 Toast 文案</div>
    </div>
  </teleport>

 
 
 
 
 
 
 
 
import { ref } from 'vue';
export default {
  setup() {
    // toast 的封装
    const visible = ref(false);
    let timer;
    const showToast = () => {
      visible.value = true;
      clearTimeout(timer);
      timer = setTimeout(() => {
        visible.value = false;
      }, 2000);
    }
    return {
      visible,
      showToast
    }
  }
}

 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
image
image

可以看到,使用 teleport 组件,通过 to 属性,指定该组件渲染的位置与 <div id="app"></div> 同级,也就是在 body 下,但是 teleport 的状态 visible 又是完全由内部 Vue 组件控制

3. v-model

非兼容:用于自定义组件时,v-model prop 和事件默认名称已更改:

  • prop:value -> modelValue;
  • event:input -> update:modelValue;

非兼容:v-bind 的 .sync 修饰符和组件的 model 选项已移除,可用 v-model 作为代替;

新增:现在可以在同一个组件上使用多个 v-model 进行双向绑定;

新增:现在可以自定义 v-model 修饰符。

在 3.x 中,自定义组件上的 v-model 相当于传递了 modelValue prop 并接收抛出的 update:modelValue 事件:

<ChildComponent v-model="pageTitle" />

<!-- 简写: -->

<ChildComponent
  :modelValue="pageTitle"
  @update:modelValue="pageTitle = $event"
/>
 
 
 
 
 
 
 
 

父组件

 <test v-model:foo="a" v-model:bar="b"></test>

 
 

子组件

<template>
  <div>
    <input type="text" :value="foo" @input="$emit('update:foo',$event.target.value)" />
    <input type="text" :value="bar" @input="$emit('update:bar',$event.target.value)" />
  </div>
</template>
<script>
export default {
  props: {
    foo: String,
    bar: String,
  },
  emits: ["update:foo", "update:bar"],
  setup(props) {
    return {};
  },
};
</script>

 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

4. v-slot

新指令v-slot统一slot和slot-scope指令语法

父组件

<child>
    <template v-slot:one>
        <div><span>菜单</span></div>
    </template>
    <template v-slot="user">
        <ul>
          <li v-for="(item, index) in user.data" :key="index">{{ item }}</li>
        </ul>
    </template>
    <template v-slot:two="user">
        <div>{{ user.data }}</div>
    </template>
</child>
 
 
 
 
 
 
 
 
 
 
 
 
 

子组件

<div class="child">
    <h3>具名插槽</h3>
    <slot name="one" />
    <h3>作用域插槽</h3>
    <slot :data="list" />
    <h3>具名作用域插槽</h3>
    <slot name="two" :data="list" />
</div>
 
 
 
 
 
 
 
 

5. suspense

允许我们的应用程序在等待异步组件时渲染一些后备内容

使用场景

  • 在页面加载之前显示加载动画
  • 显示占位符内容
  • 处理延迟加载的图像

setup生命周期函数调用了异步请求,组件标签的外部必须使用Suspense标签进行嵌套以等待异步方法的结束 => 可以进行页面的加载中的展示。同时也可以进行错误信息的页面处理

父组件

<template>
  <div id="app">
    <div v-if="error">{{ error }}</div>
    <Suspense v-else>
      <template #default>
        <User />
      </template>
      <template #fallback>
        Loading...
      </template>
    </Suspense>
  </div>
</template>

<script>
import User from "../components/User";
import { onErrorCaptured, ref } from "vue";
export default {
  components: {
    User
  },
  setup() {
    const error = ref(null);
    // 捕获子组件异常时触发的函数
    onErrorCaptured(e => {
      error.value = e;
      // 不对错误进行拦截
      return true;
    });
    return { error };
  }
};
</script>

 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 














子组件

<template>
  <div>
    <h1>{{ user.name }}</h1>
    <h1>{{ user.age }}</h1>
  </div>
</template>

<script>
export default {
  async setup() {
    const fetchUser = () => {
      return new Promise((resolve, reject) => {
        setTimeout(() => {
          resolve({ name: "Carlo", age: "20" });
          //reject("获取信息失败!");
        }, 3000);
      });
    };

    const user = await fetchUser();
    return { user };
  }
};
</script>

 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 





若子组件中有多个异步请求,则会等待所有异步方法结束,进行页面内容的加载

async setup() {
    const fetchUser = () => {
      return new Promise((resolve, reject) => {
        setTimeout(() => {
          resolve({ name: "Carlo", age: "20" });
        }, 3000);
      });
    };
    const fetchObj = () => {
      return new Promise((resolve, reject) => {
        setTimeout(() => {
          resolve({ sex: "1" });
        }, 4000);
      });
    };
    const user = await fetchUser();
    const obj = await fetchObj();
    return { user, obj };
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

若页面中有多个子组件在一个suspense内

<Suspense>
    <template #default>
        <User />
        <User1 />
    </template>
    <template #fallback>
        Loading...
    </template>
</Suspense>
 
 
 
 
 
 
 
 
 

控制台 会给出警告 image 它的API很可能会改变slots,除非只有一个根节点

  • 稳定性不够根据vue-cli版本的不同会有不同的使用方式

解决方法 :增加一个跟节点

<Suspense>
    <template #default>
        <div>
            <User />
            <User1 />
        </div>
    </template>
    <template #fallback>
        Loading...
    </template>
</Suspense>
 
 
 
 
 
 
 
 
 
 
 
上次编辑于:
贡献者: zddbic