vue3入门知识(一)

vue3简介

性能的提升

  • 打包大小减少41%
  • 初次渲染快55%,更新渲染快133%
  • 内存减少54%

源码的升级

  • 使用Proxy代替defineProperty实现响应式
  • 重写虚拟DOM的实现和Tree-Shaking

新的特性

  1. Composition API(组合API)
  • setup
  • ref与reactive
  • computed与watch
  1. 新的内置组件
  • Fragment
  • Teleport
  • Suspense
  1. 其他改变
  • 新的生命周期钩子
  • data选项应始终被声明为一个函数
  • 移除keyCode支持作为v-on的修饰符

创建vue3项目

基于vue-cli创建(基于webpack)

复制代码
// 安装或升级@vue.cli
npm install -g @vue/cli

// 执行创建命令
vue create project_name

基于vite创建

vite是新一代前端构建工具,官网地址:Vite中文网

vite的优势:

  • 轻量快速的热重载(HMR),能实现极速的服务启动
  • 对TypeScript、JSX、CSS等支持开箱即用
  • 真正的按需编译,不再等待整个应用编译完成
  • webpack构建与vite构建对比图如下:

webpack构建:

vite构建:

创建项目的命令

复制代码
npm create vue@latest

Tips:

  • 确保 Node.js 版本支持 Vue 3:推荐使用 Node.js 14 及以上版本

尝试使用node版本 14.21.3,创建项目时有报错,升级node版本为 16.20.2 之后就可以了

创建项目时的一些配置项设置,仅供参考

安装好的项目文件目录:

这个文件里面有报错,执行一下 npm install 就好了

并且这个文件里面的内容不能删除,他的作用是告诉 TypeScript 引入 Vite 的类型定义

可能还会有上图中这样的报错提示,在确保已经执行npm install之后,重新打开编辑器,报错提示就会消失了

选项式API的弊端

vue2(选项式API)数据、方法、计算属性等,是分散在:data、methods、computed中的,若想新增或者修改一个需求,就需要分别修改data、methods、computed,不便于维护和复用

组合式API的优势

可以用函数的方式,更加优雅的组织代码,让相关功能的代码有序的组织在一起

setup

setup中的this是undefined,vue3中已经弱化this了

setup的执行顺序在beforeCreate之前

setup的返回值可以是一个渲染函数,返回内容直接渲染在页面上

javascript 复制代码
return () => '直接在页面上展示的内容'
javascript 复制代码
<template>
    <div class="person">
        <h2>姓名:{{ name }}</h2>
        <h2>年龄:{{ age }}</h2>
        <button @click="changeName">修改姓名</button>
        <button @click="changeAge">修改年龄</button>
        <button @click="showTel">查看联系方式</button>
    </div>
</template>

<script lang="ts">
export default {
    // eslint-disable-next-line vue/multi-word-component-names
    name: 'Person',
    setup() {
        // 这样写的name age tel不是响应式的 vue2中是写在data中的
        let name = '张三';
        let age = 18;
        const tel = '13800138000';

        function changeName() {
            name = '李四'; // 这样修改之后页面不会更新 值确实改了但不是响应式的 因此页面未更新
        };

        function changeAge() {
            age += 1;
        };

        function showTel() {
            alert(tel);
        };

        // 将数据、方法交出去,模板中才可以使用
        return {
            name,
            age,
            tel,
            changeName,
            changeAge,
            showTel,
        };
    },
};
</script>

<style scoped lang="less">
.person {
    button {
        display: block;
        margin: 10px 0;
    }
}
</style>

data、methods可以和setup同时存在

data中可以读取setup中的数据,通过this.xxx来获取,但是setup中是无法读取data中的数据的,因为setup是在data之前执行的

setup语法糖

javascript 复制代码
<template>
    <div class="person">
        <h2>姓名:{{ name }}</h2>
        <h2>年龄:{{ age }}</h2>
        <button @click="changeName">修改姓名</button>
        <button @click="changeAge">修改年龄</button>
        <button @click="showTel">查看联系方式</button>
    </div>
</template>

<script lang="ts">
export default {
    // eslint-disable-next-line vue/multi-word-component-names
    name: 'Person',
};
</script>

