这是一篇vue3 的详细教程

news2024/12/23 3:50:48

在这里插入图片描述

Vue 3 详细教程

一、Vue 3 简介

Vue.js 是一款流行的 JavaScript 前端框架,用于构建用户界面。Vue 3 是其最新版本,带来了许多新特性和性能优化,使开发更加高效和灵活。

二、环境搭建

  1. 安装 Node.js
    • 前往Node.js 官方网站下载并安装适合你操作系统的版本。安装完成后,在终端或命令提示符中输入node -vnpm -v,确保 Node.js 和 npm(包管理器)已成功安装并显示相应版本号。
  2. 创建 Vue 项目
    • 打开终端或命令提示符,进入你想要创建项目的目录。
    • 运行npm install -g @vue/cli全局安装 Vue CLI(命令行界面工具)。如果之前安装过旧版本的 Vue CLI,可能需要先卸载npm uninstall -g vue-cli
    • 运行vue create 项目名称创建一个新的 Vue 3 项目。在创建过程中,你可以选择默认的配置(babel、eslint 等),也可以手动选择需要的特性,如 Vue Router(路由管理)、Vuex(状态管理)等。
    • 例如,选择手动配置,按下回车键后,会出现一系列选项让你勾选。你可以根据项目需求选择,比如选择 Vue Router 和 Vuex,然后使用空格键勾选,回车键确认。
    • 等待项目创建完成,进入项目目录cd 项目名称
    • 运行npm run serve启动开发服务器,在浏览器中访问http://localhost:8080/,你将看到 Vue 项目的默认页面。

三、Vue 3 基础语法

  1. 模板语法

    • 插值表达式
      • 在 Vue 的模板中,你可以使用{{}}来插入动态数据。例如:
        <template>
          <div>
            <h1>{{ message }}</h1>
          </div>
        </template>
        
        <script>
          import { defineComponent } from 'vue';
          export default defineComponent({
            name: 'App',
            data() {
              return {
                message: 'Hello Vue 3!'
              };
            }
          });
        </script>
        
      • 这里的message是在组件的数据中定义的,插值表达式会将其值显示在h1标签中。
    • 指令
      • v-bind:用于动态绑定 HTML 属性。例如,绑定一个元素的src属性:
        <template>
          <img v-bind:src="imageUrl" alt="图片">
        </template>
        
        <script>
          import { defineComponent } from 'vue';
          export default defineComponent({
            name: 'App',
            data() {
              return {
                imageUrl: 'https://example.com/image.jpg'
              };
            }
          });
        </script>
        
        也可以简写为:,如<img :src="imageUrl" alt="图片">
      • v-if 和 v-else:用于条件渲染。当条件为真时,显示v-if所在的元素,否则显示v-else所在的元素。
        <template>
          <div>
            <p v-if="showText">这是一段显示的文本</p>
            <p v-else>这段文本不显示(当条件不满足时)</p>
          </div>
        </template>
        
        <script>
          import { defineComponent } from 'vue';
          export default defineComponent({
            name: 'App',
            data() {
              return {
                showText: true
              };
            }
          });
        </script>
        
      • v-for:用于循环渲染列表。例如,渲染一个数组中的数据:
        <template>
          <ul>
            <li v-for="item in items" :key="item.id">{{ item.name }}</li>
          </ul>
        </template>
        
        <script>
          import { defineComponent } from 'vue';
          export default defineComponent({
            name: 'App',
            data() {
              return {
                items: [
                  { id: 1, name: 'Item 1' },
                  { id: 2, name: 'Item 2' },
                  { id: 3, name: 'Item 3' }
                ]
              };
            }
          });
        </script>
        
      • 这里的key是一个特殊的属性,用于给 Vue 提供一个唯一标识,以便更高效地更新和渲染列表元素。
  2. 响应式数据

    • Vue 3 使用refreactive来创建响应式数据。
    • ref
      • 用于创建基本类型(如数字、字符串、布尔值等)的响应式数据。例如:
        <template>
          <div>
            <p>{{ counter }}</p>
            <button @click="increment">增加</button>
          </div>
        </template>
        
        <script>
          import { defineComponent, ref } from 'vue';
          export default defineComponent({
            name: 'App',
            setup() {
              const counter = ref(0);
              const increment = () => {
                counter.value++;
              };
              return {
                counter,
                increment
              };
            }
          });
        </script>
        
      • 这里counter是一个响应式变量,通过ref创建。在setup函数中,修改counter.value会触发视图的更新。
    • reactive
      • 用于创建对象类型的响应式数据。例如:
        <template>
          <div>
            <p>{{ user.name }} - {{ user.age }}</p>
            <button @click="updateUser">更新用户信息</button>
          </div>
        </template>
        
        <script>
          import { defineComponent, reactive } from 'vue';
          export default defineComponent({
            name: 'App',
            setup() {
              const user = reactive({
                name: 'John',
                age: 30
              });
              const updateUser = () => {
                user.name = 'Jane';
                user.age = 35;
              };
              return {
                user,
                updateUser
              };
            }
          });
        </script>
        
      • reactive创建的对象,其属性的修改也会自动反映在视图中。
  3. 事件处理

    • 在 Vue 中,可以使用v-on指令或其简写@来监听事件并执行相应的方法。例如:
    <template>
      <button @click="handleClick">点击我</button>
    </template>
    
    <script>
      import { defineComponent } from 'vue';
      export default defineComponent({
        name: 'App',
        methods: {
          handleClick() {
            console.log('按钮被点击了!');
          }
        }
      });
    </script>
    
    • 你还可以传递参数给事件处理方法。例如:
    <template>
      <button @click="handleClickWithParam(123)">点击并传递参数</button>
    </template>
    
    <script>
      import { defineComponent } from 'vue';
      export default defineComponent({
        name: 'App',
        methods: {
          handleClickWithParam(param) {
            console.log('传递的参数是:', param);
          }
        }
      });
    </script>
    

