Vue.js 框架作者尤雨溪宣布:Vue3 将在 2022 年 2 月 7 成为新的默认版本, 还有就是状态管理工具库 Pinia 也纳入官方维护, Vue3也即将成为默认版本,那作为技术员,不搞起来,有点对不起头发呀.
对于使用 React 的重度用户,对于 hooks 和 JSX 都爱不释手吧. vue3 现在也是开发起来非常丝滑的哦. 加上 Volar 工具的加持,你值得拥有.
script setup
script setup是在单文件组件 (SFC) 中使用组合式 API的编译时语法糖。
<template>
<button @click="inc">点我</button>
<p>{{ count }}</p>
</template>
<script setup lang="ts">
const props = defineProps({
// 注意这是只读的
count: {
type: Number,
required: true,
},
});
const emit = defineEmits(["inc"]);
const inc = () => {
console.log("child", props.count);
emit("inc", Math.random());
};
const someFn = () => {
console.log("defineExpose");
};
// 暴露给组件实例调用的属性方法
defineExpose({
someFn,
a: 3,
});
</script>
<style></style>
jsx 使用
import { defineComponent, ref, onMounted } from "vue";
import { NButton } from "naive-ui";
import Counter from "@/components/Counter.vue";
export default defineComponent({
name: "App",
setup() {
const count = ref<number>(0);
const refCounter = ref<any>(null);
const handleInc = (v: number) => {
console.log("parent method", v);
count.value = v;
// 通过组件实例组件获取组件自己内部通过 defineExpose 暴露的信息
console.log(refCounter.value.a);
refCounter.value.someFn();
};
onMounted(() => {
console.log("mounted");
});
return () => (
<>
{/* 注意子组件传递出来的,名字格式 onXxx 的形式*/}
<Counter ref={refCounter} count={count.value} onInc={handleInc} />
</>
);
},
});
package.json 文件信息
{
"name": "Vite2-Vue3-TypeScript-Pinia-JSX",
"version": "1.0.0",
"main": "index.js",
"scripts": {
"dev": "vite",
"serve": "yarn build && yarn dev preview",
"build": "vite build",
"build:dev": "vue-tsc --noEmit && yarn build --mode development",
"build:pro": "vue-tsc --noEmit && yarn build --mode production",
"lint": "eslint src --ext .ts,.tsx,.vue,.js,.jsx",
"lint:fix": "eslint src --fix --cache --ext .ts,.tsx,.vue,.js,.jsx",
"prettier": "prettier --write src/**/*.{js,css,md,ts,tsx,vue}",
"prepare": "husky install"
},
"devDependencies": {
"@commitlint/cli": "^16.2.1",
"@commitlint/config-conventional": "^16.2.1",
"@types/node": "^17.0.21",
"@types/nprogress": "^0.2.0",
"@typescript-eslint/eslint-plugin": "^5.12.1",
"@typescript-eslint/parser": "^5.12.1",
"@vitejs/plugin-vue": "^2.2.2",
"@vitejs/plugin-vue-jsx": "^1.3.7",
"@vue/compiler-sfc": "^3.2.31",
"@vue/eslint-config-prettier": "^7.0.0",
"@vue/eslint-config-typescript": "^10.0.0",
"eslint": "^8.10.0",
"eslint-config-prettier": "^8.4.0",
"eslint-plugin-prettier": "^4.0.0",
"eslint-plugin-vue": "^8.5.0",
"husky": "^7.0.4",
"prettier": "^2.5.1",
"sass": "^1.49.9",
"typescript": "^4.5.5",
"vite": "^2.8.4",
"vite-plugin-compression": "^0.5.1",
"vue-tsc": "^0.32.0"
},
"dependencies": {
"axios": "^0.26.0",
"naive-ui": "^2.25.5",
"nprogress": "^0.2.0",
"pinia": "^2.0.11",
"vue": "^3.2.31",
"vue-router": "^4.0.12"
},
"husky": {
"hooks": {
"pre-commit": "lint-staged"
}
},
"lint-staged": {
"src/**/*.{js,css,md,ts,tsx}": [
"yarn prettier",
"yarn lint:fix",
"git add"
]
},
"license": "MIT"
}
vite 配置
import path from "path";
import { defineConfig } from "vite";
import vue from "@vitejs/plugin-vue";
import vueJsx from "@vitejs/plugin-vue-jsx";
import viteCompression from "vite-plugin-compression";
export default defineConfig({
base: "./", // 开发或生产环境服务的公共基础路径 ,https://vitejs.bootcss.com/guide/build.html#public-base-path
build: {
outDir: "dist", // 打包后的文件名称,
terserOptions: {
// 生产环境下移除 debugger console
compress: {
drop_console: false,
drop_debugger: true,
},
},
rollupOptions: {
output: {
// manualChunks(id) {
// if (id.includes('node_modules')) {
// return id.toString().split('node_modules/')[1].split('/')[0].toString();
// }
// }
manualChunks: {
odash: ["lodash"],
},
},
},
},
plugins: [
vue(),
// 支持 jsx 写法
vueJsx({
transformOn: true,
mergeProps: true,
}),
// gzip压缩 生产环境生成 .gz 文件
viteCompression({
verbose: true,
disable: false,
threshold: 10240,
algorithm: "gzip",
ext: ".gz",
}),
],
resolve: {
extensions: [".ts", ".tsx", ".js", ".jsx", ".json"], // vite 后缀查找
alias: {
"@": path.resolve(__dirname, "src"), // 别名路径
},
},
css: {
preprocessorOptions: {
scss: {
additionalData: '@import "@/assets/style/global.scss";', // 配置全局 scss
},
},
},
optimizeDeps: {
include: [], // 第三方库
},
//启动服务配置
server: {
open: true, // 是否自动打开浏览器
https: false, // 是否开启https
port: 3000, // 端口号
host: true, // 指定服务器应该监听哪个 IP 地址。 如果将此设置为 0.0.0.0 或者 true 将监听所有地址,包括局域网和公网地址。
hmr: {
// 热替换
overlay: true, // 是否开启错误的阴影层
},
proxy: {
"/api": {
target: "http://xxx.xx.x", // 后台接口,
changeOrigin: true,
secure: false, // 如果是 https 接口需要配置这个参数
// ws:false, // websocket
rewrite: (path) => path.replace(/^\/api/, ""), // 路径重写
},
},
},
});