1、Vue3.0环境集成
1.使用vue-cli创建
## 1.查看@vue/cli的版本,确保@vue/cli版本在4.5.0以上
vue --version
## 2.安装或者升级你的@vue-cli
## 3.创建
vue create vueproject
# 4.启动
cd vueproject
npm run serve
2.使用vite创建
vite:新一代的前端工具
优点:
-
开发环境中,无需打包,可快速的冷启动
-
轻量快速的热加载
//1.创建 npm init vite hello-vue3 -- --template vue npm init vite 项目名 可以自己选择集成环境
2、常用的Composition API(组合API)
官方文档:https://cn.vuejs.org/api/
1、setup函数
-
总结:Vue3.0中一个新的配置向,值为一个函数,组件中所有用到的:数据、方法等等,均要配置在setup中。
-
setup函数的两种返回值:
-
若返回一个对象,则对象中的数据、方法、在模板中均可直接使用(重点)
<script setup> var name = "marry"; var obj = { age: 18, gender: "女", class: '二' } </script> <template> <div> <span>{ { obj.class}}班的{ { name}}是一名{ { obj.gender}}生,今年{ { obj.age}}岁了~~~</span> </div> </template> //二班的marry是一名女生,今年18岁了~~~
-
若返回一个渲染函数,则可以自定义渲染内容(了解)
//页面中会显示一个h1标签,标签的内容是"vue3返回渲染函数" <script> import { h} from 'vue' export default { setup() { // 返回一个渲染函数 // h相当于document.CreateElement() return ()=>{ return h("h1","vue3返回渲染函数")} } } </script>
-
-
注意:
- 虽然它可以使用Vue2.0的配置,但是不要2.0 \3.0一起混用;
- Vue2.x配置(data,methods,computed…)中可以访问setup中的属性,方法,但在setup中不能访问到Vue2.x配置(data,methods,computed…)
- 如有重名,setup优先
- setup不能是一个async函数,因为返回值不再是return的对象,而是Promise,模板看不到return对象中的属性
- setup在组件加载期间,只会运行一次。
- 语法糖:在script里面加入 setup , 这个属性会让打包工具打包时,直接帮我们把setup函数内部声明的变量、函数return 然后组件就可以直接使用
- setup函数是处于 生命周期函数 beforeCreate 和 Created 两个钩子函数之前的函数
- 执行 setup 时,组件实例尚未被创建(在 setup() 内部,this 不会是该活跃实例的引用,即不指向vue实例,Vue 为了避免我们错误的使用,直接将 setup函数中的this修改成了 undefined)
- setup 函数中的 props 是响应式的,当传入新的 prop 时,它将被更新。但是,因为 props 是响应式的,你不能使用 ES6 解构,因为它会消除 prop 的响应性。
- 从 setup() 中返回的对象上的 property 返回并可以在模板中被访问时,它将自动展开为内部值。不需要在模板中追加 .value
2、ref函数
-
总结:定义一个响应式的数据
-
import {ref} from “vue”
-
语法:const xxx = ref(“value”)
- 创建一个包含响应式的数据的引用对象(reference对象)
- js中操作数据:xxx.value
- 模板中读取数据不需要.value,直接
{ {xxx}}
-
注意
- 接收的数据类型可以是基本数据类型也可以是引用数据类型(对象,数组等 xxx.value.属性值/[下标])
- 基本类型的数据:响应式依然是靠Object.defineProperty()的get和set完成的
- 对象类型的数据:内部“求助”了Vue3.0的一个新的函数------reactive函数
<script setup> import { ref } from "vue" var name = "marry"; var obj = ref({ age: 18, gender: "女", class: '二' }) function change() { obj.value.age++ } </script> <template> <div> <span>{ { obj.class}}班的{ { name}}是一名{ { obj.gender}}生,今年{ { obj.age}}岁了~~~</span> <button @click="change">年龄+1</button> </div> </template>
3、reactive函数
- 作用:定义一个对象类型的响应式数据(基本数据类型别用它,用ref函数)
- 引入:import {reactive} from ‘vue’
- 语法:const 代理一个对象 = reactive(被代理的对象) 接收一个对象(或数组),返回一个代理器对象(proxy对象)
- reactive定义的响应式数据是“深层次的”
- 内部基于ES6的Proxy实现,通过代理对象内部的数据都是响应式的
<script setup>
import {
reactive
} from "vue"
var name = "marry";
var obj = reactive({
age: 18,
gender: "女",
class: '二'
})
function change() {
obj.age++
}
</script>
<template>
<div>
<span>{
{
obj.class}}班的{
{
name}}是一名{
{
obj.gender}}生,今年{
{
obj.age}}岁了~~~</span>
<button @click="change">年龄+1</button>
</div>
</template>
ref \reactive 区别用法?
- 都是用来放响应式数据;
- 引入方式: ref: import {ref} from ‘vue’ / import {reactive} from ‘vue’
- ref( )里面放的是基本数据,和嵌套层数不是很深的引用数据; / reactive( )基本数据不用他,里面放嵌套层数比较深的引用数据;
- ref 用里面的数据时,数据方法**.value**里面, / reactive 用里面的数据时 ,直接使用。
- 响应式设计原理:ref: 监听了value的改变,劫持value属性的setter ,getter ,因此ref一般用在基本数据,或者嵌套不深的引用数据上; / reactive: 和ref一样,但是底层采用的是ES6的Proxy代理了整个引用数据。
4、Vue3.0中的响应式原理
vue2.0的响应式
-
实现原理
-
对象类型:通过Object.definedProperty()对属性的读取、修改进行拦截(数据劫持)
-
数组类型:通过重写更新数据的一系列方法来实现拦截。(对数组的方法进行了包裹)
Object.defineProperty(data,"count",{ get(){}, set(){} })
存在问题:
- 新增属性,删除属性都不会刷新界面
- 直接通过下标修改数组,界面不会自动更新
let person = { name:"李国栋", age:18 } let p = {}; Object.defineProperty(p,"name",{ get(){ console.log("有人读取数据时调用"); return person.name }, set(value){ console.log("有人修改了数据,我要去更新页面"); person.name = value } })
-
vue3.0的响应式
- 实现原理
- 通过Proxy(代理):拦截对象中任意属性的变化,包括:属性的读写,属性的添加,属性的删除等
- 通过Reflect(反射):对被代理对象的属性进行操作
- MDN文档中描述的Proxy与Reflect:
- Proxy:https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Proxy
- Reflect:https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Reflect
let person = {
name:"李国栋",
age:18
}
let p = new Proxy(person,{
// 读取
get(target,proname){
// target表示原对象 proname表示对象名
console.log("有人读取了person上的属性",target);
return target[proname]
},
// 修改或者增加
set(target,proname,value){
console.log("有人修改了person上的属性,我要去更新了");
target[proname] = value
},
// 删除
deleteProperty(target,proname){
console.log("有人删除了person上面的属性,我要去调用了");
return delete target[proname]
},
});
5、组件
-
引入:import xxx from (“组件路径”)
-
引入后直接使用:
6、计算属性
- 引入:import {computed} from “vue”
- 使用:computed( 函数)
<script setup>
import {
ref,
reactive,
computed
} from "vue"
let arr = reactive([{
title: '鱼香肉丝',
price: 20,
count: 1
},
{
title: '水煮肉片',
price: 35,
count: 1
},
{
title: '白米饭',
price: 3,
count: 1
},
])
let total = computed(() => {
console.log(66666, "计算总价")
return arr.reduce((n1, n2) => {
return n1 + n2.price * n2.count
}, 0)
})
let change1 = () => {
arr[0].count = 10
}
function add(index) {
arr[index].count++
}
function des(index) {
arr[index].count--
}
</script>
<template>
<div class="box">
<div v-for="(el,index) in arr">
<div>{
{
el.title}}----{
{
el.price}}元----
<button @click