四、Vue Router(路由管理)

  1. 安装和配置
    • 首先,在你的 Vue 3 项目中安装vue-router。在项目目录下的终端中运行npm install vue-router@4(这里安装的是 Vue Router 4 版本,适配 Vue 3)。
    • 然后,在项目的src目录下创建一个router文件夹,并在其中创建一个index.js文件用于配置路由。
    • 示例代码如下:
    import { createRouter, createWebHistory } from 'vue-router';
    import Home from '../views/Home.vue';
    import About from '../views/About.vue';
    
    const routes = [
      {
        path: '/',
        name: 'Home',
        component: Home
      },
      {
        path: '/about',
        name: 'About',
        component: About
      }
    ];
    
    const router = createRouter({
      history: createWebHistory(),
      routes
    });
    
    export default router;
    
    • 在上述代码中,我们定义了两个路由:/(首页)和/about(关于页面),分别对应Home.vueAbout.vue组件。
    • 接下来,需要在main.js文件中引入路由并将其挂载到 Vue 实例上。修改main.js文件如下:
    import { createApp } from 'vue';
    import App from './App.vue';
    import router from './router/index.js';
    
    const app = createApp(App);
    app.use(router);
    app.mount('#app');
    
  2. 路由导航
    • 在模板中,可以使用<router-link>组件来进行页面导航。例如:
    <template>
      <div>
        <nav>
          <router-link to="/">首页</router-link>
          <router-link to="/about">关于</router-link>
        </nav>
        <router-view></router-view>
      </div>
    </template>
    
    • <router-link>会渲染成一个带有链接功能的元素,点击它会导航到对应的路由页面。<router-view>是一个占位符,用于显示当前路由对应的组件内容。

五、Vuex(状态管理)

  1. 安装和配置
    • 在项目目录下的终端中运行npm install vuex@next(安装 Vuex 的适配 Vue 3 的版本)。
    • src目录下创建一个store文件夹,并在其中创建一个index.js文件用于配置 Vuex 存储。
    • 示例代码如下:
    import { createStore } from 'vuex';
    
    const store = createStore({
      state() {
        return {
          count: 0
        };
      },
      mutations: {
        increment(state) {
          state.count++;
        }
      },
      actions: {
        incrementAsync({ commit }) {
          setTimeout(() => {
            commit('increment');
          }, 1000);
        }
      },
      getters: {
        doubleCount(state) {
          return state.count * 2;
        }
      }
    });
    
    export default store;
    
    • 在上述代码中,state定义了应用的初始状态,这里是一个count变量初始值为 0。mutations用于定义更改状态的方法,这里的increment方法会将count加 1。actions用于处理异步操作,这里的incrementAsync会在 1 秒后调用increment mutation。getters用于计算派生状态,这里的doubleCount返回count的两倍。
  2. 在组件中使用 Vuex
    • 在 Vue 组件中,可以通过this.$store来访问 Vuex 存储中的状态和方法。例如:
    <template>
      <div>
        <p>当前计数:{{ count }}</p>
        <p>双倍计数:{{ doubleCount }}</p>
        <button @click="increment">增加计数</button>
        <button @click="incrementAsync">异步增加计数</button>
      </div>
    </template>
    
    <script>
      import { mapState, mapMutations, mapActions } from 'vuex';
      export default {
        computed: {
         ...mapState(['count', 'doubleCount'])
        },
        methods: {
         ...mapMutations(['increment']),
         ...mapActions(['incrementAsync'])
        }
      };
    </script>
    
    • 在上述代码中,通过mapStatecountdoubleCount映射到组件的计算属性中,这样在模板中就可以直接使用。通过mapMutationsincrement mutation 方法映射到组件的方法中,通过mapActionsincrementAsync action 方法映射到组件的方法中,以便在模板中通过按钮点击调用。