<script setup lang="ts">
// 这样写的name age tel不是响应式的 vue2中是写在data中的
let name = '张三';
let age = 18;
const tel = '13800138000';

function changeName() {
    name = '李四'; // 这样修改之后页面不会更新 值确实改了但不是响应式的 因此页面未更新
};
function changeAge() {
    age += 1;
};
function showTel() {
    alert(tel);
};
</script>

<style scoped lang="less">
.person {
    button {
        display: block;
        margin: 10px 0;
    }
}
</style>

由于这样需要写两块script标签 ,第一块的主要作用是自定义组件名称,可以借助插件,省略第一块script标签

javascript 复制代码
npm i vite-plugin-vue-setup-extend -D

安装之后在 vite.config.ts 中进行引入配置

javascript 复制代码
<template>
    <div class="person">
        <h2>姓名:{{ name }}</h2>
        <h2>年龄:{{ age }}</h2>
        <button @click="changeName">修改姓名</button>
        <button @click="changeAge">修改年龄</button>
        <button @click="showTel">查看联系方式</button>
    </div>
</template>

<script setup lang="ts" name="Person"> 
// 这样写的name age tel不是响应式的 vue2中是写在data中的
let name = '张三';
let age = 18;
const tel = '13800138000';

function changeName() {
    name = '李四'; // 这样修改之后页面不会更新 值确实改了但不是响应式的 因此页面未更新
};
function changeAge() {
    age += 1;
};
function showTel() {
    alert(tel);
};
</script>

<style scoped lang="less">
.person {
    button {
        display: block;
        margin: 10px 0;
    }
}
</style>

ref

用于(可以)定义基本类型的响应式数据,也可以定义对象类型的响应式数据,想让哪个数据是响应式的 就用ref包一下,在js代码中使用响应式数据需要用 .value 在模板中不需要

javascript 复制代码
<template>
    <div class="person">
        <h2>姓名:{{ name }}</h2>
        <h2>年龄:{{ age }}</h2>
        <h2>地址:{{ address }}</h2>
        <button @click="changeName">修改姓名</button>
        <button @click="changeAge">修改年龄</button>
        <button @click="showTel">查看联系方式</button>
    </div>
</template>

<script setup lang="ts" name="Person"> 
import { ref } from 'vue';

let name = ref('张三');
let age = ref(18);
const tel = '13800138000';
const address = '北京';

function changeName() {
    name.value = '李四';
};
function changeAge() {
    age.value += 1;
};
function showTel() {
    alert(tel);
};
</script>

<style scoped lang="less">
.person {
    button {
        display: block;
        margin: 10px 0;
    }
}
</style>

定义对象类型的响应式数据,表面使用的是ref,其实底层用的还是reactive

javascript 复制代码
<template>
    <div class="person">
        <h2>汽车信息: 一辆{{ car.brand }}车,价值{{ car.price }}</h2>
        <button @click="changePrice">修改汽车的价格</button>
        <br>
        <h2>游戏列表: </h2>
        <ul>
            <li v-for="game in games" :key="game.id">
                {{ game.name }}
            </li>
        </ul>
        <button @click="changeFirstGameName">修改第一个游戏的名字</button>
    </div>
</template>

<script setup lang="ts" name="Person"> 
import { ref } from 'vue';

let car = ref({
    brand: 'BMW',
    price: 100,
});
let games = ref([
    { name: 'LOL', id: 1 },
    { name: 'CSGO', id: 2 },
    { name: 'DOTA', id: 3 },
]);

function changePrice() {
    car.value.price += 10;
};
function changeFirstGameName() {
    games.value[0].name = '王者荣耀';
};
</script>

reactive

用于(只能)定义对象类型的响应式数据

javascript 复制代码
<template>
    <div class="person">
        <h2>汽车信息: 一辆{{ car.brand }}车,价值{{ car.price }}</h2>
        <button @click="changePrice">修改汽车的价格</button>
        <br>
        <h2>游戏列表: </h2>
        <ul>
            <li v-for="game in games" :key="game.id">
                {{ game.name }}
            </li>
        </ul>
        <button @click="changeFirstGameName">修改第一个游戏的名字</button>
        <br>
        <h2>{{ obj.a.b.c }}</h2>
        <button @click="changeObj">修改obj</button>
    </div>
</template>

