语法差异
一、 关于vuex的使用
vue2.0 创建仓库 new Vuex.Store({})
vue3.0 创建仓库 createStore({})
vue3中:
============================>创建
import { createStore } from 'vuex'
// 创建vuex仓库并导出
export default createStore({
state: {
// 数据
},
mutations: {
// 改数据函数
},
actions: {
// 请求数据函数
},
modules: {
// 分模块
},
getters: {
// vuex的计算属性
}
})
====================================》使用
import { useStore } from 'vuex'
const store = useStore()
二、关于router的使用和app的创建
vue2中:
import Vue from 'vue';
import Router from 'vue-router';
Vue.use(Router);
const routes =[]
onst router = new Router({
routes,
mode: 'hash',
})
vue3中:
import { createApp } from 'vue'
import App from './App'
import { createRouter, createWebHashHistory } from 'vue-router'
const routes = []
// 创建路由实例
const router = createRouter({
// 使用hash方式实现路由
history: createWebHashHistory(),
// 配置路由规则,写法和之前一样
routes
})
createApp(App).use(router)
三、vue3新增组合式api语法
1.setup函数
setup () {
return { }
},
2.reactive函数(通常是用来定义响应式对象数据)
setup () {
const obj = reactive({
name: 'ls',
age: 18
})
// 修改名字
const updateName = () => {
obj.name = 'zs'
}
return { obj ,updateName}
}
3.toRef函数(转换响应式对象中某个属性为单独响应式数据)
setup () {
// 1. 响应式数据对象
const obj = reactive({
name: 'ls',
age: 10
})
// 2. 模板中只需要使用name数据
// 注意:从响应式数据对象中解构出的属性数据,不再是响应式数据
// let { name } = obj 不能直接解构,出来的是一个普通数据
const name = toRef(obj, 'name')
const updateName = () => {
// toRef转换响应式数据包装成对象,value存放值的位置
name.value = 'zs'
}
return {name, updateName}
}
4.toRefs函数(转换响应式对象中所有属性为单独响应式数据)
setup () {
// 1. 响应式数据对象
const obj = reactive({
name: 'ls',
age: 10
})
// 以上方式导致数据就不是响应式数据了
const obj3 = toRefs(obj)
const updateName = () => {
obj.name = 'zs' //此处略有不同
}
return {...obj3, updateName}
}
5.ref函数(简单数据类型定义为响应式数据)
setup () {
// 1. name数据
const name = ref('ls')
const updateName = () => {
name.value = 'zs'
}
// 2. age数据
const age = ref(10)
// 对于数据未之的情况下 ref 是最适用的
// const data = ref(null)
// setTimeout(()=>{
// data.value = res.data
// },1000)
return {name, age, updateName}
}
6.computed函数(简单数据类型定义为响应式数据)
setup () {
// 1. 计算属性:当你需要依赖现有的响应式数据,根据一定逻辑得到一个新的数据。
const age = ref(16)
// 得到后年的年龄
const newAge = computed(()=>{
// 该函数的返回值就是计算属性的值
return age.value + 2
})
return {age, newAge}
}
===========================================》高级用法
setup () {
const age = ref(16)
// 计算属性高级用法,传人对象
const newAge = computed({
// get函数,获取计算属性的值
get(){
return age.value + 2
},
// set函数,当你给计算属性设置值的时候触发
set (value) {
age.value = value - 2
}
})
return {age, newAge}
}
7.watch函数
setup () {
const count = ref(0)
const add = () => {
count.value++
}
// 当你需要监听数据的变化就可以使用watch
// 1. 监听一个ref数据
// 1.1 第一个参数 需要监听的目标
// 1.2 第二个参数 改变后触发的函数
// watch(count, (newVal,oldVal)=>{
// console.log(newVal,oldVal)
// })
const obj = reactive({
name: 'ls',
age: 10,
brand: {
id: 1,
name: '宝马'
}
})
const updateName = () => {
obj.name = 'zs'
}
const updateBrandName = () => {
obj.brand.name = '奔驰'
}
// 2. 监听一个reactive数据
watch(obj, ()=>{
console.log('数据改变了')
})
watch(()=>obj.brand, ()=>{
console.log('brand数据改变了')
},{
// 5. 需要深度监听
deep: true,
// 6. 想默认触发
immediate: true
})
// 3. 监听多个数据的变化
// watch([count, obj], ()=>{
// console.log('监听多个数据改变了')
// })
// 4. 此时监听对象中某一个属性的变化 例如:obj.name
// 需要写成函数返回该属性的方式才能监听到
// watch(()=>obj.name,()=>{
// console.log('监听obj.name改变了')
// })
return {count, add, obj, updateName, updateBrandName}
}
8.ref属性
<!-- vue2.0 获取单个元素 -->
<!-- 1. 通过ref属性绑定该元素 -->
<!-- 2. 通过this.$refs.box获取元素 -->
<!-- <div ref="box">我是box</div> -->
<!-- vue2.0 获取v-for遍历的多个元素 -->
<!-- 1. 通过ref属性绑定被遍历元素 -->
<!-- 2. 通过this.$refs.li 获取所有遍历元素 -->
<!-- <ul>
<li v-for="i in 4" :key="i" ref="li">{{i}}</li>
</ul> -->
<!-- 单个元素 -->
<div ref="dom">我是box</div>
<!-- 被遍历的元素 -->
<ul>
<li v-for="i in 4" :key="i" :ref="setDom">第{{i}}LI</li>
</ul>
==============================>
setup () {
// 1. 获取单个元素
// 1.1 先定义一个空的响应式数据ref定义的
// 1.2 setup中返回该数据,你想获取那个dom元素,在该元素上使用ref属性绑定该数据即可。
const dom = ref(null)
onMounted(()=>{
console.log(dom.value)
})
// 2. 获取v-for遍历的元素
// 2.1 定义一个空数组,接收所有的LI
// 2.2 定义一个函数,往空数组push DOM
const domList = []
const setDom = (el) => {
domList.push(el)
}
onMounted(()=>{
console.log(domList)
})
return {省略。。。}
}
四、父子通讯
1.父传子:
// 父组件的数据传递给子组件
setup () {
const money = ref(100)
return { money }
}
========================>
// 子组件接收父组件数据使用props即可
props: {
money: {
type: Number,
default: 0
}
},
setup (props) {
// 获取父组件数据money
console.log(props.money)
}
2.子传父
//子组件传递数据:
setup ({emit}) {
// 向父组件传值
const changeMoney = () => {
// 通知父组件,money需要变成50
emit('change-money', 50)
}
return {changeMoney}
}
==========================》
//父组件接收
<Son @change-money="updateMoney" />
setup () {
const money = ref(100)
const updateMoney = (newMoney) => {
money.value = newMoney
}
return { updateMoney}
}
3.父子双向数据绑定
- 在vue2.x的时候 .sync 除去v-model实现双向数据绑定的另一种方式:
<!-- <Son :money='money' @update:money="fn" /> -->
<Son :money.sync='money' />
- 在vue3.0的时候,使用 v-model:money=“money” 即可:
<!-- <Son :money="money" @update:money="updateMoney" /> -->
<Son v-model:money="money" />
4.依赖注入(后代传值)
//传值者:
setup () {
const money = ref(100)
const changeMoney = (saleMoney) => {
console.log('changeMoney',saleMoney)
money.value = money.value - saleMoney
}
// 将数据提供给后代组件 provide
provide('money', money)
// 将函数提供给后代组件 provide
provide('changeMoney', changeMoney)
return { money }
接收方:=================》
setup () {
// 接收祖先组件提供的数据
const money = inject(‘money’)
return { money }
}
五、语法糖
vue2中:
<Son :value="msg" @input="msg=$event" />
vue3中:
<Son :modelValue="msg" @update:modelValue="msg=$event" />
演示:
<template>
<div class="container">
<!-- 如果你想获取原生事件事件对象 -->
<!-- 如果绑定事函数 fn fn(e){ // e 就是事件对象 } -->
<!-- 如果绑定的是js表达式 此时提供一个默认的变量 $event -->
<h1 @click="$event.target.style.color='red'">父组件 {{count}}</h1>
<hr>
<!-- 如果你想获取自定义事件 -->
<!-- 如果绑定事函数 fn fn(data){ // data 触发自定义事件的传参 } -->
<!-- 如果绑定的是js表达式 此时 $event代表触发自定义事件的传参 -->
<!-- <Son :modelValue="count" @update:modelValue="count=$event" /> -->
<Son v-model="count" />
</div>
</template>
<script>
import { ref } from 'vue'
import Son from './Son.vue'
export default {
name: 'App',
components: {
Son
},
setup () {
const count = ref(10)
return { count }
}
}
</script>
<template>
<div class="container">
<h2>子组件 {{modelValue}} <button @click="fn">改变数据</button></h2>
</div>
</template>
<script>
export default {
name: 'Son',
props: {
modelValue: {
type: Number,
default: 0
}
},
setup (props, {emit}) {
const fn = () => {
// 改变数据
emit('update:modelValue', 100)
}
return { fn }
}
}
</script>
六、混入(mixins语法)
// 全局混入 全局mixin
// vue2.0 写法 Vue.mixin({})
app.mixin({
methods: {
say () {
console.log(this.$el,'在mounted中调用say函数')
}
},
mounted () {
this.say()
}
})
<template>
<div class="container1">
<h1> 作者:周杰伦 <a href="javascript:;">关注</a> </h1>
<hr>
<Son />
</div>
</template>
<script>
import Son from './Son.vue'
export default {
name: 'App',
components: {
Son
}
}
</script>
<template>
<div class="container2">
<h2> 作者:周杰伦 <button>关注</button> </h2>
</div>
</template>
<script>
export default {
name: 'Son'
}
</script>
<style scoped lang="less"></style>
// 配置对象
export const followMixin = {
data () {
return {
loading: false
}
},
methods: {
followFn () {
this.loading = true
// 模拟请求
setTimeout(()=>{
// 省略请求代码
this.loading = false
},2000)
}
}
}
<template>
<div class="container1">
<h1> 作者:周杰伦 <a href="javascript:;" @click="followFn">{{loading?'请求中...':'关注'}}</a> </h1>
<hr>
<Son />
</div>
</template>
<script>
import Son from './Son.vue'
import {followMixin} from './mixins'
export default {
name: 'App',
components: {
Son
},
mixins: [followMixin]
}
</script>
<template>
<div class="container2">
<h2> 作者:周杰伦 <button @click="followFn">{{loading?'loading...':'关注'}}</button> </h2>
</div>
</template>
<script>
import {followMixin} from './mixins'
export default {
name: 'Son',
mixins: [followMixin]
}
</script>
<style scoped lang="less"></style>
- 在vue2.0中一些可复用的逻辑可以使用mixins来封装,当是需要考虑逻辑代码冲突问题。vue3.0的组合API很好的解决了这个问题,就不在推荐使用mixins了
七、自定义指令
- vue3中
directives:{
focus:{
mounted(el){
el.focus()
}
}
}
=======================>
app.directive('focus',{
mounted(el){ //使用指令的DOM是否创建好,钩子函数:mounted
el.focus()
},
updated(el){
el.focus()
}
})
- vue2中:
- 在vue2的项目中使用自定义指令时,【mounted ->inserted 】【updated -> update 】
Vue.directive('focus',{
inserted:function(el){
//获取元素焦点
el.focus();
}
})
======================>带参数
<input type="text" v-color='{color:"orange"}' />
Vue.directive('color',{
inserted:function(el,binding){ //使用指令的DOM是否创建好,钩子函数: inserted
//binding表示传递过来的参数
el.style.backgroundColor=binding.value.color;
}
})