六、组件通信

  1. 父子组件通信
    • 父传子
      • 在父组件中,可以通过属性传递的方式将数据传递给子组件。例如:
        <!-- 父组件 -->
        <template>
          <div>
            <child-component :message="parentMessage"></child-component>
          </div>
        </template>
        
        <script>
          import { defineComponent } from 'vue';
          import ChildComponent from './ChildComponent.vue';
          export default defineComponent({
            name: 'ParentComponent',
            components: { ChildComponent },
            data() {
              return {
                parentMessage: '这是来自父组件的消息'
              };
            }
          });
        </script>
        
        在子组件中,可以通过props选项接收父组件传递的数据:
        <!-- 子组件 -->
        <template>
          <div>
            <p>{{ message }}</p>
          </div>
        </template>
        
        <script>
          import { defineComponent } from 'vue';
          export default defineComponent({
            name: 'ChildComponent',
            props: {
              message: String
            }
          });
        </script>
        
    • 子传父
      • 子组件可以通过触发自定义事件并传递数据给父组件。例如:
        <!-- 子组件 -->
        <template>
          <div>
            <button @click="sendMessageToParent">向父组件发送消息</button>
          </div>
        </template>
        
        <script>
          import { defineComponent } from 'vue';
          export default defineComponent({
            name: 'ChildComponent',
            methods: {
              sendMessageToParent() {
                this.$emit('childMessage', '这是来自子组件的消息');
              }
            }
          });
        </script>
        
        在父组件中,监听子组件触发的事件并接收数据:
        <!-- 父组件 -->
        <template>
          <div>
            <child-component @childMessage="handleChildMessage"></child-component>
            <p>{{ receivedMessage }}</p>
          </div>
        </template>
        
        <script>
          import { defineComponent } from 'vue';
          import ChildComponent from './ChildComponent.vue';
          export default defineComponent({
            name: 'ParentComponent',
            components: { ChildComponent },
            data() {
              return {
                receivedMessage: ''
              };
            },
            methods: {
              handleChildMessage(message) {
                this.receivedMessage = message;
              }
            }
          });
        </script>
        
  2. 兄弟组件通信
    • 可以通过使用 Vuex 来实现兄弟组件之间的通信。例如,一个兄弟组件修改了 Vuex 中的状态,另一个兄弟组件可以通过mapState获取到更新后的状态。
    • 或者,可以创建一个事件总线(Event Bus)来实现兄弟组件通信。首先,创建一个事件总线文件,例如src/bus.js
    import { mitt } from 'mitt';
    
    const bus = mitt();
    
    export default bus;
    
    • 在需要发送事件的兄弟组件中:
    <template>
      <div>
        <button @click="sendMessageToBrother">向兄弟组件发送消息</button>
      </div>
    </template>
    
    <script>
      import bus from '../bus.js';
      export default {
        methods: {
          sendMessageToBrother() {
            bus.emit('brotherMessage', '这是来自一个兄弟组件的消息');
          }
        }
      };
    </script>
    
    • 在需要接收事件的兄弟组件中:
    <template>
      <div>
        <p>{{ receivedMessage }}</p>
      </div>
    </template>
    
    <script>
      import bus from '../bus.js';
      export default {
        data() {
          return {
            receivedMessage: ''
          };
        },
        mounted() {
          bus.on('brotherMessage', (message) => {
            this.receivedMessage = message;
          });
        },
        beforeUnmount() {
          bus.off('brotherMessage');
        }
      };
    </script>
    
    • 在上述代码中,mounted钩子中监听brotherMessage事件,beforeUnmount钩子中取消监听,以避免内存泄漏。

七、生命周期钩子

