| 阶段 | 技术栈 |
| ----------------------- | -------------------------------------------- |
| 阶段一:vue3-todoList | 初识compositionAPI |
| 阶段二:vue3-仿知乎日报 | 对compositionAPI、vite、typescript进一步了解 |
B站免费vue3教学视频:https://www.bilibili.com/video/BV13V411S79q/
### vue3.0入门到精通
#### vue3.0 安装
前安装过vue的2.0版本,你需要把2.0相关的删除
```
npm uni -g vue-cli
```
安装vue/cli脚架
```
npm i -g @vue/cli
```
检查版本号,目前安装vuecli 4.5.4
```
vue -V
```
创建:在命令窗口输入指令
选择default vue 3
```
vue create 项目名称
```
#### vue composition API
vue3.0 侧重于解决代码组织与逻辑复用问题
目前,我们使用的是“options”API 构建组件。 为了将逻辑添加到Vue组件中,我们填充(options)属性,如data、methods、computed等。 这种方法最大的缺点是,它本身不是一个工作的JavaScript代码。 您需要确切地知道模板中可以访问哪些属性以及this关键字的行为。在底层,Vue编译器需要将此属性转换为工作代码。正因为如此,我们无法从自动建议或类型检查中获益。
Composition API希望将通过当前组件属性、可用的机制公开为JavaScript函数来解决这个问题。 Vue核心团队将组件Composition API描述为“一套附加的、基于函数的api,允许灵活地组合组件逻辑”。 使用Composition API编写的代码更易读,并且场景不复杂,这使得阅读和学习变得更容易。
让我们看到一个非常简单的组件示例,它使用新的组件Composition API来理解它是如何工作的。
```
<template>
<div id="app">
<img alt="Vue logo" src="./assets/logo.png">
<div>{{msg}}年龄为{{age}}</div>
<button @click="add"> + </button>
</div>
</template>
<script>
export default {
name: 'App',
data() {
return {
msg:'王大合',
age:18
}
},
methods:{
add() {
this.age += 1
}
}
}
</script>
```
##### setup
vue3.0将组件的逻辑都写在了函数内部,setup()会取代vue2.x的data()函数,返回一个对象,暴露给模板,而且只在初始化的时候调用一次,因为值可以被跟踪,所以我们通过vue3来改变编程习惯
首先引入ref
使用数据需要return
```
import {ref} from 'vue'
setup() {
const msg = ref('王大合')
const age = ref(18)
function add() {
age.value +=1
}
return {msg,age,add}
}
```
**computed**
```
<template>
<div id="app">
<img alt="Vue logo" src="./assets/logo.png">
<div>{{msg}}的年龄为{{age}}</div>
<div>{{double}}</div>
<button @click="add">+</button>
</div>
</template>
<script>
import {computed, ref} from 'vue'
export default {
name: 'App',
setup() {
const msg = ref('王大合')
const age = ref(18)
const double = computed(() =>{
return age.value * 2
})
function add() {
age.value += 1
}
return {msg,age,add,double}
}
}
</script>
```
##### reactive
在 `setup` 函数里面, 我们适应了 Vue3.0 的第一个新接口 `reactive` 它主要是处理你的对象让它经过 `Proxy` 的加工变为一个响应式的对象,
##### toRefs
用于将响应式对象变成普通对象
```
<template>
<div id="app">
<img alt="Vue logo" src="./assets/logo.png">
<div>{{msg}}的年龄为{{age}}</div>
<div>{{double}}</div>
<button @click="add">+</button>
</div>
</template>
<script>
import {computed, reactive,toRefs} from 'vue'
export default {
name: 'App',
setup() {
const state = reactive({
msg:'王大合',
age:18,
double : computed(() =>{
return state.age * 2
})
})
function add() {
state.age += 1
}
return {...toRefs(state),add}
}
}
</script>
```
##### props 和 context
在 `Vue2.0` 中我们可以使用 `props` 属性值完成父子通信,在这里我们需要定义 `props` 属性去定义接受值的类型,然后我们可以利用 `setup` 的第一个参数获取 `props` 使用。
```
export default {
name: 'App',
components:{
Content
},
setup() {
const state = reactive({
msg:'王大合',
age:18,
double : computed(() =>{
return state.age * 2
})
})
function add() {
state.age += 1
}
return {...toRefs(state),add}
}
}
```
我们在 `App.vue` 里面就可以使用该头部组件,有了上面的 `props` 我们可以根据传进来的值,让这个头部组件呈现不同的状态。
```
<template>
<div id="app">
<img alt="Vue logo" src="./assets/logo.png">
<div>{{msg}}的年龄为{{age}}</div>
<div>{{double}}</div>
<Content :msg='msg' />
<button @click="add">+</button>
</div>
</template>
```
这里我新建一个新的组件content,在app.vue中引入
```
<!-- -->
<template>
<div>{{data}}</div>
</template>
<script>
import {ref} from 'vue'
export default {
name:'content',
props:{
msg:String
},
setup(props) {
const data = ref(props.msg)
return {data}
}
}
</script>
```
`setup` 函数的第二个参数是一个上下文对象,这个上下文对象中包含了一些有用的属性,这些属性在 `Vue2.0` 中需要通过 `this` 才能访问到,在 `vue3.0` 中,访问他们变成以下形式:
```
setup(props, ctx) {
console.log(ctx) // 在 setup() 函数中无法访问到 this
console.log(this) // undefined
}
```
具体能访问到以下有用的属性:
```
- slot
- attrs
- emit
```
父组件
```
<template>
<div id="app">
<img alt="Vue logo" src="./assets/logo.png">
<div>{{msg}}的年龄为{{age}}</div>
<div>{{double}}</div>
<Content :msg='msg' @change='showName' />
<button @click="add">+</button>
</div>
</template>
<script>
import {computed, reactive,toRefs} from 'vue'
import Content from './components/content.vue'
export default {
name: 'App',
components:{
Content
},
setup() {
const state = reactive({
msg:'王大合',
age:18,
double : computed(() =>{
return state.age * 2
})
})
function showName(params) {
alert(params)
}
function add() {
state.age += 1
}
return {...toRefs(state),add,showName}
}
}
</script>
```
子组件
```
<!-- -->
<template>
<div>{{data}}</div>
<button @click="changeName">打个招呼!</button>
</template>
<script>
import {ref} from 'vue'
export default {
name:'content',
props:{
msg:String
},
setup(props,context) {
const data = ref(props.msg)
function changeName() {
context.emit('change','Hello,王大合!')
}
return {data,changeName}
}
}
</script>
```
##### watch
监听ref
不指定数据源
```
const a = ref(18)
watch(()=>{
console.log(a.value)
})
```
指定数据源
```
const a = ref(18)
watch(a,()=> {
console.log(a.value)
})
```
监听reactive
```
const state = reactive({
msg:'王大合',
age:18,
double : computed(() =>{
return state.age * 2
})
})
```
不指定数据源
```
watch(()=>{
console.log(state.age)
})
```
指定数据源
```
watch(()=>state.age,()=>{
console.log(state.age)
})
```
回调函数参数以及watche clean,使用clean时候是处理重复性的watch监听事件
```
watch(() => state.age,(newVal,oldVal,clean)=> {
console.log(state.msg + "去年年纪:"+oldVal +"今年年纪:" + newVal)
clean(
()=>{
console.log('clean')
}
)
})
```
#### vue3.X+vite+typescript
##### 放弃webpack,使用vite安装vue3.0
这个是尤大开发的新工具,目的是以后替代webpack,原理是利用浏览器现在已经支持es6的import了,遇到import会发送一个http请求去加载文件,vi