vue3.0创建项目学习记录
一、vue3.0已经发布啦~记录一下自己创建vue3.0项目的体验过程。此刻就想放张图:二、更新的一些东西Object.defineProperty => Proxyvdom 静态标记更加强大Composition APIvite三、初始项目一改vue2.x使用vue-cli, vue3.0基于vite去创建项目:npm init vite-app <project-name>c
一、vue3.0已经发布啦~
记录一下自己创建vue3.0项目的体验过程。
此刻就想放张图:
二、更新的一些东西
- Object.defineProperty => Proxy
- vdom 静态标记更加强大
- Composition API
- vite
三、初始项目
一改vue2.x使用vue-cli, vue3.0基于vite去创建项目:
npm init vite-app <project-name>
cd <project-name>
npm install
npm run dev
四、项目结构
├── index.html
├── package.json
├── public
│ └── favicon.ico
└── src
├── App.vue
├── assets
│ └── logo.png
├── components
│ └── HelloWorld.vue
├── index.css
└── main.js
index.html/main.js
可以看到 main.js的引用写了type="module"
,利用浏览器的自带的import机制;
index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<link rel="icon" href="/favicon.ico" />
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Vite App</title>
</head>
<body>
<div id="app"></div>
<script type="module" src="/src/main.js"></script>
</body>
</html>
- main.js 初始实例不再是
new vue(option)
,改为了createApp(App)
Vue.prototype
扩展方法改为了app.config.globalProperties
- 还有一个需要注意的地方,vue3.0 setup内部不支持this,像vue2.x里可以 Vue.prototype扩展一些全局方法,在页面使用直接this就可以访问,在
Composition API
里面已经不能这么玩了😂。
main.js
import { createApp } from 'vue'
import App from './App.vue'
import './assets/index.css'
import * as config from './utils/config_globalProperties.ts'
const app = createApp(App);
// app.config: 全局配置的对象
// app.config.globalProperties代替Vue 2.x Vue.prototype 扩展
// vue3.0 setup内部不支持this, 一些公共方法挂载vue也是访问不到的
Object.keys(config).forEach(ele => {
app.config.globalProperties[ele] = config[ele]
});
// 应用挂载
app.mount('#app');
五、Composition API
1.setup
组件选项创建后在组件创建之前执行的组件选项,它用作组合API的入口点,相当于beforCreated()
、created()
;
vue2.x 在写页面的时候,script
里面,是写的option Api
导出一个对象,对象里面就是data
、methods
、mounted
…
现在直接一个setup
函数,在setup
里面把数据return给template;
下面是官网的例子,非常清晰:
<!-- MyBook.vue -->
<template>
<div>{{ readersNumber }} {{ book.title }}</div>
</template>
<script>
import { ref, reactive } from 'vue'
export default {
setup() {
const readersNumber = ref(0)
const book = reactive({ title: 'Vue 3 Guide' })
// expose to template
return {
readersNumber,
book
}
}
}
</script>
2.ref
是对基本数据类型数据进行双向绑定的Api,经过ref过的数据,需要通过value属性拿到值;
import { ref } from "vue";
...
const a = ref(0);
console.log(a.value) // 0
...
3.reactive
引用数据类型的数据使用reactive
,使用reactive
有一个要注意的点,最好不要对reactive过的对象做解构操作,会使reactive过的对象里面的基本数据类型失去双向绑定,对解构的数据做更改是不会再去更新reactive的这个对象了。建议对reactive的数据慎用解构,直接操作reactive的对象,免得导致一些不必要的坑;
import { reactive } from "vue";
...
let obj = reactive({
a: "a",
b: "b",
c: {
c1: "c1",
},
});
// 数据更新
obj.a = "我是a呀";
obj.b = "我是b呀";
obj.c.c1 = "我是c1呀";
// 注意:对reactive的数据解构会导致 基础数据类型 失去reactive
let { a, c } = obj;
a = "我是被解构的a"; // 已经脱离reactive
c.c1 = "我是被解构的c1"; // 还是可以更改到obj
console.log(obj); // {a: "我是a呀",b: "我是b呀",c: {c1: "我是被解构的c1"}}
console.log(a); // 我是被解构的a
console.log(c); // {c1: "我是被解构的c1"}
...
4.Lifecycle Hooks 生命周期
composition Api
里面生命周期也有所变化,beforeCreate
、created
被setup替代,其他生命周期均多了on
:
->beforeCreate
use setup()
->created
use setup()
beforeMount
->onBeforeMount
mounted
->onMounted
beforeUpdate
->onBeforeUpdate
updated
->onUpdated
beforeUnmount
->onBeforeUnmount
unmounted
->onUnmounted
errorCaptured
->onErrorCaptured
renderTracked
->onRenderTracked
renderTriggered
->onRenderTriggered
import { onMounted, onUpdated, onUnmounted } from 'vue'
const MyComponent = {
setup() {
onMounted(() => {
console.log('mounted!')
})
onUpdated(() => {
console.log('updated!')
})
onUnmounted(() => {
console.log('unmounted!')
})
}
}
5.Provide / Inject
其实这个跟React.context
很类似,都是为了解决组件嵌套多层props传值的问题(避免数据多层传递的繁琐性),在父级把需要传递的数据通过Provide
包裹,在需要用到数据的子组件使用Inject
注入即可使用,在子级修改Inject
后的值父级的值是动态改变的。
app.vue 父级
<template>
<img alt="Vue logo" src="./assets/logo.png" />
<HelloWorld />
</template>
<script>
import HelloWorld from "./components/HelloWorld.vue";
import { provide, ref } from "vue";
export default {
components: {
HelloWorld,
},
setup() {
let msg = ref("Hello Vue 3.0 + Vite");
// 提供数据 provide inject
// vue3.0 一改组件
// 类似于 React.context(), myContext.provider myCcontent.consumer
provide("msg", msg);
return { msg };
},
};
</script>
helloworld.vue 子级中使用
setup() {
// 接收 父组件传来的数据
const msg = inject("msg");
return { msg }
},
6.自己搭建的小项目里暂时只使用到了:
- ref
- reactive
- provide inject
helloword.vue
<template>
<h1>{{ msg }}</h1>
<p>{{ obj.a }}</p>
<p>{{ obj.b }}</p>
<p>{{ obj.c && obj.c.c1 }}、{{ obj.c && obj.c.c2 }}</p>
<button @click="addCount">count is: {{ count }}</button>
</template>
<script>
import helloworld from "./helloworld";
export default {
setup() {
// helloworld() 为逻辑代码,可以单独拎出去,这也是composition Api的一大好处,逻辑代码可以高度解耦,可复用性更强!
return Object.assign({}, helloworld());
},
};
</script>
helloworld.ts
import { ref, reactive, inject } from "vue";
import { $log, $info, $test } from "../modules-index";
const helloworld = ():object => {
// 接收 父组件传来的数据
const msg = inject("msg");
// 1. ref
const count = ref(0);
const addCount = function () {
count.value++;
$log(count.value, "count:");
};
// 2. reactive
const obj = reactive({
a: "a",
b: "b",
c: {
c1: "c1",
c2: "c2",
},
});
obj.a = "我是a呀";
obj.b = "我是b呀";
obj.c.c1 = "我是c1呀";
// 注意:对reactive的数据解构会导致 基础数据类型 失去reactive
let { a, c } = obj;
a = "我是被解构的a";
c.c1 = "我是被解构的c1";
$log(obj); // {a: "我是a呀",b: "我是b呀",c: {c1: "我是被解构的c1",c2: "c2",},}
$log(a, 'a:'); // 我是被解构的a
$log(c, 'c:'); // {c1: "我是被解构的c1", c2: "c2"}
// 测试引用
$log($info, "测试引用:");
$test();
// 通过return把数据暴露给template
return { msg, count, addCount, obj }
};
export default helloworld;
六、代码
以上示例的代码放在了GitHub上: https://github.com/LLDLLY/vue3.0-init.git
更多推荐
所有评论(0)