Vue 3 中的组件有一系列生命周期钩子,它们在组件的不同阶段被调用。

  1. beforeCreate
    • 在实例初始化之后,数据观测(data option 的处理)和事件配置(event / watch 选项的处理)之前被调用。这个阶段通常用于在组件实例创建之前进行一些初始化工作,但此时数据和响应式系统尚未初始化,所以不能访问datacomputedmethods中的数据和方法。
    • 示例用法:
      import { defineComponent } from 'vue';
      export default defineComponent({
        name: 'MyComponent',
        beforeCreate() {
          console.log('beforeCreate - 组件实例初始化后,数据观测和事件配置前调用');
        }
      });
      
  2. created
    • 在实例创建完成后被立即调用。此时,组件实例已经完成了数据观测、属性和方法的计算,但尚未挂载到 DOM 上。可以在这里进行一些需要访问响应式数据的初始化操作,比如发起异步数据请求等。
    • 示例用法:
      import { defineComponent, ref } from 'vue';
      export default defineComponent({
        name: 'MyComponent',
        data() {
          return {
            message: '初始消息'
          };
        },
        created() {
          console.log('created - 组件实例创建完成,数据观测和计算属性等初始化后调用');
          console.log('初始消息:', this.message);
          // 可以在这里发起异步请求获取数据
          this.fetchData();
        },
        methods: {
          fetchData() {
            // 模拟异步请求
            setTimeout(() => {
              this.message = '获取到的数据';
            }, 1000);
          }
        }
      });
      
  3. beforeMount
    • 在挂载开始之前被调用。此时,模板已经编译完成,但尚未渲染到 DOM 中。可以在这个阶段进行一些最后的准备工作,比如手动操作 DOM 等(但不建议这样做,因为 Vue 的理念是尽量避免直接操作 DOM,除非有特殊需求)。
    • 示例用法:
      import { defineComponent } from 'vue';
      export default defineComponent({
        name: 'MyComponent',
        beforeMount() {
          console.log('beforeMount - 挂载开始之前调用');
        }
      });
      
  4. mounted
    • 在组件挂载到 DOM 后被调用。此时,组件已经完全渲染到页面上,可以在这个阶段进行一些与 DOM 操作相关的操作,比如获取 DOM 元素、初始化第三方库等。这个钩子函数通常用于在组件渲染完成后执行一些需要依赖 DOM 的操作。
    • 示例用法:
      import { defineComponent, ref } from 'vue';
      export default defineComponent({
        name: 'MyComponent',
        mounted() {
          console.log('mounted - 组件挂载到DOM后调用');
          const element = document.getElementById('myElement');
          if (element) {
            // 对元素进行操作
            element.style.color ='red';
          }
          // 初始化第三方库
          this.initThirdPartyLibrary();
        },
        methods: {
          initThirdPartyLibrary() {
            // 假设这里是初始化一个第三方图表库的代码
            // 例如:Chart.js 的初始化
            const ctx = document.getElementById('chartCanvas').getContext('2d');
            new Chart(ctx, {
              type: 'bar',
              data: {
                labels: ['January', 'February', 'March'],
                datasets: [{
                  label: 'Sales',
                  data: [10, 20, 30],
                  backgroundColor: 'rgba(75, 192, 192, 0.2)',
                  borderColor: 'rgba(75, 192, 192, 1)',
                  borderWidth: 1
                }]
              }
            });
          }
        }
      });
      
  5. beforeUpdate
    • 在数据更新时(响应式数据发生变化),但在虚拟 DOM 重新渲染和打补丁之前被调用。可以在这个钩子中访问到更新前的状态,可以用于在更新 DOM 之前进行一些准备工作,比如记录当前状态等。
    • 示例用法:
      import { defineComponent, ref } from 'vue';
      export default defineComponent({
        name: 'MyComponent',
        data() {
          return {
            count: 0
          };
        },
        beforeUpdate() {
          console.log('beforeUpdate - 数据更新前调用');
          console.log('更新前的计数:', this.count);
        },
        methods: {
          incrementCount() {
            this.count++;
          }
        }
      });
      
  6. updated
    • 在数据更新(响应式数据发生变化)导致的虚拟 DOM 重新渲染和打补丁之后被调用。此时,DOM 已经更新为最新的状态,可以在这个阶段进行一些与更新后相关的操作,比如重新获取 DOM 元素的新状态等。但需要注意的是,在这个钩子中频繁操作 DOM 可能会导致性能问题,因为它可能会在一个更新周期内被多次调用。
    • 示例用法:
      import { defineComponent, ref } from 'vue';
      export default defineComponent({
        name: 'MyComponent',
        data() {
          return {
            count: 0
          };
        },
        updated() {
          console.log('updated - 数据更新后,虚拟DOM重新渲染和打补丁后调用');
          console.log('更新后的计数:', this.count);
          const element = document.getElementById('countDisplay');
          if (element) {
            element.textContent = `当前计数:${this.count}`;
          }
        },
        methods: {
          incrementCount() {
            this.count++;
          }
        }
      });
      
  7. beforeUnmount
    • 在组件卸载之前被调用。可以在这个阶段进行一些清理工作,比如取消定时器、解绑事件监听器、清除全局变量等,以防止内存泄漏和不必要的副作用。
    • 示例用法:
      import { defineComponent, ref } from 'vue';
      export default defineComponent({
        name: 'MyComponent',
        data() {
          return {
            timer: null
          };
        },
        mounted() {
          this.timer = setInterval(() => {
            console.log('定时任务执行');
          }, 1000);
        },
        beforeUnmount() {
          console.log('beforeUnmount - 组件卸载之前调用');
          clearInterval(this.timer);
          this.timer = null;
          // 假设这里有解绑事件监听器的代码
          window.removeEventListener('resize', this.handleResize);
        },
        methods: {
          handleResize() {
            // 处理窗口大小调整的逻辑
          }
        }
      });
      
  8. unmounted
    • 在组件卸载之后被调用。此时,组件的所有实例绑定和事件监听器都已经被移除,DOM 元素也已经被销毁。可以在这个阶段进行一些最后的清理工作,比如进行一些日志记录等。
    • 示例用法:
      import { defineComponent } from 'vue';
      export default defineComponent({
        name: 'MyComponent',
        unmounted() {
          console.log('unmounted - 组件卸载之后调用');
        }
      });
      

理解和正确使用这些生命周期钩子对于优化组件的性能、管理组件的状态以及处理各种逻辑场景非常重要。在实际开发中,需要根据具体的需求选择合适的生命周期钩子来执行相应的代码。

八、组合式 API

