vue3.0
vue2和vue3的区别
1vue2 和vue3双向数据绑定原理不同
2.0的响应式基于Object.defineProperty中的set和get方法实现兼容主流浏览器和ie9以上的ie浏览器,能够监听数据对象的变化,但是监听不到对象属性的增删、数组元素和长度的变化,同时会在vue初始化的时候把所有的Observer(观察者)都建立好,才能观察到数据对象属性的变化。
3.0的响应式采用了ES2015的Proxy来代替Object.defineProperty,可以做到监听对象属性的增删和数组元素和长度的修改,同时还实现了惰性的监听(不会在初始化的时候创建所有的Observer,而是会在用到的时候才去监听)但是,虽然主流的浏览器都支持Proxy,ie系列却还是不兼容,所以针对ie11,vue3.0决定做单独的适配,暴露出来的api一样,但是底层实现还是Object.defineProperty
2vue3默认进行懒观察(lazy observation)
vue2.0中数据一开始就创建了观察者,数据很大的时候,就会出现问题,vue3中进行了优化 只有用于渲染初始化可见部分的数据,才会创建观察者,效率更高。
3Vue3 对ts的支持更好
4项目目录结构发生了变化
2.x中 移除了配置文件目录,config 和 build 文件夹 3.x中 相关的配置需要在根目录中手动创建vue.config.js
5更精准的变更通知
2.x 版本中,你使用 Vue.set 来给对象新增一个属性时,这个对象的所有 watcher 都会重新运行; 3.x 版本中,只有依赖那个属性的 watcher 才会重新运行
6.vue2组件属性方式变成CompositionAPI(组合式)函数式风格。
vue/cli 5x
在vue3开发中 脚手架vue/cli版本必须最新 cnpm install -g @vue/cli
创建项目同 之前方式 使用 vue create 项目名
注意 在vue/cli 5x中对我们的文件名 有约束必须大驼峰
注意 在项目根目录找到一个vue.config.js 文件,没有就在根目录创建一个,写上下面标注的代码,保存,在重新编译。项目就可以正常运行了。
const { defineConfig } = require('@vue/cli-service') module.exports = defineConfig({ transpileDependencies: true, lintOnSave: false//关闭eslint的校验 })
Vue3 新特性函数 ---- setup 启动器
1.setup函数是处于 生命周期函数 beforeCreate 和 Created 两个钩子函数之间的函数 也就说在 setup函数中是无法 使用 data 和 methods 中的数据和方法的 2、setup函数是 Composition API(组合API)的入口 3、在setup函数中定义的变量和方法最后都是需要 return 出去的 不然无法再模板中使用
注意:vue3和vue2不同的地方就是不必写 data、methods、等代码块了所有的东西都可以在 setup 中返回
setup 可以返回两种值:
返回对象
1、返回对象,对象中的属性、方法都可以直接在模板中使用--稍后马上学到
返回渲染函数(很少用)
2、返回渲染函数,可以自定义渲染内容(其实也就是 render 函数)注意:渲染函数优先级还高,他会替换掉模板中的其他内容(用的比较少记住就好)
VUE3中h()函数和createVNode()函数的使用
h()函数和createVNode()函数都是创建dom节点,他们的作用是一样的,但是在VUE3中createVNode()函数的功能比h()函数要多且做了性能优化,渲染节点的速度也更快。
语法:
h(标签, {属性},内容)
<template> <div> </div> </template> <script> // 1.要使用先引用 import {h} from "vue" export default { setup() { return () => h('div',{class:"demodiv"}, ['Hello,Vue3']) } } </script> <style> </style>
h(标签, {属性},[可以继续嵌套h()])
<template> <div> </div> </template> <script> // 1.要使用先引用 import {h} from "vue" export default { setup() { return () => h('div',{class:"demodiv"}, [ h("h1",{class:"demoh"},["我是标题标签"]) ]) } } </script> <style> </style>
createVNode(标签, {属性},[内容])
<template> <div> </div> </template> <script> // 1.要使用先引用 import {createVNode} from "vue" export default { setup() { return () => createVNode('div',{class:"demodiv"}, ['Hello,Vue3']) } } </script> <style> </style>
createVNode(标签, {属性},[可以继续嵌套createVNode()])
<template> <div> </div> </template> <script> // 1.要使用先引用 import {createVNode} from "vue" export default { setup() { return () => createVNode('div',{class:"demodiv"}, [ createVNode("h1",{class:"demoh"},["我是标题标签"]) ]) } } </script> <style> </style>
setup参数
setup有两个形参
参数1第一个参数props
props是一个对象,包含父组件传递给子组件的所有数据。
父组件
<template> <div> 我是父组件 <Zc title="我是正向传值的数据"/> </div> </template> <script> import { defineComponent } from 'vue' import Zc from "../components/ZiCom.vue" //defineComponent最重要的是:在TypeScript下,给予了组件 正确的参数类型推断 //defineComponent最重要的是:在TypeScript下,给予了组件 正确的参数类型推断 export default defineComponent({ components:{ Zc }, setup() { return { } }, }) </script> <style> </style>
子组件
<template> <div> 我是子组件--{ {title}} </div> </template> <script> import { defineComponent } from 'vue' export default defineComponent({ props:["title"],//子组件设置props setup(props) {//setup第一个参数是props console.log(props)//如果想在setup中读取props数据必须设置第一个形参 return { } }, }) </script> <style> </style>
参数2第一个参数context
context是setup的第二个参数里面包含了以下三个属性 attrs emit slots
attrs
attrs 获取当前标签上面的所有属性的对象
注意 attrs是接收props没有声明的属性
注意 如果子组件用props已经声明 就不能使用attrs 否则会返回undefind
父组件
<template> <div> 我是父组件 <Zc title="我是正向传值的数据"/> </div> </template> <script> import { defineComponent } from 'vue' import Zc from "../components/ZiCom.vue" export default defineComponent({ components:{ Zc }, setup() { return { } }, }) </script> <style> </style>
子组件
<template> <div> 我是子组件--{ {title}} </div> </template> <script> import { defineComponent } from 'vue' export default defineComponent({ // props:["title"],//如果使用attrs接收就不能声明props否则接收不到 setup(props,context) {//setup第2个参数是context console.log(context.attrs) return { } }, }) </script> <style> </style>
总结:
什么时候用props来接收数据 什么时候使用context的attrs来接受数据
1.如果你接收来的数据想在页面展示的时候你使用props来接收(使用props接受的时候 必须定义props这个属性)
2.如果父组件传递过来的数据你不想在页面展示 只是想使用这个数据进行一些逻辑处理 那么你可以使用context.attrs来进行接受(如果想使用 不能定义props)
emit自定义事件
emit事件分发 用于子传父 如果子组件的数据想传递给父组件 就是用emit(逆向传值)
子组件
<template> <div> 我是子组件 <button @click="zifun">点我抛出事件</button> </div> </template> <script> import { defineComponent } from 'vue' export default defineComponent({ setup(props,context) { // 子组件通过context的emit方法进行数据的抛出 let zifun=()=>{ context.emit("zipao",'我是子组件的数据') } return {//不要忘了return zifun } }, }) </script> <style> </style>
父组件
<template> <div> 我是父组件 <!-- 接收子组件的数据 注意不加()不加()--> <Zc @zipao="fufun"/> </div> </template> <script> import { defineComponent } from 'vue' import Zc from "../components/ZiCom.vue" export default defineComponent({ components:{ Zc }, setup() { let fufun=(val)=>{ console.log("子组件的数据",val) } return { fufun