提示:Vue2系列请参考Vue2+Vue3小白零基础教程—vue2篇文章,本文为vue2小白零基础教程续集。
官方文档:https://cli.vuejs.org/zh/guide/creating-a-project.html#vue-create
## 查看@vue/cli版本,确保@vue/cli版本在4.5.0以上
vue --version
## 安装或升级你的@vue/cli
npm install -g @vue/cli
## 创建
vue create vue_test
## 启动
cd vue_test
npm run serve
官方文档:https://v3.cn.vuejs.org/guide/installation.html#vite
vte官网: https://vitejs.cn
$ npm init vite <project-name> -- --template vue
$ cd <project-name>
$ npm install
$ npm run dev
官方文档:介绍 | 组合式API
理解:We3.0中一个新的配置项,值为一个函数
stup是所有 composition AP(组合AP)“表演的舞台”。
组件中所用到的:数据、方法等等,均要配置在 setup中
setup函数的两种返回值:
我的姓名:{{name}}
我的年龄:{{age}}
性别:{{sex}}
a的值是:{{a}}
const xxx = ref( initValue)
xxx.value
.value
,直接: {{xxx}}
我的姓名:{{name}}
我的年龄:{{age}}
学业信息:{{info.type}}
学号:{{info.sid}}
const 代理对象= reactive(源对象)
接收一个对象(或数组),返回一个代理对象( proxy对象)Proxy
实现,通过代理对象操作源对象内部数据进行操作
我的姓名:{{person.name}}
我的年龄:{{person.age}}
学业信息:{{person.info.type}}
学号:{{person.info.sid}}
爱好: {{person.hibby}}
实现原理
对象类型: 通过 object.defineProperty()
对属性的读取、修改进行拦截(数据劫持)。
数组类型: 通过重写更新数组的一系列方法来实现拦截。(对数组的变更方法进行了包裹)
Object.defineProperty(data, 'count', {
get(){...},
set(){...}
})
存在问题
DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Documenttitle>
head>
<body>
<script>
let person = {
name: "张三",
age: 18
}
//vue2中的响应式原理
// let p = {}
// Object.defineProperty(p, 'name', {
// get(){
// console.log("有人读取了person.name");
// return person.name
// },
// set(value){
// console.log("有人修改了person.name");
// person.name=value
// }
// })
// Object.defineProperty(p, 'age', {
// get(){
// console.log("有人读取了person.age");
// return person.name
// },
// set(value){
// console.log("有人修改了person.age");
// person.name=value
// }
// })
//vue3中数据响应原理
let p = new Proxy(person, {
get(target, propName){
console.log(`有人读取了person身上的${propName}属性`);
// return target[propName]
return Reflect.get(target, propName)
},
set(target, propName, value){
console.log(`有人修改或添加了person身上的${propName}属性`);
// target[propName] = value
Reflect.set(target, propName, value)
},
deleteProperty(target, propName){
console.log(`有人删除了person身上的${propName}属性`);
// return delete target[propName]
Reflect.deleteProperty(target, propName)
}
})
script>
body>
html>
从定义数据角度对比
从原理角度对比
Object.defineProperty()
的get与set来实现响应式(数据劫持Proxy
来实现响应式(数据劫持),并通过 Reflect
操作源对象内部的数据。从使用角度对比
.value
,读取数据时模板中直接读取不需要.vaue
.value
this. $attrs
this.slots
this. $emit
hello world
学校信息
学校名称:{{name}}
学校地址:{{addr}}
与vue2x中 computec配置功能一致
写法
个人信息:
姓:
名:
全名:{{person.fullName}}
姓名:
与Ve2x中 watch配置功能一致
两个小“坑”
num的值为:{{num}}
姓名:{{name}}
学生信息
学生姓名:{{student.sname}}
学生学号:{{student.sid}}
薪水:{{student.job.j1.salary}}
num的值为:{{num}}
姓名:{{name}}
学生信息
学生姓名:{{student.sname}}
学生学号:{{student.sid}}
薪水:{{student.job.j1.salary}}
beforeDestroy
改名为 beforeUnmount
destroyed
改名为unmount
hello world
num : {{num}}
什么是hook?
hook函数
import {reactive,onMounted, onUnmounted} from "vue"
export default function(){
let point = reactive({
x: 0,
y: 0
})
function getPoint(event){
point.x = event.pageX
point.y = event.pageY
console.log(point.x,point.y);
}
onMounted(()=>{
window.addEventListener("click", getPoint)
})
onUnmounted(()=>{
window.removeEventListener("click", getPoint)
})
return point
}
Demo.vue
hello world
num : {{num}}
鼠标点击的坐标为:x:{{point.x}}, y:{{point.y}}
const name = toRef(person, "name")
toRefs
与toRe
功能一致,但可以批量创建多个re对象,语法: toRefs(person)
{{person}}
我的姓名:{{name}}
我的年龄:{{age}}
学业信息:{{info.type}}
学号:{{info.sid}}
爱好: {{hibby}}
遇到bug:在多个shallowRef属性时,一个时基本的数据类型,一个是对象类型,先点击修改对象的类型,后点击修改基本数据类型,之前修改而为响应的对象类型也会修改。
num的值为:{{num}}
x的值为:{{x}}
学生信息
学生姓名:{{student.sname}}
学生学号:{{student.sid}}
薪水:{{student.job.j1.salary}}
num的值为:{{num}}
学生信息
学生姓名:{{student.sname}}
学生学号:{{student.sid}}
薪水:{{student.job.j1.salary}}
num的值为:{{num}}
学生信息
学生姓名:{{student.sname}}
学生学号:{{student.sid}}
薪水:{{student.job.j1.salary}}
Car:{{student.car}}
{{msg}}
作用: 实现祖孙组件(跨级组件)间通信
套路:父组件有一个provide
选项来提供数据,子组件有一个inject
选项来开始使用这些数据
具体写法:
祖组件中
祖组件, 汽车品牌:{{name}}, 价格{{price}}
子组件中(孙组件可以使用provid和inject,也可以使用props)
子组件
孙组件中
孙组件, 汽车品牌:{{name}}, 价格{{price}}
reactive
创建的响应式代理readonly
创建的只读代理reactive
或者 readonly
方法创建的代理
祖组件, 汽车品牌:{{name}}, 价格{{price}}
传统 OptionsAPI中,新增或者修改一个需求,就需要分别在data, methods, computed里修改
我们可以更加优雅的组织我们的代码,函数。让相关功能的代码更加有序的组织在一起
弹窗
这是一个弹窗
等待异步组件时渲染一些额外内容,让应用有更好的用户体验
使用步骤:
异步引入组件
父组件
加载中。。。
子组件
子组件
{{num}}
vue2x有许多全局API和配置
例如:注册全局组件、注册全局指令等
//注册全局组件
Vue.component('MyButtom',{
data:()=>({
count: 0
}),
template: ''
})
//注册全局指令
Vue.directive('focus',{
inserted: el => el.focus()
})
vue3.0中对这些API做出了调整
data选项应始终被声明为一个函数
过度类名的更改
vue2x写法
.v-enter
.v-leave-to{
opacity: 0;
}
.v-leave,
.v-enter-to{
opacity: 1;
}
vue3x写法
.v-enter-from
.v-leave-to{
opacity: 0;
}
.v-leave-from,
.v-enter-to{
opacity: 1;
}
移除 keyCode作为v-on的修饰符,同时也不再支持 config.keyCodes
移除 v- on.native
修饰符
父组件中绑定事件
子组件中声明自定义事件
移除过滤器(fter)
过滤器虽然这看起来很方便,但它需要一个自定义语法,打破大括号内表达式是“只是 JavaScript"的假设,这不仅有学习成本,而且有实现成本!建议用方法调用或计算属性去替换过滤器。
}, 1000)
})
return await p
}
}
vue2x有许多全局API和配置
例如:注册全局组件、注册全局指令等
//注册全局组件
Vue.component('MyButtom',{
data:()=>({
count: 0
}),
template: ''
})
//注册全局指令
Vue.directive('focus',{
inserted: el => el.focus()
})
vue3.0中对这些API做出了调整
将全局的API,即: vue.xxx
调整到应用实例(app
)上
[外链图片转存中…(img-tB04dAG2-1632411038088)]
data选项应始终被声明为一个函数
过度类名的更改
vue2x写法
.v-enter
.v-leave-to{
opacity: 0;
}
.v-leave,
.v-enter-to{
opacity: 1;
}
vue3x写法
.v-enter-from
.v-leave-to{
opacity: 0;
}
.v-leave-from,
.v-enter-to{
opacity: 1;
}
移除 keyCode作为v-on的修饰符,同时也不再支持 config.keyCodes
移除 v- on.native
修饰符
父组件中绑定事件
子组件中声明自定义事件
移除过滤器(fter)
过滤器虽然这看起来很方便,但它需要一个自定义语法,打破大括号内表达式是“只是 JavaScript"的假设,这不仅有学习成本,而且有实现成本!建议用方法调用或计算属性去替换过滤器。
…