Vue 3 引入了组合式 API,它提供了一种更灵活和逻辑复用性更强的方式来组织组件的逻辑。

  1. setup 函数
    • setup是组合式 API 的核心函数,在组件创建之前执行,用于初始化响应式数据、定义方法等。它接收两个参数:propscontext
    • props是父组件传递给子组件的属性对象,是响应式的。可以通过解构的方式获取需要的属性。
    • context包含了一些其他的上下文信息,如attrs(非 props 属性集合)、slots(插槽对象)和emit(用于触发自定义事件的方法)等。
    • 示例代码:
      <template>
        <div>
          <p>{{ message }}</p>
          <button @click="handleClick">点击修改消息</button>
        </div>
      </template>
      
      <script>
        import { defineComponent, ref } from 'vue';
        export default defineComponent({
          name: 'MyComponent',
          props: {
            initialMessage: String
          },
          setup(props, context) {
            // 使用ref创建响应式数据
            const message = ref(props.initialMessage);
            const handleClick = () => {
              message.value = '新的消息';
              // 触发自定义事件通知父组件
              context.emit('messageUpdated', message.value);
            };
            return {
              message,
              handleClick
            };
          }
        });
      </script>
      
  2. 响应式函数
    • 除了ref用于创建基本类型的响应式数据外,还有reactive用于创建对象类型的响应式数据,以及computed用于创建计算属性。
    • reactive示例:
      import { reactive } from 'vue';
      const state = reactive({
        count: 0,
        name: 'John'
      });
      // 修改响应式对象的属性
      state.count++;
      state.name = 'Jane';
      
    • computed示例:
      import { reactive, computed } from 'vue';
      const state = reactive({
        count: 0
      });
      // 创建计算属性
      const doubleCount = computed(() => state.count * 2);
      console.log(doubleCount.value); // 初始值为0
      state.count++;
      console.log(doubleCount.value); // 值变为2
      
  3. 自定义钩子
    • 可以创建自定义钩子来封装可复用的逻辑。例如,创建一个用于获取数据的自定义钩子:
      import { ref, onMounted } from 'vue';
      export function useFetchData(apiUrl) {
        const data = ref(null);
        const loading = ref(true);
        const error = ref(null);
      
        onMounted(async () => {
          try {
            const response = await fetch(apiUrl);
            if (!response.ok) {
              throw new Error('网络请求失败');
            }
            data.value = await response.json();
          } catch (err) {
            error.value = err;
          } finally {
            loading.value = false;
          }
        });
      
        return {
          data,
          loading,
          error
        };
      }
      
    • 在组件中使用自定义钩子:
      <template>
        <div>
          <p v-if="loading">正在加载数据...</p>
          <p v-if="error">{{ error }}</p>
          <ul v-if="data">
            <li v-for="item in data" :key="item.id">{{ item.name }}</li>
          </ul>
        </div>
      </template>
      
      <script>
        import { defineComponent } from 'vue';
        import { useFetchData } from './customHooks.js'; // 假设自定义钩子在这个文件中
        export default defineComponent({
          name: 'DataComponent',
          setup() {
            const { data, loading, error } = useFetchData('https://api.example.com/data');
            return {
              data,
              loading,
              error
            };
          }
        });
      </script>
      

九、Teleport 组件

Teleport是 Vue 3 中一个很有用的特性,它允许你将一个组件的模板内容渲染到 DOM 中的其他位置,而不是默认的组件挂载点。

  1. 基本用法
    • 例如,有一个模态框组件,你可能希望它的内容渲染到页面的body元素上,而不是组件所在的位置,这样可以避免模态框的样式受到组件自身布局的限制。
    • 首先,在模板中使用Teleport组件:
      <template>
        <Teleport to="body">
          <div class="modal">
            <h2>这是一个模态框</h2>
            <p>模态框的内容</p>
            <button @click="closeModal">关闭</button>
          </div>
        </Teleport>
      </template>
      
      <script>
        import { defineComponent } from 'vue';
        export default defineComponent({
          name: 'ModalComponent',
          data() {
            return {
              isModalOpen: true
            };
          },
          methods: {
            closeModal() {
              this.isModalOpen = false;
            }
          }
        });
      </script>
      
    • 在上述代码中,Teleport组件将内部的div.modal内容渲染到了body元素上。你可以通过修改to属性的值来指定将内容渲染到其他的 DOM 元素上,比如一个特定的div元素的 ID。
  2. 与 CSS 样式结合
    • 当使用Teleport时,需要注意样式的应用。因为内容被渲染到了其他位置,所以可能需要特别处理样式。
    • 可以在全局样式中或者在组件的style标签中使用适当的选择器来确保模态框的样式正确应用。例如:
      /* 全局样式 */
      body.modal {
        position: fixed;
        top: 50%;
        left: 50%;
        transform: translate(-50%, -50%);
        background-color: white;
        padding: 20px;
        border-radius: 5px;
        box-shadow: 0 0 10px rgba(0, 0, 0, 0.3);
      }
      
    • 或者在组件的style标签中使用scoped样式(如果只想应用于当前组件的模态框):
      <template>
        <!-- 模态框内容等 -->
      </template>
      
      <script>
        // 组件脚本
      </script>
      
      <style scoped>
      .modal {
         /* 模态框的样式与上面类似 */
       }
      </style>
      

