//创建一个vue应用(理解成之前的根实例)
// 1.导入createApp函数从vue中
// 2.创建一个根目录 App.vue 导入至main
// 3.使用createApp创建应用实例
// 4.应用实例挂载到#app容器中
创建vite vue2脚手架
npm init vite-app 项目名字
export default {
name: 'App',
//1.组合式api的起点,将来的组合api的代码,基本上再这里
//2.setup再beforecreate之前执行,组件创建前就执行
// 3.setup中不能使用this=>undefined
setup () {
}
}
setup中定义的方法和数据必须return 才能使用。setup可以形参
vue的生命周钩子
setup 创建实例前
onBeforeMount 挂载dom前
onMounted 挂载dom后
onBeforeUpdate 更新组件前
onReforeUnmount 卸载销毁前
setup里面能够同时存在相同的生命周期函数
按顺序执行
定义响应式数据reactive ref
reactive是一个函数,它可以定义一个复杂的数据类型,成为响应式数据,一般用于定义对象
<template>
<div class="container">
<div>{{obj.name}}</div>
<div>{{obj.age}}</div>
<button @click="objUpdate">修改数据</button>
</div>
</template>
<script>
import { reactive } from 'vue'
export default {
setup () {
const obj = reactive({
name: 'ls',
age: 18
})
const objUpdate = () => {
obj.name = 'zs'
}
return {
obj,
objUpdate
}
}
}
</script>
<style>
</style>
toRef 对象中某个值要响应式
<template>
<div class="container">
{{name}}
<button @click="xiugai">修改</button>
</div>
</template>
<script>
import { reactive, toRef } from 'vue'
export default {
setup () {
//1.响应式数据对象
const obj = reactive({
name: 'ls',
age: 10
})
//2.模板中只需要name数据
// const { name } = obj
const name = toRef(obj, 'name')
// 修改方法
//修改的不是响应式
const xiugai = () => {
console.log('updateName');
//toRef转换响应式数据包装成对象,value存放值的位置
name.value = 'zs'
}
return {
name,
xiugai
}
}
}
</script>
<style>
</style>
torefs 转换响应式对象的所有数据
<template>
<div class="container">
<div class="x">{{x}}</div>
<div class="y">{{y}}</div>
<button @click="add">+</button>
<div class="num">{{count}}</div>
</div>
</template>
<script>
import { onMounted, onUnmounted, reactive, toRefs, ref } from 'vue'
const useMouse = () => {
//坐标
const mouse = reactive({
x: 0,
y: 0
})
const move = (e) => {
mouse.x = e.pageX
mouse.y = e.pageY
}
//1.2等dom渲染完毕,去监听事件
onMounted(() => {
document.addEventListener('mousemove', move)
})
//1.3组件销毁删除事件
onUnmounted(() => {
document.removeEventListener('mousemove', move)
})
return mouse
}
export default {
setup () {
// //坐标
// const mouse = reactive({
// x: 0,
// y: 0
// })
// const move = (e) => {
// mouse.x = e.pageX
// mouse.y = e.pageY
// }
// //1.2等dom渲染完毕,去监听事件
// onMounted(() => {
// document.addEventListener('mousemove', move)
// })
// //1.3组件销毁删除事件
// onUnmounted(() => {
// document.removeEventListener('mousemove', move)
// })
//数字的累加
const mouse = useMouse()
const count = ref(0)
const add = () => {
count.value++
}
return {
...toRefs(mouse),
add,
count
}
}
}
</script>
<style>
</style>
计算属性computed
<template>
<div class="container">
<div>今年:{{age}}</div>
<div>后年:{{newAge}}</div>
</div>
</template>
<script>
import { computed, ref } from 'vue'
export default {
setup () {
// 1.计算属性:当你需要依赖现在的响应式数据,根据一定逻辑得到一个新的数据
const age = ref(18)
//得到后面的年龄
const newAge = computed(() => {
return age.value + 2
})
return {
age, newAge
}
}
}
</script>
<style>
</style>
计算属性不能修改
计算属性高级用法
<template>
<div class="container">
<div>今年:{{age}}</div>
<div>后年:{{newAge}}</div>
<input type="text"
v-model="newAge" />
</div>
</template>
<script>
import { computed, ref } from 'vue'
export default {
setup () {
// 1.计算属性:当你需要依赖现在的响应式数据,根据一定逻辑得到一个新的数据
const age = ref(18)
//得到后面的年龄
const newAge = computed({
//get函数,获取计算属性的值
get () {
return age.value + 2
},
//set函数,当你给计算属性设置值的时候触发
set (value) {
age.value = value - 2
}
// return Number(age.value) + 2
//
})
return {
age, newAge
}
}
}
</script>
<style>
</style>
计算属性也支持双向绑定
总结:计算属性两种用法
给computed传入函数,返回值计算计算属性的值
给computed传入对象,get获取计算属性的值,set监听计算属性改变
watch
重点:监听对象中的某一个属性需要写成函数类型
<template>
<div class="container">
<p>count的值:{{count}}</p>
<button @click="add">修改数据</button>
<div>
<p>{{obj.name}}</p>
<p>{{obj.age}}</p>
<button @click="updateName">改名字</button>
</div>
<div>
<div> {{obj.brand[0].name}}</div>
<button @click="updateBrandName">改品牌的名字</button>
</div>
</div>
</template>
<script>
import { reactive, ref, watch } from 'vue'
export default {
setup () {
const count = ref(0)
const add = () => {
count.value++
}
const obj = reactive({
name: "ls",
age: 18,
brand: [
{
name: '劳斯莱斯',
}
]
})
//当你需要监听数据的变化就可以使用watch
// 1.监听一个ref数据
//1.1 第一个参数监听改变后的数,第二个参数改变后触发的数
watch(count, (newval, oldval) => {
console.log(newval, oldval);
})
//2.监听一个reactive数据
watch(obj, () => {
console.log('数据变化了');
}, {
//深度监听
deep: true,
//默认监听
immediate: true
})
// 3监听多个数据
// watch([count, obj], () => {
// console.log('监听多个数据的改变');
// })
const updateName = () => {
obj.name = 'zs0111'
}
const updateBrandName = () => {
obj.brand[0].name = 'zs0111'
}
//4 只监听obj中name的变化
// watch(() => obj.name, () => {
// console.log('监听obj.age的改变了');
// })
//5
return { count, add, updateName, obj, updateBrandName }
}
}
</script>
<style>
</style>
总结:监听某个属性用到函数返回值,deep和immediate
ref
目标:掌握使用ref属性绑定dom或组件
获取dom或者组件实例可以使用ref属性,写法和vue2.0需要区分开
获取单个dom或者组件
<template>
<div class="container">
<!-- vue2.0获取div元素 -->
<!-- 1.通过ref属性绑定改元素 -->
<!-- 2.通过this.$refs.box获取元素 -->
<div ref="box">box盒子</div>
<!-- vue2.0获取v-for遍历的多个元素 -->
<!-- 1.通过ref属性绑定被遍历元素 -->
<!-- 2.通过this.$refs.li获取所有遍历元素 -->
<ul>
<li v-for="i in 4"
:key="i"
:ref="setDom">
第 {{i}}LI
</li>
</ul>
</div>
</template>
<script>
import { onMounted, ref } from 'vue'
export default {
setup () {
//获取单个元素
//1.先定义一个空的响应式ref定义的
//setup中返回该元素,你想获取那个dom元素。再该元素上使用ref属性绑定该数据即可
const box = ref(null)
onMounted(() => {
console.log(box.value);
})
//2.获取v-for遍历的元素
//2.1 定义一个空数组,接收所有的Li
// 2.2 定义一个函数, 往空数组pushDOM
const domList = []
const setDom = (el) => {
console.log('setDom', el);
domList.push(el)
}
console.log(domList, '获取li的dom');
return {
box,
setDom
}
}
}
</script>
<style>
</style>
总结:
- 单个元素:先声明ref响应式数据,返回给模板使用,通过ref绑定数据
- 遍历的元素:先定义一个空数组,定一个函数获取元素,返回给模板使用,通过ref绑定这个函数
数据传递
<template>
<div class="container">
<h1>子组件</h1>
<p>{{money}}</p>
</div>
</template>
<script>
export default {
name: 'Son',
props: {
money: {
type: Number,
default: 0
}
},
setup (props) {
console.log(props.money);
}
}
</script>
<style>
</style>
总结:props 传递数据 setup中可以获取到数据
自定义事件传递数据
son.vue
<template>
<div class="container">
<h1>子组件</h1>
<p>{{money}}</p>
<button @click="changeMoney">得到钱</button>
</div>
</template>
<script>
export default {
name: 'Son',
props: {
money: {
type: Number,
default: 0
}
},
//props 父组件的数据传递给子组件
//emit 触发自定义事件的函数
setup (props, context) {
console.log(props.money);
const changeMoney = () => {
//消费50元
//通知父组件,money需要变成50
context.emit('change-money', 50)
}
return {
changeMoney
}
}
}
</script>
<style>
</style>
父组件
<template>
<div class="container">
<h1>父组件</h1>
<hr>
{{money}}
<Son :money="money"
@change-money="updateMoney"></Son>
</div>
</template>
<script>
import { ref } from 'vue'
import Son from './Son.vue'
export default {
name: 'App',
components: {
Son
},
//父组件的数据传递给子组件
setup () {
const money = ref(100)
const updateMoney = (newMoney) => {
console.log(newMoney);
}
return {
money,
updateMoney
}
}
}
</script>
<style>
</style>
双向绑定.sync
出去v-model实现双向绑定的另一种方式
<Son :moeny="money" @update:money="fn"/>
<Son :money.sync="money"/>
双向绑定