这些是setup函数,生命周期,reactive函数,toRef函数,toRefs函数,ref函数的基本用法
还有vue3.0的计算属性,监听器,ref属性变化
除此之外还有一个案例来使用上面的新特性
demo目录如下
App.vue
<template>
<div class="countainer" style="display: flex">
<div style="flex: 1">
<div>{{ msg }}</div>
<button @click="func()">点我获取setup里的函数方法</button>
<div>
我是被解构的数据name: {{ name }}
<br />
我是被toRef的数据name2: {{ name2 }}
</div>
<button @click="func3()">点我改变被解构的和toRef的数据</button>
<div>
obj.name:{{ obj.name }}
<br />
obj.age:{{ obj.age }}
<br />
obj2.name:{{ obj2.name }}
<br />
obj2.age:{{ obj2.age }}
<br />
</div>
<button @click="func2()">点我改变数据</button>
<div>
我是用...的被toRefs的obj3数据name: {{ obj3Name }}
<br />
我是用...的被toRefs的obj3数据age: {{ obj3Age }}
<br />
我是用...的被toRefs的obj3数据active: {{ obj3Active }}
<br />
</div>
<button @click="func4()">点我改变toRefs的数据</button>
<div>
我是被ref定义的refName数据: {{ refName }}
<br />
我是被ref定义的refAge数据: {{ refAge }}
<br />
</div>
<button @click="func5()">点我修改被ref定义的数据</button>
<demo1 />
<demo2 />
<demo3 />
</div>
<div style="flex: 1">
<demo4 />
</div>
</div>
</template>
<script>
import { onBeforeMount, onMounted, reactive, toRef, toRefs, ref } from 'vue'
import demo1 from './components/demo1.vue'
import demo2 from './components/demo2.vue'
import demo3 from './components/demo3.vue'
import demo4 from './components/demo4.vue'
export default {
name: 'App',
components: {
demo1,
demo2,
demo3,
demo4,
},
/**
* 模板中需要的数据和函数,都从setuo里返回
*/
setup() {
console.log('setup', this); // 先执行,this是underfined,将来组合API的代码全部都在这里
let msg = '我是setup返回的数据'
const func = () => {
console.log('我是setup返回的函数方法', 'func');
console.log(msg, 'msg'); // 不需要this就可以访问
}
console.log('-------------------------');
console.log('下面是vue3.0和vue2.0的生命周期, 在setup里面的生命周期函数不用return出去');
onBeforeMount(() => {
console.log('onBeforeMount挂载DOM前', 'vue3.0', document.querySelector('.countainer'));
}),
onMounted(() => {
console.log('onMounted挂载DOM后', 'vue3.0', document.querySelector('.countainer'));
})
console.log('-------------------------');
// 普通数据无法被响应式修改
const obj = {
name: 'pasco152',
age: 24,
active: 'play'
}
// 但是reactive可以,有一点就是这里如果普通数据和reactive一起用,普通数据也会被改变
// 注意reactive是用来定义复杂数据类型的
const obj2 = reactive({
name: 'reactive的pasco152',
age: 'reactive的24',
active: 'reactive的play'
})
const func2 = () => {
obj.name = 'pasco152被改变了';
obj.age = '24被改变了';
obj2.name = 'reactive的pasco152被改变了'
obj2.age = 'reactive的24被改变了'
}
// 用解构的方式,此时name变为无法被响应式修改的数据,但是obj2仍旧是响应式数据
let { name } = obj2;
// 用toRef的方式
// toRef的使用场景是: 有一个响应式数据,但是模板只需要使用其中一项数据,并且这两个数据是相互关联的
const name2 = toRef(obj2, 'name'); // 在这里用const也没关系,因为toRef已经把它变为一个对象
const func3 = () => {
console.log('修改被解构数据的方法触发了');
name = '我是被解构的数据name'
name2.value = '我是被toRef的数据name2' // 注意这里要用value去修改
}
// 用toRefs的方式,可以用...obj3的方式直接在template上面使用参数
// 同样如果使用解构的方式去修改的话,数据就不再是响应式的了,这里不做赘述
const obj3 = reactive({
obj3Name: 'obj3的reactive的pasco152',
obj3Age: 'obj3的reactive的24',
obj3Active: 'obj3的reactive的play'
})
// toRefs的使用场景: 剥离响应式对象,想使用响应式对象中的多个或者所有属性作为响应式数据
const obj3Ref = toRefs(obj3);
const func4 = () => {
obj3.obj3Name = '我是被toRefs的数据obj3Name', // 这里为啥不用obj3Ref.obj3Name.value呢,这是因为obj3和obj3Ref是互通的
obj3.obj3Age = '我是被toRefs的数据obj3Age',
obj3.obj3Active = '我是被toRefs的数据obj3Active'
}
// 接下来使用ref来定义简单数据类型
// 注意ref也可以定义复杂数据类型,reactive只能用来定义复杂数据类型
// ref的使用场景: 当你明确知道这个数据是复杂数据类型就用reactive,不确定就使用ref
const refName = ref('我是ref定义的name')
const refAge = ref('我是ref定义的age')
const func5 = () => {
refName.value = '我是ref定义的name被修改了' // 在获取、修改值的时候需要使用.value
refAge.value = '我是ref定义的age被修改了' // 但是在tamplate上使用的时候不需要使用.value
}
return { msg, obj, obj2, name, name2, ...obj3Ref, refName, refAge, func, func2, func3, func4, func5 }; // 这里返回的是一个对象
},
/**
* vue3.0也支持vue2.0的生命周期,他们可以和谐的在一起使用
*/
beforeCreate() { // vue2.0的生命周期
console.log('beforeCreate', 'vue2.0', document.querySelector('.countainer')); // 后执行
},
}
</script>
demo1.vue
<template>
<div class="demo1">
<div>---------------------子组件demo1------------------------</div>
鼠标坐标<br>
我是被toRefs定义的数据X: {{ x }}<br>
我是被toRefs定义的数据Y: {{ y }}
</div>
</template>
<script>
import { onMounted, onUnmounted, reactive, toRefs } from 'vue'
export default {
name: 'demo1',
setup() {
// 鼠标坐标
const mouse = reactive({
x: 0,
y: 0
})
const move = (e) => {
mouse.x = e.pageX
mouse.y = e.pageY
}
onMounted(() => {
document.addEventListener('mousemove', move)
}),
onUnmounted(() => {
document.removeEventListener('mousemove', move)
})
return { ...toRefs(mouse) }
}
}
</script>
demo2.vue
<template>
<div class="demo2">
<div>-------------------子组件demo2--------------------------</div>
数字: {{ count }}
<button @click="addFunc()">点我+1</button>
<button @click="reduceFunc()">点我-1</button>
<button @click="zeroFunc()">点我归零</button>
</div>
</template>
<script>
import { onMounted, reactive, ref } from 'vue'
export default {
name: 'demo2',
setup() {
const count = ref(0);
const addFunc = () => {
count.value++;
}
const reduceFunc = () => {
count.value--;
}
const zeroFunc = () => {
count.value = 0;
}
return { count, addFunc, reduceFunc, zeroFunc }
}
}
</script>
demo3.vue
<template>
<div class="demo3">
<div>-----------计算属性------------</div>
<div>
没被修改前name: {{ name }}<br>
修改后name: {{ newName }}
</div>
<div>------------计算属性高级运用,get set函数</div>
<div>
没被修改前name2: {{ name2 }}<br>
修改后name2: {{ newName2 }}<br>
<input type="text" v-model="newName2">
</div>
</div>
</template>
<script>
import { ref, computed } from 'vue'
export default {
name: 'demo3',
setup() {
let name = ref('一号pasco152');
// 依赖现有的响应式数据,经过一定逻辑处理获得的一个新数据
// 里面做过缓存
// 计算属性不能更改
let newName = computed(()=> {
return name.value + '被computed改变了'
})
let name2 = ref('二号pasco152')
let newName2 = computed( { // 注意这里computed的值也被改变了
get() {
// 这里获取计算属性的值
return name2.value + '也被computed改变了'
},
set(value) {
// value就是通过computed改变的值,也就是get返回的值,并不是name2本身的值
name2.value = value + '被set改变了';
}
})
return { name, newName, name2, newName2 }
}
}
</script>
demo4.vue
<template>
<div class="demo4">
<div>---------watch侦听器--------------</div>
<div>
count: {{ count }}
<button @click="addFunc()">点我count+1</button>
</div>
<div>
obj1.name: {{ obj1.name }}<br>
obj1.age: {{ obj1.age }}<br>
<button @click="updateObj1">点我修改obj1</button>
</div>
</div>
</template>
<script>
import { reactive, ref, watch } from 'vue'
export default {
name: 'demo4',
setup() {
let count = ref(0);
let obj1 = reactive({
name: 'pasco152',
age: 24
})
let addFunc = () => {
count.value++;
}
let updateObj1 = () => {
obj1.name = 'pasco152被修改了'
}
// 接下来监听count
watch(count,(oldVal, newVal) => {
console.log(oldVal); // 需要监听的目标
console.log(newVal); // 改变后的值
})
// 接下来监听obj1
watch(obj1, (oldVal, newVal) => {
// 这里的新旧数据都是新数据,原因是因为响应式数据的关系
console.log(oldVal);
console.log(newVal);
})
// 再接下来监听多个数据
watch([count, obj1], () => {
console.log('监听多个数据被触发了');
})
// 再再接下来监听复杂数据中的某一项
watch(()=>obj1.name, ()=>{ // 监听某一项需要用函数返回的形式
console.log('监听obj1中的name被触发了');
})
return { count, obj1, addFunc, updateObj1 }
}
}
</script>
demo5.vue
<template>
<div class="demo5">
<div>-----------ref属性---------</div>
<!-- 通过ref绑定元素 -->
<!-- 通过this.$refs.box获取元素 -->
<div ref="box">我是ref定义的box</div>
<!-- 通过this.$refs.li获取所有遍历的元素 -->
<ul>
<li v-for="i in 5" :key="i" ref="li">{{ i }}</li>
</ul>
<!-- 单个 -->
<div ref="dom">使用setup绑定的ref</div>
<!-- 多个 -->
<ul>
<li v-for="i in 5" :key="i" :ref="setDom">{{ i }}</li>
</ul>
<button @click="count++">{{ count }}</button>
<button @click="logList">打印domList的值</button>
</div>
</template>
<script>
import { onBeforeUpdate, ref, onMounted } from 'vue'
export default {
name: 'demo5',
setup() {
// 定义一个空的dom,return出去,在想绑定的元素上用ref绑定即可
const dom = ref(null);
onMounted(() => {
console.log(dom.value);
console.log(domList);
})
// 定义v-for遍历的元素
let domList = [];
const setDom = (el) => {
// 该函数会被打印5次
// 同时会传入值
domList.push(el);
}
// 通过setDom设置的值虽然是可以的,但是会有一个问题,就是在每次onMounted的时候都会push进去
// 所以需要在onBeforeUpdate里面还原domList
onBeforeUpdate(() => {
domList = [];
})
const count = ref(0);
const logList = () => {
console.log(domList);
}
return { dom, setDom, count, logList }
}
}
</script>
中间换了个主题........这不重要,后续会有更新其他vue3.0的新特性以及完整的项目建立流程