哪个网站可以做汽车评估,电子商务网站建设的意义是什么,池州网站制作公,龙岗网站建设流程VUE3版本新特性
VUE3和VUE2的区别路由的使用vite安装项目新特性使用
1.VUE3和VUE2的区别
2020年9月18日#xff0c;Vue.js发布版3.0版本#xff0c;代号#xff1a;One Piece 于 2022 年 2 月 7 日星期一成为新的默认版本! Vue3性能更高,初次渲染快55%, 更新渲染快133% 。…VUE3版本新特性
VUE3和VUE2的区别路由的使用vite安装项目新特性使用
1.VUE3和VUE2的区别
2020年9月18日Vue.js发布版3.0版本代号One Piece 于 2022 年 2 月 7 日星期一成为新的默认版本! Vue3性能更高,初次渲染快55%, 更新渲染快133% 。体积更小 Vue3.0 打包大小减少41%。 同时Vue3可以更好的支持TypeScript。 vue3中文文档Vue.js : https://cn.vuejs.org/vue2和vue3的主要区别在于以下几点1、生命周期函数钩子不同
beforeCreate - setup() 开始创建组件之前创建的是data和method
created - setup()
beforeMount - onBeforeMount 组件挂载到节点上之前执行的函数。
mounted - onMounted 组件挂载完成后执行的函数
beforeUpdate - onBeforeUpdate 组件更新之前执行的函数。
updated - onUpdated 组件更新完成之后执行的函数。
beforeDestroy - onBeforeUnmount 组件挂载到节点上之前执行的函数。
destroyed - onUnmounted 组件卸载之前执行的函数。
activated - onActivated 组件卸载完成后执行的函数
deactivated - onDeactivated 在组件切换中老组件消失的时候执行2、数据双向绑定原理不同
VUE2VUE3利用ES5的一个APIObject.defineProperty()对数据进行劫持结合发布者订阅者模式的方式来实现的。使用了ES6的Proxy API对数据代理。
vue3提供的proxy API代理的优势在于
defineProperty只能监听某个属性不能对全对象监听可以省去for…in闭包等内容来提升效率直接绑定整个对象即可可以监听数组不再单独的对数组做特异性处理。可以检测到数组内部数据的变化。
3、定义变量和方法不同
vue2vue3在data中定义变量在methods中创建方法使用一个新的setup方法
vue3提供的setup方法在组件初始化构造的时候触发使用以下三个步骤建立反应性数据 从vue引入reactive 使用reactive方法来声明数据为响应性数据 使用setup方法返回响应性数据从而template可以获取这些响应式数据。 script
export default {
setup(){// 数据和方法都写这里更简洁const user username;const met (){}
}
}
/script4、API类型不同
vue2vue3选项型api在代码中分割不同属性datacomputedmethods等组合型api使用方法进行分隔显得更加简便整洁
5、是否支持碎片
vue2vue3否是即可以拥有多个根节点
templatedivh1/h1divdivh1/h1div
/template6、父子之间传参不同
vue2vue3父传子子组件通过prop接收子传父子组件中通过$emit向父组件触发一个监听方法传递一个参数使用setup()中的第二个参数content对象中有emit只需要在setup()接收第二个参数中使用分解对象法取出emit就可以在setup方法中随意使用了。
7、v-if 和 v-for的优先级
VUE2VUE3v-for 优先于 v-if 生效v-if 优先于 v-for 生效
2.使用Vite创建项目
在VUE3中使用vite来创建项目而不再使用 vue-cli初始化项目 ,vite 是新一代前端构建工具官网地址https://vitejs.cnvite的优势如 轻量快速的热重载HMR能实现极速的服务启动。 对 TypeScript、JSX、CSS 等支持开箱即用。 真正的按需编译不再等待整个应用编译完成。注意Vite 需要 Node.js 版本 12.0.0。【使用nvm安装 node 18.14.2】 注意:还需要去设置仓库地址: npm config set registry https://registry.npmmirror.com在VUE2中使用npm进行包的管理在VUE3中pnpm进行包的管理首先我们需要安装 pnpm
安装pnpm :
在磁盘上创建一个文件夹如 vue3-demo,然后进入目录使用cmd窗口执行命令如下
npm i pnpm -g安装vite : 执行下面命令按照提示完成项目创建 pnpm create vitelatest 或者 yarn create vite
1.输入项目名字默认为vue3-demo2.选择创建的项目类型选择vue即可3.选择创建的vue项目类型 TypeScript4.启动项目
命令 pnpm create vitelatest 执行效果如下
- 也可以使用 npm init vitelatest
3. 安装依赖 进入到创建好的项目中执行命令 pnpm i
shell
pnpm icnpm install启动项目 启动命令看 package.json - scripts { … } pnpm dev访问控制台地址启动效果如下然后使用开发工具导入创建好的项目
3.项目结构认识
├── dist/ //代码编译目录
└── src/├── api/ // 接口请求目录├── assets/ // 静态资源目录├── common/ // 通用类库目录├── components/ // 公共组件目录├── router/ // 路由配置目录├── store/ // 状态管理目录├── style/ // 通用样式目录├── utils/ // 工具函数目录├── views/ // 页面组件目录├── App.vue├── main.ts //主ts
├── tests/ // 单元测试目录
├── index.html //默认首页入口页面
├── jsconfig.json // JavaScript 配置文件
├── vite.config.js // Vite 配置文件
└── package.json //依赖管理
└── vite.config.ts4.route的使用
4.1.安装route路由
官网https://router.vuejs.org/zh/installation.html
pnpm install vue-router4
4.2.创建页面
在src目录下创建views/order/order.vue 以及 views/user/user.vue 页面文件内容如下
script setup langts/scripttemplatediv11111111111111/div
/templatestyle scoped
/style
----4.3.创建router
在src目录下创建router/index.ts文件内容如下
import { createRouter, createWebHashHistory } from vue-routerconst router createRouter({history: createWebHashHistory(),routes: [{path:/,name:home,component:()import(../views/User.vue)},{path:/test,name:test,component:()import(../views/Order.vue),}],})export default router createWebHashHistory: hash 模式下使用的是createWebHashHistoryapi 进行配置 VueRouter 的历史模式。使用 hash 模式下会在浏览器网页路由当中使用哈希字符#对 url 进行切割并且匹配哈希字符后的字符进行判断路由匹配与跳转处理。 4.4.在main.js中使用路由 ...省略...//导入路由import { createApp } from vue’import router from ‘./router/index’
//创建appconst app createApp(App);
//使用路由app.use(router)
//挂载appapp.mount(‘#app’)
#### 4.5.在App.vue文件中指定路由出口
vue
templatediv!-- 路由出口 所有页面都会放到这个里面--router-view/router-view/div
/template4.6.重启测试
5.vue的核心语法
5.1 简单入门
Vue3向下兼容Vue2语法且Vue3中的模板中可以没有根标签
templatediv classpersonh2姓名{{name}}/h2h2年龄{{age}}/h2button clickchangeName修改名字/buttonbutton clickchangeAge年龄1/buttonbutton clickshowTel点我查看联系方式/button/div
/templatescript langtsexport default {name:App,data() {return {name:张三,age:18,tel:13888888888}},methods:{changeName(){this.name zhang-san},changeAge(){this.age 1},showTel(){alert(this.tel)}},}
/script5.2 Setup函数
在学习以下知识之前我们先了解一下 options api 和 composition api的区别vue2中使用的是optionsAPI来定义一个组件内部的一些属性如methods、data等等其缺点往往会在大项目中体现出来比如一个简单的计数器功能可能需要在methods内部书写一部分逻辑在computed内部也书写一部分逻辑那么问题来了如果该组件内部有n个这样的小功能那么此时代码逻辑是十分分散的并且后期迭代维护面临的问题也是可能修改一个需求需要在不同的属性内部反复查找相关的代码而compositionAPI的出现就是为了解决这一问题的。
vue3新增的compositionAPI主要就是为了解决API太过于分散的问题避免一个功能点下的api太过于分散不便于维护将同一个功能下的api统一放到一个地方这样一来项目的开发和维护就简便多了。compositionAPI也叫做组合式APIvue3中组合式API的入口就是setup函数 https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/bc0be8211fc54b6c941c036791ba4efe~tplv-k3u1fbpfcp-watermark.image setup是Vue3中一个新的配置项值是一个函数它是 Composition API “表演的舞台”组件中所用到的数据、方法、计算属性、监视…等等均配置在setup中。
特点如下
setup函数返回的对象中的内容可直接在模板中使用。setup中访问this是undefined。setup函数会在beforeCreate之前调用它是“领先”所有钩子执行的。
5.1.普通写法[不推荐]
通过 export default { setup(){ } } 来定义setup函数 这种方式不推荐
templatediv classpersonh2姓名{{name}}/h2h2年龄{{age}}/h2button clickchangeName修改名字/buttonbutton clickchangeAge年龄1/buttonbutton clickshowTel点我查看联系方式/button/div
/templatescript langtsexport default {name:Person,setup(){// 数据原来写在data中注意此时的name、age、tel数据都不是响应式数据let name 张三let age 18let tel 13888888888// 方法原来写在methods中function changeName(){name zhang-san //注意此时这么修改name页面是不变化的console.log(name)}function changeAge(){age 1 //注意此时这么修改age页面是不变化的console.log(age)}function showTel(){alert(tel)}// 返回一个对象对象中的内容模板中可以直接使用return {name,age,tel,changeName,changeAge,showTel}}}
/script5.2.语法糖[推荐] 注意在setup语法中使用 this 会出现unidefined , 在 setup 中你应该避免使用 this因为它不会找到组件实例。setup 的调用发生在 data property、computed property 或 methods 被解析之前所以它们无法在 setup 中被获取这也是为了避免setup()和其他选项式API混淆。### 6.数据响应函数
什么是响应式响应式指的是把数据绑定当视图当数据的值发生改变视图也会跟着重新渲染。
#### 6.1.ref基础数据响应式函数
VUE3提供了ref函数可以在修改完 数据后自动渲染视图类似余双向绑定- 在js中通过 import {ref} from vue; 来声明 ref函数
- 注意ref属性在js中要使用.value 取值
javascript
templatediv classpersonh2姓名{{name}}/h2h2年龄{{age}}/h2button clickchangeName修改名字/buttonbutton clickchangeAge年龄1/buttonbutton clickshowTel点我查看联系方式/button/div
/templatescript setup langts namePersonimport {ref} from vue// name和age是一个RefImpl的实例对象简称ref对象它们的value属性是响应式的。let name ref(张三)let age ref(18)// tel就是一个普通的字符串不是响应式的let tel 13888888888function changeName(){// JS中操作ref对象时候需要.valuename.value 李四console.log(name.value)// 注意name不是响应式的name.value是响应式的所以如下代码并不会引起页面的更新。// name ref(zhang-san)}function changeAge(){// JS中操作ref对象时候需要.valueage.value 1 console.log(age.value)}function showTel(){alert(tel)}
/script通过ref获取dom对象
templateinput refinputRef :valuerefValue/
/templatescript setupimport {ref} from vue;//变量名 inputRef 和 dom元素上的refinputRef 一样就能获取到dom元素let inputRef ref(null);console.log(inputRef);/script6.2.reactive创建对象类型的响应式数据
对于对象类型可以使用reactive进行响应式函数处理
templatediv classpersonh2汽车信息一台{{ car.brand }}汽车价值{{ car.price }}万/h2h2游戏列表/h2ulli v-forg in games :keyg.id{{ g.name }}/li/ulh2测试{{obj.a.b.c.d}}/h2button clickchangeCarPrice修改汽车价格/buttonbutton clickchangeFirstGame修改第一游戏/buttonbutton clicktest测试/button/div
/templatescript langts setup namePerson
import { reactive } from vue// 数据
let car reactive({ brand: 奔驰, price: 100 })
let games reactive([{ id: ahsgdyfa01, name: 英雄联盟 },{ id: ahsgdyfa02, name: 王者荣耀 },{ id: ahsgdyfa03, name: 原神 }
])
let obj reactive({a:{b:{c:{d:666}}}
})function changeCarPrice() {car.price 10
}
function changeFirstGame() {games[0].name 流星蝴蝶剑
}
function test(){obj.a.b.c.d 999
}
/script注意其实ref接收的数据可以是基本类型、对象类型。若ref接收的是对象类型内部其实也是调用了reactive函数
例如
templatediv classpersonh2汽车信息一台{{ car.brand }}汽车价值{{ car.price }}万/h2h2游戏列表/h2ulli v-forg in games :keyg.id{{ g.name }}/li/ulh2测试{{obj.a.b.c.d}}/h2button clickchangeCarPrice修改汽车价格/buttonbutton clickchangeFirstGame修改第一游戏/buttonbutton clicktest测试/button/div
/templatescript langts setup namePerson
import { ref } from vue// 数据
let car ref({ brand: 奔驰, price: 100 })
let games ref([{ id: ahsgdyfa01, name: 英雄联盟 },{ id: ahsgdyfa02, name: 王者荣耀 },{ id: ahsgdyfa03, name: 原神 }
])
let obj ref({a:{b:{c:{d:666}}}
})console.log(car)function changeCarPrice() {car.value.price 10
}
function changeFirstGame() {games.value[0].name 流星蝴蝶剑
}
function test(){obj.value.a.b.c.d 999
}
/script对比
ref用来定义基本类型数据、对象类型数据reactive用来定义对象类型数据。ref创建的变量必须使用.valuereactive重新分配一个新对象会失去响应式
7.toRef 和 toRefs【了解】
7.1.toRef解析响应式
将一个响应式对象中的每一个属性转换为ref对象toRefs与toRef功能一致但toRefs可以批量转换。
templatediv classpersonh2姓名{{person.name}}/h2h2年龄{{person.age}}/h2h2性别{{person.gender}}/h2button clickchangeName修改名字/buttonbutton clickchangeAge修改年龄/buttonbutton clickchangeGender修改性别/button/div
/templatescript langts setup namePersonimport {ref,reactive,toRefs,toRef} from vue// 数据let person reactive({name:张三, age:18, gender:男})// 通过toRefs将person对象中的n个属性批量取出且依然保持响应式的能力let {name,gender} toRefs(person)// 通过toRef将person对象中的gender属性取出且依然保持响应式的能力let age toRef(person,age)// 方法function changeName(){name.value ~}function changeAge(){age.value 1}function changeGender(){gender.value 女}
/script8.computed计算函数
下面通过计算函数演示2个值相加需要通过 import {computed} from “vue”; 引入函数
templatediv classperson姓input typetext v-modelfirstName br名input typetext v-modellastName br全名span{{fullName}}/span brbutton clickchangeFullName全名改为li-si/button/div
/templatescript setup langts nameAppimport {ref,computed} from vuelet firstName ref(zhang)let lastName ref(san)// 计算属性——只读取不修改/* let fullName computed((){return firstName.value - lastName.value}) */// 计算属性——既读取又修改let fullName computed({// 读取get(){return firstName.value - lastName.value},// 修改set(val){console.log(有人修改了fullName,val)firstName.value val.split(-)[0]lastName.value val.split(-)[1]}})function changeFullName(){fullName.value li-si}
/script9.watch监听器
watch的作用是用来监听某个值的变化从而出发watch回调。watch可以 监听单体数据 监听对象 监听对象的某个属性 监听多个数据 templatediv classwatch/divbutton clickvalue修改value/buttonbutton clickpersion.age修改persion/button
/template
script setupimport {reactive, ref, watch} from “vue”;
const value ref(1111);const persion reactive({ username:“zs” , age:18})//监听单个值watch(value,(){ console.log(value);})//监听对象watch(persion,(){ console.log(persion);})
//监听多个,用[]包含多个watch([persion,value],(){ console.log(persion,value);});
//监听对象的属性 watch(persion.age,(){ console.log(persion);});
watch如果监听对象可以深度监听(即对象中又深度嵌套了对象嵌套的对象值被修改也会被监听到)
### 10.watchEffect监听副作用[了解]
立即运行一个函数同时响应式地追踪其依赖并在依赖更改时重新执行该函数。watchEffect的作用是只要使用到的数据都会被监听到无需指定具体监听谁他包含4个功能- 页面加载watchEffect的回调就会立即执行
- 只要watchEffect 只要里面使用了任何数据就会触发回到函数
- onCleanup函数可以清除副作用
- 返回一个stopHandler可以停止监听
vue
templatediv classwatch_effect/divbutton clicknumnum/buttonbutton clickstopHandlerStopWatch/button
/templatescript setupimport {ref, watchEffect} from vue;const num ref(1111);//1.页面加载初始化立即回执行回调
//2.只要watchEffect 只要里面使用了数据就会触发回到函数
//3.onCleanup函数可以清除副作用
//4.返回一个stopHandler可以停止监听
/**
watchEffect((){console.log(num.value);
})**/const stopHandler watchEffect(onCleanup{console.log(num.value);onCleanup((){console.log(清除副作用);});
})/script11.生命周期方法
因为 setup 是围绕 beforeCreate 和 created 生命周期钩子运行的所以不需要显式地定义它们。换句话说在这些钩子中编写的任何代码都应该直接在 setup 函数中编写。下表包含如何在 setup () 内部调用生命周期钩子
选项式 API(VUE2)Hook inside setupbeforeCreateNot needed* 不需要createdNot needed* 不需要beforeMountonBeforeMount挂载之前mountedonMounted页面加载完成时执行beforeUpdateonBeforeUpdateupdatedonUpdatedbeforeUnmountonBeforeUnmountunmountedonUnmounted页面销毁时执行errorCapturedonErrorCapturedrenderTrackedonRenderTrackedrenderTriggeredonRenderTriggeredactivatedonActivateddeactivatedonDeactivated
下面是代码案例
script setup
import {onBeforeMount, onBeforeUnmount, onMounted, onUnmounted} from vue;console.log(初始化)
onMounted((){console.log(onMounted 挂载中...);
})onBeforeMount((){console.log(onBeforeMount 挂载前....);
})
onUnmounted((){console.log(onUnmounted 当销毁..)
})
onBeforeUnmount((){console.log(onBeforeUnmount 当销毁前..)
})
/script12.父子组件[重点]
12.1.父传参数给子
第一步创建一个父组件页面引入子组件并传入参数 parent.vue
templateH1 classparent_child父传子/H1h2使用子组件传参/h2child-vue text传入静态文本 :numnum :titletitle :persionpersion/child-vue
/templatescript setup//引入子组件取名用驼峰页面用中划线 child-vue/child-vue
import ChildVue from /views/parent_child/child.vue;
import {reactive, ref} from vue;//构建一个响应式对象
const persion reactive({username:zs,age:18
})
//定义响应式变量
const title ref(我是标题);
const num ref(111);
/script第二步创建一个子组件页面 : child.vue 通过 defineProps接受父传入的参数
templateh2text{{text}}/h2h2num{{num}}/h2h2title{{title}}/h2h2persion{{persion}}/h2
/templatescript setup
//通过defineProps来接受父传入过来的参数
const prop defineProps({text:String,num:Number,title:String,persion:Object
})
//在js中可以读取父传入过来的参数但是不能修改
console.log(prop.title , prop.title)/script注意在子组件中没法修改父转件传入的参数
12.2.子传参给父
子组件给父组件传值需要通过defineEmits在子组件声明事件方法然后调用该事件方法传值父组件需要监听该事件方法取值。第一步在子组件中准备一个按钮点击按钮就给父组件传值。然后给按钮绑定一个方法。
h1给父组件传参/h1
button clicksendData2Parent给父组件传参/button------------------------------------------------------------------------------------------//声明事件
const $emits defineEmits([data2parent,事件名,事件名]);const sendData2Parent (){//调用声明的事件$emits(data2parent,传给父组件的数据);
}const $emits defineEmits([“data2parent”,“事件2”,“事件3”]); 自定义了三个事件$emits(‘data2parent’,“传给父组件的数据”); 调用自定义的事件
第二步在父组件中绑定该事件并调用一个函数来接受值
child-vue data2parentgetDataFromChild .../child-vueconst getDataFromChild (data){console.log(打印数据,data);
}data2parent“getDataFromChild” : data2parent对应了子组件中声明的事件拿到数据后交给getDataFromChild去处理。 12.3.子暴露 VUE3提供了 defineExpose 来暴露子组件中的数据和方法在父组件中可以拿到子组件中暴露的数据或者方法。第一步在子组件中暴露数据 //子暴露
defineExpose({data:我是子暴露的数据,sayHi:(){return 我是子暴露的方法被调用返回的结果;}
})第二步在父组件接受子暴露的数据 child-vuerefchildVueRef .../child-vue//用一个响应式变量接受子暴露的数据const childVueRef ref(null);onMounted((){ console.log(“子暴露的数据”,childVueRef.value.data); console.log(“子暴露的方法”,childVueRef.value.sayHi());})
- refchildVueRef : 接受子暴露把数据绑定给childVueRef注意因为在父组件的 setup 函数中声明周期很早此时子组件还没加载所以需要在onMounted去调用子暴露的数据和方法才可以拿到结果。### 13.自定义Hooks函数
**hooks就是用来给我们抽取公共代码的**hooks函数就是通过 use开头的js参数 。 自定义hook的优势复用代码, 让setup中的逻辑更清楚易懂。
代码如下 useSum.tsjs
import {ref,onMounted} from vueexport default function(){let sum ref(0)const increment (){sum.value 1}const decrement (){sum.value - 1}onMounted((){increment()})//向外部暴露数据return {sum,increment,decrement}
} useDog.ts中内容如下
import {reactive,onMounted} from vue
import axios,{AxiosError} from axiosexport default function(){let dogList reactivestring[]([])// 方法async function getDog(){try {// 发请求let {data} await axios.get(https://dog.ceo/api/breed/pembroke/images/random)// 维护数据dogList.push(data.message)} catch (error) {// 处理错误const err AxiosErrorerrorconsole.log(err.message)}}// 挂载钩子onMounted((){getDog()})//向外部暴露数据return {dogList,getDog}
}组件中使用
templateh2当前求和为{{sum}}/h2button clickincrement点我1/buttonbutton clickdecrement点我-1/buttonhrimg v-for(u,index) in dogList :keyindex :srcu span v-showdogList.isLoading加载中....../spanbrbutton clickgetDog再来一只狗/button
/templatescript langtsimport {defineComponent} from vueexport default defineComponent({name:App,})
/scriptscript setup langtsimport useSum from ./hooks/useSumimport useDog from ./hooks/useDoglet {sum,increment,decrement} useSum()let {dogList,getDog} useDog()
/script