一,全局挂载实例到vue全局
1,使用 app.config.globalProperties
比如经常使用的axios
import { createApp } from'vue'
import axios from'axios'
//引入echarts
import * as echarts from 'echarts';
const app = createApp()
app.config.globalProperties.$echarts = echarts;//挂载echarts
app.config.globalProperties.$axios = axios
app.mount('#root')
在组件中使用
1. 通过 getCurrentInstance 的 proxy 使用,不过 proxy 的 ts 类性中还有一个 undefined,所以使用 ts 时,类型就要自己处理
2. 通过 getCurrentInstance 的 appContext 使用,appContext获取的即为main.js里创建的的 vue 对象.
import { defineComponent, getCurrentInstance } from 'vue'
export default defineComponent({
name: 'Home',
setup() {
const { proxy } = getCurrentInstance();//获取公用方法proxy.$axios
const chartDom = <HTMLElement>document.getElementById("main");
const { $axios, $echarts } =proxy
//或者使用echat
const myChart = $echarts.init(chartDom);
console.log($axios)
// appContext 使用
const { $axios } = getCurrentInstance().appContext.config.globalProperties
console.log($axios)
}
})
2,通过 依赖和注入( provide 和 inject) 来完成(推荐)
import { createApp } from'vue'
import axios from'axios'
const app = createApp()
//注入axios
app.provide('$axios', axios)
app.mount('#root')
在组件中使用
import { defineComponent, inject } from 'vue'
export default defineComponent({
setup() {
// js
const $axios = inject('$axios')
console.log($axios)
}
})
VUE3 不推荐 app.config.globalProperties方式在原型链上挂载一些东西这种方式,而是更建议使用 的 provide 和 inject 方式
二,路由总结
1,对比vue2 和如何使用
vue3 使用路由的方式跟vue2 其实差不多,区别在于vue3 不在需要通过vue.use()方式 把路由挂载到vue上,
api方面也有所调整,通过createRouter来创建路由,再在mian.js中use一下
其次,路由方式也有所调整,我们需要在vue-router中导入 路由方式 createWebHashHistory 和 createWebHistory 然后再进行使用。直接看代码,进行比较
- vue2.xxx 使用路由
// router/index.js
import Vue from "vue";
import VueRouter from "vue-router";
Vue.use(VueRouter);
// 路由表
const routes = [
{
path: '/hot',
name: 'Hot',
component: () => import("@/views/hot"),
meta: {
title: '热门',
}
},
{
path: '/news',
name: 'News',
component: () => import("@/views/news"),
meta: {
title: '资讯',
},
},
]
const router = new VueRouter({
mode: "history",
routes,
});
export default router;
//main.js
import Vue from "vue";
import App from "./App.vue";
import router from "./router";
import store from "./store";
//全局的配置
//import './modules/config'
new Vue({
router,
store,
render: (h) => h(App),
}).$mount("#app");
- vue3.xx使用路由
// router/index.js
import { createRouter, createWebHistory } from "vue-router";
const routes = [
{ path: "/", redirect: "/watch" },
{ path: "/watch", name: "watch", component: () => import("../pages/watch") },
{
path: "/computer",
name: "computer",
component: () => import("../pages/computer")
},
{
path: "/component",
name: "component",
component: () => import("../pages/component")
},
{
path: "/setup",
name: "setup",
component: () => import("../pages/setup")
}
];
const router = createRouter({
history: createWebHistory(), //vue3 不在使用字符串方式 指定路由方式,需要通过引入vue-router中的方法去指定
routes: routes
});
export default router;
// main.js
import { createApp } from "vue";
import App from "./App.vue";
import router from "./router/index";
const app = createApp(App);
app.use(router);
app.mount("#app");
2,路由跳转方式及传参
vue2中我们知道,vue的路由跳转方式有通过router-link 直接跳转,或者通过编程式路由 进行跳转
vue3中其实差不多,只不过在使用编程式路由跳转的时候,我们不能再通过this.$router.xxx 的方式直接跳转,需要通过引入 useRouter 方式进行处理
我们先看一下 两种跳转的书写方式
<template>
<button>
<router-link
:to="{ path: '/computer', query: { name: '啥也不是,计算属性' } }"
>跳转计算属性</router-link
>
跳转计算属性页面
</button>
<button>
<router-link to="/setup">setup语法糖demo</router-link>
</button>
<button @click="toWatch">跳转监听器页面</button>
<button @click="toComponent">跳转组件传值</button>
<router-view />
</template>
<script>
import { useRouter } from "vue-router";
export default {
name: "App",
setup() {
const router = useRouter();
let toWatch = () => {
router.push({ path: "/watch", params: { name: "我来啦,监听器" } });
};
let toComponent = () => {
router.push({ path: "/component" });
};
return {
toWatch,
toComponent,
};
},
</script>
//组件中接收参数
<script>
import { useRoute } from "vue-router";
export default {
name: "",
components: {},
setup() {
const route = useRoute();
//获取params参数
const name = route.params.name;
//获取query参数
//let name = route.query.name;
return{
name
}
}
三,计算属性和监听器
1,计算属性
vue3中的计算属性 我们也需要通过引入的方式使用,与vue2不同的是,vue3的计算属性是通过定义变量后使用computed函数的方式进行获取值,如下代码:
<template>
<div>
{{ number }}
{{ newNumber }}
<button @click="changeQuery">点一下试试?</button>
</div>
</template>
<script>
import { ref, onMounted, toRefs, computed } from "vue";
export default {
name: "computer",
components: {
},
setup() {
onMounted(() => {
});
const number = ref(100);
let newNumber = computed(() => {
return number.value * 2;
});
const changeQuery = () => {
number.value += 100;
};
return {
number,
newNumber,
changeQuery,
};
},
methods: {},
};
</script>
2,监听器
我们都知道,vue的监听器是监听某个值的变化而执行的。vue3中使用watch的方式跟计算属性差不多。也是通过引入的方式去调用,看一下代码
<template>
<div>
<p>举个栗子</p>
<p>我是{{ character }}</p>
<p v-if="characters.length !== 0">
监听到被打,现在的情况是{{ characters }}
</p>
<button @click="hitClick">打他</button>
</div>
</template>
<script>
import { ref, onMounted, watch } from "vue";
export default {
name: "App",
components: {},
setup() {
const character = ref("帅哥");
const characters = ref("");
watch(character, (val) => {
characters.value = "好惨啊,变成了" + val;
});
const hitClick = () => {
character.value = "鼻青脸肿的人";
};
return {
characters,
character,
hitClick,
};
},
};
</script>
//watch 设置深度监听
// {
// immediate: true, // 立即执行
// deep: true // 深度监听
// }
如果使用reactive定义的变量,我们可以
import { watch, reactive,toRefs } from 'vue'
export default {
name: "App",
components: {},
setup() {
const state = reactive({
count: 1
})
// 监听count
watch(
() => state.count,
(newVal, oldVal) => {
console.log(state.count)
console.log(`watch监听变化前的数据:${oldVal}`)
console.log(`watch监听变化后的数据:${newVal}`)
},
{
immediate: true, // 立即执行
deep: true // 深度监听
}
)
return{
...toRefs(state)
}
}
}
四,组件传值
1,常用方式
vue遵循的是单向数据流模式,意思就是 数据从父组件传递到子组件,子组件只能使用而不能更改,如果需要更改,则需要通过订阅-发布的方式 告诉父组件,让父组件自行去修改值。
父子组件中传值,可以通过props的方式进行传递,子组件接收props需要在setup函数中接收props,如果需要使用emit方式通知父组件,需要接收多一个context上下文
如:
//父组件代码
<template>
<div>
<p ref="errorBox" />
<p>欢迎来到‘组件传值!’,来体验一下吧!</p>
<Children :money="money" @ask-money="gotMoneyChildren"></Children>
</div>
</template>
<script>
import Children from "../components/Children.vue";
import { ref, onMounted, reactive, toRefs } from "vue";
export default {
name: "App",
components: { Children },
setup() {
const errorBox = ref(null);
const data = reactive({
money: "",
});
onMounted(() => {
errorBox.value.innerHTML = "这里是组件传值";
});
const gotMoneyChildren = (val) => {
if (val.total_money) {
let total_money = Number(data.money);
let ask_money = Number(val.total_money);
data.money = total_money + ask_money;
} else {
errorBox.value.style = "color:red";
errorBox.value.innerHTML = "你到是说你要多少钱啊";
}
};
return {
gotMoneyChildren,
...toRefs(data),
errorBox,
};
},
};
</script>
//子组件代码
<template>
<div class="children-class">
<h3>
我是儿子:
<p v-if="money == 0 || money == ''">
俺爹没有给零花钱我,所以我身上有:0块钱
</p>
<p v-else>俺爹给零花钱我了,所以我身上有{{ money }}块钱</p>
<p>
爹,给俺<input
type="text"
v-model="total_money"
placeholder="可怜可怜孩子吧!爸"
/>块钱
</p>
<button @click="askFatherGotmoney">点击要钱</button>
</h3>
</div>
</template>
<script>
import { ref, onMounted } from "vue";
export default {
name: "Children",
props: {
money: {
type: Number,
default: 0,
},
},
setup(props, context) {
console.log(props.money,'父组件传递的money')
const total_money = ref("");
onMounted(() => {});
const askFatherGotmoney = () => {
context.emit("ask-money", { total_money: total_money.value });
};
return {
total_money,
askFatherGotmoney,
};
},
};
</script>
<style scoped>
.children-class {
color: #42b983;
}
</style>
2,setup 语法糖方式
setup语法糖是通过在script标签添加 setup属性 ,组件只需引入不用注册,属性和方法也不用返回,也不用写setup函数,也不用写export default ,甚至是自定义指令也可以在我们的template中自动获得。
ps:vue3版本需要在 "^3.2.6" 之上
这种写法会自动将所有顶级变量、函数,均会自动暴露给模板(template)使用**
**但是这里强调一句 “暴露给模板,跟暴露给外部不是一回事” 意思是 外部使用不了当前模板的变量,函数等等
下面介绍一下,再setup语法糖中 如何进行组件传值
- 简单传值和接收
//父组件 传值子组件
<template>
<child name='我是父组件传递过来的值'/>
</template>
<script setup>
// 引入子组件(组件自动注册)
import child from './child.vue'
</script>
由于没有setup函数,我们需要通过引入
defineProps 用来接收父组件传来的 props ; defineEmits 用来声明触发的事件。
defineEmits和defineProps在
<template>
<span>{{props.name}}</span>
<span>{{name}}</span>
<button @click='changeName'>更名</button>
</template>
<script setup>
import { defineEmits, defineProps } from 'vue'
// 声明props
const props = defineProps({
name: {
type: String,
default: ''
}
})
// 声明事件
const emit = defineEmits(['updateName'])
const changeName = () => {
// 执行
emit('updateName', 'Tom')
}
</script>
- 子组件通知父组件(修改值)
上面代码中,子组件引入了defineEmits 并定义了updateName为通知父组件 让其调用的方法,我们修改一下父组件,并监听一下子组件传递的方法
<template>
<child :name='state.name' @updateName='updateName'/>
</template>
<script setup>
import { reactive } from 'vue'
import child from './child.vue'
const state = reactive({
name: 'Jerry'
})
// 接收子组件触发的方法
const updateName = (name) => {
state.name = name
}
</script>
五,vue3中使用ref操作dom
1,常用方式
我们都知道,vue2中可以通过在节点中绑定ref属性,在代码中使用 this.$refs.xxx 方式操作dom,vue3中如何使用ref操作dom呢? 我们看一下代码
<template>
<p ref="errorBox" />
</template>
<script>
import { ref,nMounted } from "vue";
export default {
name: "",
components: {},
setup() {
const errorBox = ref(null);
onMounted(() => {
errorBox.value.innerHTML = "这里是监听器";
});
return {
errorBox
};
},
};
</script>
vue3中通过绑定节点属性ref='xxx' 的方式 在代码中,定义与绑定属性'xxx' 相同的名称的ref(ref可以为空,也可以为null) 然后通过return方式 返回出去。
2,setup语法糖方式
setup语法糖中没有setup函数,无法retuen返回出去,我们该怎么操作?
可以通过引入vue中的getCurrentInstance方式 进行使用,如:
<template>
<div>
<p>这里是setup语法糖,详情请看代码</p>
</div>
<p ref="errorBox" />
</template>
<script setup>
import { ref, onMounted, getCurrentInstance } from "vue";
let currentInstance = null;
onMounted(() => {
currentInstance = getCurrentInstance();
console.log(currentInstance, "xx");
currentInstance.refs.errorBox.innerHTML = "这里是setup语法糖";
});
</script>
注意一下:如果父组件没使用语法糖,而子组件使用了setup语法糖,我们知道,使用了语法糖的是不会对外暴露的
这时候,我们需要在子组件中使用 defineExpose 对外暴露属性,如
//父组件
<template>
<Childre ref="childre" />
</template>
<script lang="ts" setup>
import { ref } from "vue";
import Childre from "./Childre.vue";
const childre = ref('childre')
console.log('---childre---',childre)
</script>
//子组件
<template>
<div>你好,这里是{{ msg }}</div>
</template>
<script lang="ts" setup>
import { ref ,defineExpose} from "vue";
const msg = ref('子组件')
defineExpose({
msg
})
</script>
六,最后
使用setup语法糖有许多的便利,后续有完整的开发体验,在进行更新交流,另外
附上本文实例演示地址 跳转链接 setup语法糖不知道怎么回事,在codesandbox上无法正常显示,需要源代码的 可以添加我的微信:'ZT_9998051022'