十、Suspense 组件

Suspense组件用于处理异步加载的组件,它可以提供一个更友好的加载状态显示方式,当异步组件正在加载时,可以显示一个加载占位符,加载完成后再显示实际的组件内容。

  1. 使用场景
    • 例如,当你有一个组件需要从服务器获取大量数据后才能渲染,在数据获取过程中,页面可能会出现空白或者加载缓慢的情况。使用Suspense可以在这个过程中显示一个加载提示,提升用户体验。
  2. 基本用法
    • 首先,创建一个异步组件。假设我们有一个AsyncComponent,它在setup函数中模拟异步数据获取:
      // AsyncComponent.vue
      import { defineComponent, ref } from 'vue';
      export default defineComponent({
        name: 'AsyncComponent',
        async setup() {
          const data = ref(null);
          // 模拟异步获取数据,这里使用 setTimeout 代替实际的异步请求
          await new Promise((resolve) => setTimeout(resolve, 2000));
          data.value = '异步数据获取成功';
          return {
            data
          };
        },
        template: '<div>{{ data }}</div>'
      });
      
    • 然后,在使用这个异步组件的父组件中,使用Suspense包裹:
      <template>
        <Suspense>
          <template #default>
            <AsyncComponent />
          </template>
          <template #fallback>
            <div>正在加载...</div>
          </template>
        </Suspense>
      </template>
      
      <script>
        import { defineComponent } from 'vue';
        import AsyncComponent from './AsyncComponent.vue';
        export default defineComponent({
          name: 'ParentComponent',
          components: {
            AsyncComponent
          }
        });
      </script>
      
    • 在上述代码中,#default插槽中是要异步加载的组件(AsyncComponent),#fallback插槽中是当异步组件正在加载时显示的内容(这里是一个简单的“正在加载…”提示)。

十一、性能优化

  1. 代码分割
    • 在大型 Vue 应用中,为了提高页面加载速度,可以使用代码分割技术。Vue CLI 已经内置了对代码分割的支持。例如,对于一些大型的库或者模块,可以将其分割成单独的 chunk(代码块),在需要时再进行加载。
    • 在路由配置中,可以使用import()函数进行动态导入路由组件,这样相关的代码会被自动分割成单独的 chunk。
    • 示例代码(在router/index.js中):
      const routes = [
        {
          path: '/',
          name: 'Home',
          component: () => import('../views/Home.vue') // 动态导入Home.vue组件
        },
        {
          path: '/about',
          name: 'About',
          component: () => import('../views/About.vue') // 动态导入About.vue组件
        }
      ];
      
  2. 虚拟列表(Virtual List)
    • 当处理大量列表数据时,例如渲染一个包含数千条记录的列表,可能会导致性能问题。可以使用虚拟列表技术,只渲染当前可见区域的列表项,提高渲染性能。
    • 可以使用第三方库如vue-virtual-scroller来实现虚拟列表。首先,安装该库:npm install vue-virtual-scroller
    • 然后,在组件中使用:
      <template>
        <div>
          <VirtualList :data="bigDataList" :item-size="50">
            <template #default="{ item }">
              <div>{{ item.name }}</div>
            </template>
          </VirtualList>
        </div>
      </template>
      
      <script>
        import { defineComponent } from 'vue';
        import VirtualList from 'vue-virtual-scroller';
        export default defineComponent({
          name: 'ListComponent',
          components: {
            VirtualList
          },
          data() {
            return {
              bigDataList: [] // 假设这是一个包含大量数据的数组
            };
          },
          async mounted() {
            // 模拟获取大量数据
            const response = await fetch('https://api.example.com/largeData');
            const data = await response.json();
            this.bigDataList = data;
          }
        });
      </script>
      
    • 在上述代码中,VirtualList组件根据列表项的高度(item-size)和当前可见区域来计算需要渲染的列表项,大大提高了性能,特别是在处理长列表时。
  3. 避免不必要的重新渲染
    • Vue 的响应式系统会自动跟踪数据的变化并触发组件的重新渲染。但有时候,一些不必要的数据变化可能会导致组件频繁重新渲染,影响性能。
    • 可以使用Object.freeze()方法来冻结一些不会变化的数据对象,避免 Vue 对其进行深度响应式追踪。例如:
      import { defineComponent, ref } from 'vue';
      export default defineComponent({
        name: 'MyComponent',
        setup() {
          const staticData = ref({ name: '静态数据', value: 123 });
          Object.freeze(staticData.value); // 冻结数据对象
          const dynamicData = ref({ count: 0 });
          const incrementCount = () => {
            dynamicData.value.count++;
          };
          return {
            staticData,
            dynamicData,
            incrementCount
          };
        }
      });
      
    • 在上述代码中,staticData中的数据不会被 Vue 深度追踪,因为它被冻结了,只有dynamicData中的数据变化会导致组件重新渲染,这样可以提高性能,特别是当有大量静态数据且不需要频繁更新时。

