# Vue3.0beta尝鲜
从去年开始Vue3.0一直在预热,到现在Vue3.0beta已经发布有一短时间了,网上也说了好多Vue3的一些新的特征。尤大大也说:Vue从底层开始重构,可以说重新出发。
前一段时间也出了中文版的composition-api,如果多想了解的,可以去看下。
废话不多说,赶紧动手玩下吧。
怎么使用Vue3.0beta
- Vue/cli版本要4.0以上,现在基本上都是4.0以上了,如果还没有升级到4.0以上的,首先要升级下
关于旧版本
Vue CLI 的包名称由 vue-cli 改成了 @vue/cli。 如果你已经全局安装了旧版本的 vue-cli (1.x 或 2.x),你需要先通过 npm uninstall vue-cli -g 或 yarn global remove vue-cli 卸载它。安装:
npm install -g @vue/cli # OR yarn global add @vue/cli
1
2
3你还可以用这个命令来检查其版本是否正确:
vue --version
1- 创建新的项目并安装vue-next
vue create vue3-demo
1步骤我就不多说了,详情
创建好项目,我们安装vue-next
vue add vue-next
1安装成功后我们可以看下package.json,如果Vue的版本出现beta,那么恭喜呢,你成功了,接下来你就可以愉快的玩Vue3了。
"dependencies": { "core-js": "^3.6.5", "register-service-worker": "^1.7.1", "vue": "^3.0.0-beta.15", "vue-router": "^4.0.0-alpha.14", "vuex": "^4.0.0-alpha.4" },
1
2
3
4
5
6
7安装的另一种方式vite (推荐使用)
据尤大大说:vite只是一个demo,为了Vue3.0开发的工具,刚开始就是玩玩,谁知道一玩就控制不住了,所有就有了vite。
Vite是一个自以为是的Web开发人员构建工具,可在开发期间通过本机ES模块导入为您的代码提供服务,并将其与Rollup捆绑在一起进行生产。
- 闪电般快速的冷服务器启动
- 即时热模块更换(HMR)
- 真正的按需编译
在Beta中,可能很快就会发布1.0。
如果你使用vite,你会发现编译的速度很快,可以说秒开。为什么这么快呢?vite的渲染方式和webpack渲染方式不同,vite可以根据现代的浏览器module直接渲染.vue文件,而webpage需要先编译在渲染,时间可想而知,那个很快!
先看个图:
连webpage的大佬都要哭了,开玩笑了,不过vite确实很快。
我们对比下vite和webpage的渲染方式
vite渲染方式:
webpage渲染方式:
vite是一款真正的开箱即用的工具,下面跟着我体验一下吧。
- 创建项目
# NPM
$ npm init vite-app <project-name>
$ cd <project-name>
$ npm install
$ npm run dev
2
3
4
5
# YARN
$ yarn create vite-app <project-name>
$ cd <project-name>
$ yarn
$ yarn dev
2
3
4
5
创建的速度也是很快3.79s
首先看下Vue3的语法:也可以去看下Vue3.0手册
export default {
name: 'Home',
setup() {
// 定义一个ref响应式对象
const count = ref(0)
// 如果要定义多个可以使用reactive
const state = reactive({
size: 36,
color: 'red'
})
// 定义一个方法
const increment = () => {
count.value++
}
return {
count,
increment,
...toRefs(state)
}
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
可以看出Vue3语法有个很大的改变,Vue3更多的放在逻辑层,可以说按需加载我们要渲染和要用的的函数,这样我们的浏览器的开销就小了许多,渲染的速度就快了许多。Vue3用Proxy监听数据的变化。
对比Vue2使用Object.defineProperty监听对象改变,所有的生命周期都暴露给this,这样的开销,不论我们改变那个变量或者函数,都会触发对象的改变。这样我们在data中定义的我们我们不用的变量,也是多余的开销,从而影响我们的渲染速度。
实战
- data
#Vue2 export default { data() { return { message: 'vue2' } }, }
1
2
3
4
5
6
7
8setup() 函数返回的 property 将会被暴露给 this
Vue3如果要定义响应对象,要用ref或者reactive,如果不用你定义的变量不是响应式的,这个还是要注意点。
然后通过return返回我们要用的函数和要渲染的变量,如果不返回我们在HTML中是渲染不到的,这个就是我们说的按需渲染的。
如果想了解的更多,可以看下这篇深入理解 Vue3 Reactivity API,这里就不多做介绍,这里我们就教大家怎么使用。import { ref, reactive, toRefs } from 'vue' export default { setup() { // msg 这样定义不是响应式的 const msg = 'Vue3' // 定义一个ref响应式对象 const count = ref(0) // 如果要定义多个可以使用reactive const state = reactive({ size: 36, color: 'red' } // 如果我们要获取count的值 要用.value,在html渲染中可以省略.value {{count}} console.log(count.value) return { count, ...toRefs(state) } } }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21- 生命周期
与 2.x 版本生命周期相对应的组合式 API
- beforeCreate → 使用 setup()
- created → 使用 setup()
- beforeMount → onBeforeMount
- mounted → onMounted
- beforeUpdate → onBeforeUpdate
- updated → onUpdated
- beforeDestroy → onBeforeUnmount
- destroyed → onUnmounted
- errorCaptured → onErrorCaptured
import { reactive, toRefs, computed, onMounted, onBeforeMount, onBeforeUpdate, onBeforeUnmount, onUpdated, onUnmounted, onErrorCaptured } from 'vue' export default { setup() { // 定义一个ref响应式对象 const count = ref(0) // beforeMount onBeforeMount(() => { console.log("onBeforeMount"); }) // mounted onMounted(() => { console.log("onMounted"); }) // beforeUpdate onBeforeUpdate(() => { console.log("onBeforeUpdate"); }) // updated onUpdated(() => { console.log("onUpdated"); }) // beforeDestroy onBeforeUnmount(() => { console.log("onBeforeUnmount"); }) // destory onUnmounted(() => { console.log("onUnmounted"); }) // errorCaptured onErrorCaptured(() => { console.log("onErrorCaptured"); }) return { count, } } }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41- mehods
# Vue2 export default { ... methods:{ increment(){ this.count++; } } }
1
2
3
4
5
6
7
8
9
10#Vue3 export default { setup() { // 定义一个方法 const increment = () => { count.value++ } // 记得要return return { increment} } }
1
2
3
4
5
6
7
8
9
10
11
12
13- watch
watchEffect 传入一个函数并立即执行,如果函数里面使用了上面定义好的响应式对象,当对象发生变化时,会再次触发这个函数
import { reactive, toRefs, watch } from 'vue' export default { setup() { const loadPge = (path) => { router.push({ path }) } const state = reactive({ count: 1 }) const add = () => { state.count++ } watchEffect(() => { state.number = state.count + '----' console.log(`effect 触发了!${state.count}`) }) // 定义监听器 const watcher = watch(state, (val, oldVal) => { console.log('watch', val, oldVal) }) return { ...toRefs(state), add } } }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26- 组件
组件通信
和vue2的通信大同小异,新建ComDemo.vue,setup函数接受一个 props 和 context 上下文
context: { attrs, emit, slots}children子组件
// ComDemo.vue <template> <div>{{name}}</div> </template> <script> import { inject } from 'vue' export default { props: { name: { type: String, default: '' } }, setup(props, context) { console.log(props, context) const str = '子组件的属性str' const talk = () => { console.log('我被父组件触发了') } context.emit('talk', '我是子组件 我触发你了') // 接收provide值 const injectmsg = inject('injectmsg') console.log('injectmsg : ', injectmsg) return { str, talk } } } </script>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25parent父组件
// ParentDemo.vue <template> <div> <ComDemo :name="name" @talk="talk" ref="comdemo" /> </div> </template> <script> import ComDemo from '../components/ComDemo.vue' import { provide, reactive, toRefs, ref, onMounted } from 'vue' export default { components: { ComDemo }, setup() { const state = reactive({ name: '我是父组件传值' }) // 多级传值 provide('injectmsg', 'provide talk') const talk = () => { console.log('父组件') } const comdemo = ref(null) onMounted(() => { // 得到子组件的值 console.log(comdemo.value.str) // 触发子组件事件 // comdemo.value.talk() }) return { ...toRefs(state), talk, comdemo } } } </script>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37- router
比之前的的封装了一个函数useRouter,返回之前和Vue2一样的路由方法。
<script> import { useRouter } from 'vue-router' export default { setup() { console.log(useRouter()) const router = useRouter() const loadPge = (path) => { router.push({ path }) } return { loadPge } } } </script>
1
2
3
4
5
6
7
8
9
10
11
12
13- vuex
vuex一样的封装了一个函数useStore,通过computed返回vuex的state和getter。
// 方法1: import { computed } from 'vue' import { useStore } from 'vuex' export default { setup () { const store = useStore() return { count: computed(() => store.state.count), // state evenOrOdd: computed(() => store.getters.evenOrOdd), //getters increment: () => store.commit('increment'), // mutations decrement: () => store.dispatch('decrement'), // actions } } }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15// 方法2: import { mapState, mapActions } from 'vuex' export default { computed: mapState({ count: state => state.count }), methods: { ...mapMutations({ decret: 'decret' }), ...mapActions({ decrement: 'decrement' }) }, created () { this.$store.dispatch('products/getAllProducts') } }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
其他的一直在总结中,不足之处,还请大家不吝指教!!!