Author:Gorit
Date:2021/4/24
Refer:网易云课堂
2021年发表博文: 17/30
学习文档
如果是第一次接触 Vue3,可以看这个 Vue3 初体验
项目结构介绍
Vue3 是向下兼容 Vue2 API 的,但是 Vue3 中提供了一种全新的 Composition API
setup() 作为 Vue3.0 的入口函数
reactive() 作声明式渲染,用来响应数据
ref() 显示响应式数据,配合 reactve()
直接返回数据
<template>
<div>直接返回 state【非响应式的数据】:{{count}}</div>
</template>
<script> // 如果是 Vue2 项目,想要用 Vue3 的语法,需要安装 @vue/composition-api // import { xxx } from '@vue/composition-api' import { reactive } from 'vue' export default { name: 'App', // Vue3.0 的入口函数,编写 Vue3 代码,beforeCreate之前进行触发, 需要 return setup() { const state = reactive({ count: 0 }); // 不具备数据响应式的效果,1s 后数据没有任何变化 setTimeout(()=> { state.count++; },1000) return state; } } </script>
通过对象的形式
<template>
<div>返回 state 对象 【响应式数据】{{state.count}}</div>
</template>
<script> import { reactive } from 'vue' export default { name: 'App', // Vue3.0 的入口函数,编写 Vue3 代码,beforeCreate之前进行触发, 需要 return setup() { // 具备数据响应式, 返回对象 const state = reactive({ count: 0 }); setTimeout(()=> { state.count++; },1000) return { state }; // 对返回的结果 解构,这样数据就可以只显示 {{ count }} 就可以了 // return { // count: state.count //} } } </script>
<template>
<img alt="Vue logo" src="./assets/logo.png">
<div>ref 实现响应式对象 {{ count }}</div>
</template>
<script> import { ref } from 'vue' export default { name: 'App', setup() { // 使用 ref() 实现响应式数据 const count = ref(0); // 这样 count 就实现了响应式的效果 setInterval(()=> { count.value++; },1000) return { count }; } } </script>
因此,我们既要响应式,又要展示数据,折中的方案是直接使用 ref
<template>
<img alt="Vue logo" src="./assets/logo.png">
<div class="my-app">
<!-- Vue3 无法直接拿到值 -->
<h3>{{counter}}</h3>
<button @click="increment(1)">increment</button>
<button @click="decrement(1)">decrement</button>
</div>
</template>
<script> import { ref } from 'vue' /** * Options API Vue2 Class * Composition API Vue3 Function */ export default { name: 'App', setup() { const counter = ref(1000) // console.log(counter.value) const increment = () => { counter.value += 1; } const decrement = () => { counter.value -= 1; } // 必须 return,外部才能拿到值 return { counter, increment,decrement } } } </script>
在上面的代码中,我们使用 ref() 和 reactive() 分别可以实现响应式的数据,我们是否可以两者一起使用呢?
<template>
<img alt="Vue logo" src="./assets/logo.png">
<div>ref() 和 reactive() 实现响应式对象 {{ count }}</div>
</template>
<script> // 如果是 Vue2 项目,想要用 Vue3 的语法,需要安装 @vue/composition-api // import { xxx } from '@vue/composition-api' import { ref, reactive } from 'vue' export default { name: 'App', setup() { // ---------------------------- ref 和 reactive 连用 const count = ref(0); const state = reactive({ count }) setInterval(()=> { state.count++; },1000) return { count }; } } </script>
<template>
<img alt="Vue logo" src="./assets/logo.png">
<div>实现响应式对象 {{ count }}</div>
</template>
<script> import { reactive, toRefs } from 'vue' export default { name: 'App', setup() { // ---------------------------- //使用 toRefs() 将 reactive 转换为 Ref const state = reactive({ count: 0 }); const { count } = toRefs(state); // toRefs() 作用:将普通类型数据,转换为 Ref 响应式数据 setInterval(()=> { state.count++; },1000) return { count }; } } </script>
<template>
<img alt="Vue logo" src="./assets/logo.png">
<div>实现响应式对象 {{ count }}</div>
</template>
<script> import { reactive, toRefs } from 'vue' export default { name: 'App', setup() { // ---------------------------- //使用 toRefs() 将 reactive 转换为 Ref const state = reactive({ count: 0 }); const count = toRef(state, 'count'); // toRef() 作用:将普通类型数据,转换为 Ref 响应式数据,指定单个数据转换 setInterval(()=> { state.count++; },1000) return { count }; // toRefs === {} } } </script>
ref 和 reactive 分别是两种响应式数据的变量风格,具体看个人情况使用
<template>
<img alt="Vue logo" src="./assets/logo.png">
<div>
{{count}} , {{double}}
</div>
</template>
<script> import { ref, computed } from 'vue' export default { name: 'App', setup() { // 使用计算属性 const count = ref(1) const double = computed(()=>count.value * 2) setTimeout(()=>{ count.value++ },1000) return { count,double } } } </script>
<template>
<img alt="Vue logo" src="./assets/logo.png">
<div>
{{count}} , {{double}}
</div>
</template>
<script> import { reactive, toRefs, computed } from 'vue' export default { name: 'App', setup() { const state = reactive({ count: 1, double: computed(()=>state.count * 2) }) setTimeout(()=>{ state.count++ },1000) return toRefs(state) } } </script>
<template>
<img alt="Vue logo" src="./assets/logo.png">
<div>
事件:{{count}}
</div>
<button @click="add">添加</button>
</template>
<script> import { ref, watch } from 'vue' export default { name: 'App', setup() { // =============== 事件 const count = ref(1) const add = () => { // 事件方法 count.value++; } // 配合侦听器 watch(count ,(count, prevCount) => { console.log(count, prevCount) }) return {count, add} } } </script>
文档
新的生命周期函数钩子要在 setup() 中使用
export default {
setup() {
// mounted
onMounted(() => {
console.log('Component is mounted!')
})
}
}
这里主要是回顾 组件化编程
拆分的方式同 Vue2,注册 + 引入
组件拆分的案例我们沿用上面的计数器来实现 (参考 3.1.4 小节的内容)
预览效果:
编码如下:
<template>
<div>
我是子组件 CounterView
{{counter}}
</div>
</template>
<script> export default { name: 'CounterView', // props: ['counter'] vue2 一般都是这么写的 // 下面的这种写法会更加规范 props: { counter: { type: Number, required: true, default: 500 } } } </script>
<template>
<div>
<img alt="Vue logo" src="./assets/logo.png" />
<!-- 属性绑定 -->
<counter-view :counter="counter"/>
<button @click="increament(1)">增加</button>
<button @click="increament(-1)">减少</button>
</div>
</template>
<script> import { ref } from "vue"; import CounterView from '@/components/CounterView.vue' export default { name: "App", components: { CounterView }, setup() { const counter = ref(1000); console.log(counter.value); // 定义函数 const increament = (num) => { counter.value += num; }; return { counter,increament }; }, }; </script>
<style> </style>
这里我们在上面的基础上,将 setup() 中定义的事件,拆分至另一个新的 vue 文件
首先我们需要补充一些前置概念:
this.$emit("事件名称", '值")
, 在 Vue3 中也会用到类似的,后面会有具体的演示在子组件完成事件注册
<template>
<div>
<button @click="increament(1)">增加</button>
<button @click="increament(-1)">减少</button>
</div>
</template>
<script> export default { name: 'CounterController', setup(props,ctx) { console.log(props, ctx) // 这里打印的就是我们刚刚上面看到的 const increament = (num) => { // ctx.emit 等价于 vue2 中 this.$emit("xxx",xxx)。 在 vue3 中 setup() 函数是没有 this 的概念的 ctx.emit("onIncreament",num) // 完成事件注册,将操作的逻辑交给父组件来完成 } return {increament} }, } </script>
在父组件完成事件调用
<template>
<div>
<img alt="Vue logo" src="./assets/logo.png" />
<!-- 属性绑定 -->
<counter-view :counter="counter"/>
<!-- <button @click="increament(1)">增加</button> <button @click="increament(-1)">减少</button> -->
<!-- 子组件事件注册完毕后,交给父组件进行触发, 处理的函数需要传 $event 就可以实现和上面一样的效果了 -->
<counter-controller @onIncreament="increament($event)" />
</div>
</template>
<script> import { ref } from "vue"; import CounterView from '@/components/CounterView.vue' import CounterController from '@/components/CounterController.vue' export default { name: "App", components: { CounterView, CounterController }, setup() { const counter = ref(1000); // 定义函数 const increament = (num) => { counter.value += num; }; return { counter,increament }; }, }; </script>
我们来回顾一下所学内容
版权说明 : 本文为转载文章, 版权归原作者所有 版权申明
原文链接 : https://codinggorit.blog.csdn.net/article/details/116096468
内容来源于网络,如有侵权,请联系作者删除!