十二、部署

  1. 构建生产版本
    • 在项目开发完成后,需要构建生产版本的代码。在项目目录下的终端中运行npm run build。这会将项目中的代码进行压缩、优化等处理,生成适合部署到生产环境的文件。
    • 构建完成后,会在项目目录下生成一个dist文件夹,其中包含了index.html文件以及jscss等静态资源文件。
  2. 部署到服务器
    • 部署的方式有很多种,常见的有部署到云服务器(如阿里云、腾讯云等)、虚拟主机等。
    • 以部署到 Nginx 服务器为例:
      • dist文件夹中的所有文件上传到服务器的指定目录(例如/var/www/html/my-vue-app)。
      • 配置 Nginx 服务器,创建一个新的站点配置文件(例如/etc/nginx/sites-available/my-vue-app.conf),内容如下:
        server {
          listen 80;
          server_name your_domain.com; // 替换为你的域名
        
          root /var/www/html/my-vue-app;
        
          location / {
            try_files $uri $uri/ /index.html;
          }
        }
        
      • 然后将该配置文件链接到sites-enabled目录下:sudo ln -s /etc/nginx/sites-available/my-vue-app.conf /etc/nginx/sites-enabled/
      • 最后,重启 Nginx 服务器:sudo service nginx restart
      • 现在,你就可以通过浏览器访问你的域名来查看部署的 Vue 应用了。

大家认真阅读!早日腾飞!一键三连!!!!!!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2224555.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

WPF+MVVM案例实战(六)- 自定义分页控件实现

文章目录 1、项目准备2、功能实现1、分页控件 DataPager 实现2、分页控件数据模型与查询行为3、数据界面实现 3、运行效果4、源代码获取 1、项目准备 打开项目 Wpf_Examples&#xff0c;新建 PageBarWindow.xaml 界面、PageBarViewModel.cs ,在用户控件库 UserControlLib中创建…

WASM 使用说明23事(RUST实现)

文章目录 1. wasm是什么1.1 chatgpt定义如下:1.2 wasm关键特性&#xff1a; 2. wasm demo2.1 cargo 创建项目2.2 编写code2.3 安装wasm-pack2.4 编译 3.1 html页面引用wasm代码&#xff08;js引用&#xff09;3.2 访问页面4 导入js function4.1 编写lib.rs文件&#xff0c;内容…

UML 总结(基于《标准建模语言UML教程》)

定义 UML 又称为统一建模语言或标准建模语言&#xff0c;是一种标准的图形化建模语言&#xff0c;它是面向对象分析与设计的一种标准表示。尽管UML 本身没有对过程有任何定义&#xff0c;但UML 对任何使用它的方法&#xff08;或过程&#xff09;提出的要求是&#xff1a;支持用…

【含开题报告+文档+PPT+源码】基于vue框架的东升餐饮点餐管理平台的设计与实现

开题报告 在当前信息化社会背景下&#xff0c;餐饮行业正经历着由传统线下服务模式向线上线下深度融合的转变。随着移动互联网技术及大数据应用的飞速发展&#xff0c;用户对于餐饮服务平台的需求也日益多元化和个性化。他们期望能在一个集便捷、高效、个性化于一体的平台上完…

自动化测试工具Ranorex Studio(十六)-添加新Action

在Action表中&#xff0c;有两种手动添加action的方式。 一种方法是指定Action本身&#xff08;’添加新Action’&#xff09;&#xff0c;然后分配对应的对象库条目&#xff08;在多数情况下&#xff09;。 第二种方法是直接把对象库条目拖放到Action表内&#xff0c;然后生成…

力扣 中等 2466.统计构造好字符串的方案数

文章目录 题目介绍题解 题目介绍 题解 题意&#xff1a;每次可以爬 zero 或 one 个台阶&#xff0c;返回爬 low 到 high 个台阶的方案数。 和上题337.组合总和 &#xff08;链接&#xff09;的思路一样&#xff0c;只不过是将可以爬的台阶数从数组换成了两个数&#xff08;ze…

视频美颜平台的搭建指南:基于直播美颜SDK的完整解决方案

众所周知&#xff0c;直播美颜SDK是实现视频美颜功能的核心。本文将详细解析如何基于直播美颜SDK搭建一个完整的视频美颜平台。 一、视频美颜SDK的核心功能 直播美颜SDK作为平台的技术核心&#xff0c;能够提供丰富的美颜效果和稳定的视频处理能力。通常&#xff0c;SDK具备以…

iOS AVAudioSession 详解【音乐播放器的配置】

前言 在 iOS 音频开发中&#xff0c;AVAudioSession 是至关重要的工具&#xff0c;它控制着应用的音频行为&#xff0c;包括播放、录音、后台支持和音频中断处理等。对于音乐播放器等音频需求强烈的应用&#xff0c;设计一个合理的 AVAudioSession 管理体系不仅能保证音频播放…