<script setup lang="ts" name="Person"> 
import { reactive } from 'vue';

let car = reactive({
    brand: 'BMW',
    price: 100,
});
let games = reactive([
    { name: 'LOL', id: 1 },
    { name: 'CSGO', id: 2 },
    { name: 'DOTA', id: 3 },
]);
let obj = reactive({
    a: {
        b: {
            c: 666,
        }
    }
})

function changePrice() {
    car.price += 10;
};
function changeFirstGameName() {
    games[0].name = '王者荣耀';
};
function changeObj() {
    // reactive的响应式是深层次的
    obj.a.b.c = 1000;
};
</script>

ref与reactive

  1. ref用来定义:基本类型数据、对象类型数据

  2. reactive用来定义:对象类型数据

区别:

  1. ref创建的变量必须使用 .value (可以使用volar插件自动添加 .value)

  2. reactive重新分配一个新对象,会失去响应式(可以使用Object.assign去整体替换)

javascript 复制代码
<template>
    <div class="person">
        <h2>汽车信息: 一辆{{ car.brand }}车,价值{{ car.price }}</h2>
        <button @click="changeCar">修改汽车</button>
    </div>
</template>

<script setup lang="ts" name="Person"> 
import { reactive } from 'vue';

let car = reactive({
    brand: 'BMW',
    price: 100,
});

function changeCar() {
    // 这样会失去响应式
    // car = {
    //     brand: '奔驰',
    //     price: 200,
    // };
    
    // 这样不会失去响应式
    Object.assign(car, {
        brand: '奔驰',
        price: 200,
    });
};
</script>

使用原则:

  1. 若需要一个基本类型的响应式数据,必须使用ref

  2. 若需要一个响应式对象,层级不深,ref、reactive都可以

  3. 若需要一个响应式对象,且层级较深,推荐使用reactive

toRefs

把一个响应式对象中的内容拿出来,依然具备响应式的能力

javascript 复制代码
<template>
    <div class="person">
        <h2>{{ person.name }}</h2>
        <h2>{{ person.age }}</h2>
        <button @click="changeName">修改姓名</button>
        <button @click="changeAge">修改年龄</button>
    </div>
</template>

<script setup lang="ts" name="Person"> 
import { reactive, toRefs } from 'vue';

const person = reactive({
    name: '张三',
    age: 18,
});

// 直接从响应式对象中解构出来的变量都不是响应式的 需要toRefs包裹才会变成响应式的
let { name, age } = toRefs(person);

function changeName() {
    // 这里修改之后 name、person.name 都会改变
    name.value += '~';
};
function changeAge() {
    age.value += 1;
};
</script>

<style scoped lang="less">
.person {
    button {
        margin: 10px;
    }
}
</style>

toRef

作用和toRefs一样,但每次只能取一个

javascript 复制代码
<template>
    <div class="person">
        <h2>{{ person.name }}</h2>
        <h2>{{ person.age }}</h2>
        <button @click="changeName">修改姓名</button>
    </div>
</template>

<script setup lang="ts" name="Person"> 
import { reactive, toRef } from 'vue';

const person = reactive({
    name: '张三',
    age: 18,
});

let name = toRef(person, 'name');

function changeName() {
    // 这里修改之后 name、person.name 都会改变
    name.value += '~';
};
</script>
相关推荐
树叶会结冰18 分钟前
HTML语义化:当网页会说话
前端·html
冰万森23 分钟前
解决 React 项目初始化(npx create-react-app)速度慢的 7 个实用方案
前端·react.js·前端框架
牧羊人_myr36 分钟前
Ajax 技术详解
前端
浩男孩1 小时前
🍀封装个 Button 组件,使用 vitest 来测试一下
前端
蓝银草同学1 小时前
阿里 Iconfont 项目丢失?手把手教你将已引用的 SVG 图标下载到本地
前端·icon
布列瑟农的星空1 小时前
重学React —— React事件机制 vs 浏览器事件机制
前端
程序定小飞1 小时前
基于springboot的在线商城系统设计与开发
java·数据库·vue.js·spring boot·后端
一小池勺1 小时前
CommonJS
前端·面试
孙牛牛2 小时前
实战分享:一招解决嵌套依赖版本失控问题,以 undici 为例
前端