RabbitMQ是一个开源的消息代理和队列服务器

RabbitMQ是一个开源的消息代理和队列服务器&#xff0c;它基于AMQP&#xff08;Advanced Message Queuing Protocol&#xff0c;高级消息队列协议&#xff09;协议实现&#xff0c;同时也支持其他消息协议如STOMP、MQTT等。作为一个可靠的消息传递服务&#xff0c;RabbitMQ在分…

青少年CTF平台的基础题writeup

青少年CTF平台 1、文章管理系统 首先他这里有一个问号id&#xff0c;就想着使用mysql跑一下&#xff0c;但是windows的sqlmap很不给力&#xff0c;都不动&#xff0c;所以我后面换成了kali机来跑 跑一下就跑出了好多的数据库 第一次我使用ctftraining不出货&#xff0c;跑的一…

Coppelia Sim (v-REP)仿真 机器人3D相机手眼标定与实时视觉追踪 (一)

coppelia sim[V-REP]仿真实现 机器人于3D相机手眼标定与实时视觉追踪 一 标定板的制作生成标定的PDF文件PDF转为图像格式图像加载到仿真中 二 仿真场景设置加载机器人加载的控制dummy ![在这里插入图片描述](https://i-blog.csdnimg.cn/direct/b48549d355d8441d8dfc20bc7ba7196…

【K8S系列】Kubernetes Pod节点CrashLoopBackOff 状态及解决方案详解【已解决】

在 Kubernetes 中&#xff0c;Pod 的状态为 CrashLoopBackOff 表示某个容器在启动后崩溃&#xff0c;Kubernetes 尝试重启该容器&#xff0c;但由于持续崩溃&#xff0c;重启的间隔时间逐渐增加。下面将详细介绍 CrashLoopBackOff 状态的原因、解决方案及相关命令的输出解释。 …

.NET Core WebApi第1讲(概念):Web基础、AJAX、JQuery

动态页面&#xff1a;数据流动 / Web服务器 / Ajax / 前后端分离 / restful风格源栈课堂一起帮https://17bang.ren/Code/261 一、Web基础 二、AJAX诞生 三、JQuery

ctfshow(262,264)--反序列化漏洞--字符串逃逸

Web262 源代码&#xff1a; index.php: error_reporting(0); class message{public $from;public $msg;public $to;public $tokenuser;public function __construct($f,$m,$t){$this->from $f;$this->msg $m;$this->to $t;} }$f $_GET[f]; $m $_GET[m]; $t $_…

虚拟现实新纪元:VR/AR技术将如何改变娱乐与教育

内容概要 在当今科技飞速发展的时代&#xff0c;虚拟现实&#xff08;VR&#xff09;和增强现实&#xff08;AR&#xff09;技术不仅让我们的娱乐体验如虎添翼&#xff0c;更为教育变革注入了新活力。这些技术的飞跃进展&#xff0c;将原本平淡无奇的场景转变为令人沉醉的沉浸…

HICP--2

在area 0的路由器只生成 area 0 的数据库&#xff0c;只在area 1 的一样。但是既在又在的生成两个 area的 LSDB 一、区域间三类LSA 在OSPF&#xff08;Open Shortest Path First&#xff09;协议中&#xff0c;区域间三类LSA&#xff08;Link-State Advertisement&#xff09…

【UE5】将2D切片图渲染为体积纹理,最终实现使用RT实时绘制体积纹理【第七篇-体积纹理绘制】

我们前几篇已经完成了渲染部分&#xff0c;现在终于开始做动态绘制功能了 之前使用的是这样一个体积雾的切片图&#xff0c;那么现在要做的就是动态编辑它 首先&#xff0c;让我们简单了解一下它是如何运作的&#xff1a; 开始绘制画布以渲染目标&#xff0c;并将材质绘制到画…

Python字幕滚动:为视频添加专业级动态效果!

Python实现由下向上滚动字幕 在数字媒体和编程领域&#xff0c;动态文本效果总能吸引观众的注意力。其中&#xff0c;滚动字幕是一种常见的视觉效果&#xff0c;经常用于视频、演示文稿和网页中。在Python中&#xff0c;我们可以通过多种方式来实现滚动字幕效果&#xff0c;比…

《2024中国泛娱乐出海洞察报告》解析,垂直且多元化方向发展!

随着以“社交”为代表的全球泛娱乐市场规模不断扩大以及用户需求不断细化&#xff0c;中国泛娱乐出海产品正朝着更加垂直化、多元化的方向发展。基于此&#xff0c;《2024中国泛娱乐出海洞察报告》深入剖析了中国泛娱乐行业出海进程以及各细分赛道出海现状及核心特征。针对中国…

qt QMediaPlaylist

QMediaPlaylist 是 Qt Multimedia 模块中的一个类&#xff0c;用于管理媒体文件的播放列表。它提供了一种方便的方式来组织和控制多媒体内容的播放&#xff0c;如音频和视频文件。 主要方法 QMediaPlaylist(00bject *parent nullptr):构造一个新的媒体播放列表对象。void add…