目录
2020.9 vue.js 发布3版本。 耗时2年多开发完毕。由尤雨溪团队打造。
1、性能提升
2、源码升级
3、新的特性
composition API(组合式api)
其他改变
- // 1. 确保你的vue-cli 脚手架版本在4.5.0以上,这样才能创建
- // 2. 检查脚手架版本 vue -V 或 vue --version
- // 3. 如果版本低话,重新安装vue-cli npm install -g @vue/cli
- // 4. vue create vue3-project
- // 5. cd vue3-project
- // 6. npm run serve 启动项目
-
vite模板搭建vue3项目
- npm init vue@latest
-
- // vue3 入口文件 main.js
- // 引入的不是Vue构造函数了,而是createApp 这个工厂函数(工厂函数就是返回值为一个对象的函数)
- import { createApp } from 'vue'
- import App from './App.vue'
- const app = createApp(App).mount('#app') // app 相当于vue2中的vm,但是比vm轻,里面绑定的属性和方法更少,而不是像vm那样用的不用的都绑上,显的有点重
-
-
- // vue2入口文件 main.js
- import Vue from 'vue'
- import App from './App.vue'
- const vm = new Vue({
- render: h => h(App),
- }).$mount('#app')
-
- // 比较
- // vue3 引入的是createApp 这个函数,而不是vue2中的的 Vue 构造函数啦。
- // vue3中的 app 类似于之前vue2中的vm, 但是app应用实例对象比vm 更轻,里面绑定的属性和方法更少
-
-
-
- <template>
- <img alt="Vue logo" src="./assets/logo.png">
- <HelloWorld msg="Welcome to Your Vue.js App"/>
- </template>
-
Composition API 也叫组合式api 主要包括如下及部分:
- <template>
- <div>
- <p>姓名:{{ name }}</p>
- <p>年龄:{{ age }}</p>
- <p @click="sayHello(10)">说话</p>
- </div>
- </template>
-
- <script>
- export default {
- name: "App",
- setup() { //为一个函数
- //定义变量
- let name = "张三";
- let age = 20;
- // 定义方法
- function sayHello(m) {
- alert(`${name}--${age}--${m}`);
- }
- return { //setup函数返回值为一个对象
- name,
- age,
- sayHello,
- };
- },
- };
- </script>
-
- <template>
- <div>
- <p>姓名:{{ name }}</p>
- <p>年龄:{{ age }}</p>
- <p @click="sayHello(10)">说话</p>
- <p>{{ height }}</p>
- </div>
- <!-- vue2.x中的事件 -->
- <div @click="test1">vue2中的事件test1</div>
- <!-- vue3中的事件 -->
- <div @click="test2">vue3中的事件test2</div>
- </template>
-
- <script>
- export default {
- name: "App",
- data() {
- return {
- sex: "男", // vue2中的变量
- height: 186, // vue2中的变量
- };
- },
- methods: {
- test1() {
- console.log(this.name); // "张三"
- console.log(this.age); // 20;
- console.log(this.sayHello); // 函数
- console.log(this.sex); // 男
- },
- },
- setup() {
- let name = "张三";
- let age = 20;
- let height = 176; // setup中的变量
- function sayHello(m) {
- alert(`${name}--${age}--${m}`);
- }
- function test2() {
- console.log(this.name); // "张三
- console.log(this.sayHello); // 函数
- console.log(this.sex); // undefined vue3中的setup 访问不了vue2中数据
- console.log(this.test1);// undefined vue3中的setup 访问不了vue2中方法
- }
- return {
- name,
- age,
- sayHello,
- test2,
- height,// setup中的变量
- };
- },
- };
-
1、 setup 在beforeCreate之前执行,且setup中获取不到this this为undefined
- beforeCreate() {
- console.log("beforeCreate");
- console.log(this); // proxy 实例对象
- },
- setup() {
- console.log("setup");
- console.log(this); // undefined
- }
-
如下代码:当点击执行changeFn函数,修改setup中定义的变量时,发现页面中的name和age的数据并没有修改,说明该数据不是响应式数据
- <template>
- <div>111</div>
- <p>{{ name }}--{{ age }}</p>
- <button @click="changeFn">changeFn</button>
- </template>
-
- <script>
- export default {
- name: "App",
- setup() {
- //定义变量
- let name = "张三";
- let age = 20;
- // 定义方法
- function changeFn() {
- name = "李四";
- age = 30;
- }
- return {
- //setup函数返回值为一个对象
- name,
- age,
- changeFn,
- };
- },
- };
- </script>
-
- <script>
- import { ref } from "vue"; // 引入响应式函数ref
- ...
- </script>
-
这里根据大佬的反馈有点小问题哈,
点击如下change事件,修改name 和age
- <template>
- <div>
- <!--name这个ref 引用对象在使用时不需要加value,vue3会自动帮你加value,所以可以拿到值-->
- <p>{{ name }}--{{ age }}</p>
- <p>{{ job.type }}--{{job.salary}}</p>
- <p @click="change">说话</p>
- </div>
- </template>
- <script>
- import { ref } from "vue"; // 引入响应式函数ref
- export default {
- name: "App",
- setup() {
- let name = ref("张三"); //返回一个 ref 引用对象
- let age = ref(20);
- console.log(name)
- // 当ref传的参数为对象时
- let job = ref({
- type: "前端工程师",
- salary: "20k",
- });
- function change() {
- name.value = "李四"; // ref对象.value 修改其值
- age.value = 30;
- job.value.type = "后端开发工程师";
- job.value.salary = "30k";
- }
- return {
- name,
- age,
- change,
- job
- };
- },
- };
- </script>
-
1、定义一个对象类型的响应式数据,返回一个Proxy 实例对象,不能用于基本数据类型,否则报错。(基本类型响应式数据使用ref)。
语法:const 代理对象= reactive(源对象) ,接收一个对象或数组,返回一个代理对象(即Proxy源对象)
- <script>
- import { reactive } from "vue";
- ...
- </script>
-
- <template>
- <p>{{ job.type }} --{{ job.salary }}--{{ job.like.a.b }}--{{job.content}}</p>
- <p v-for="(item, index) in foodArr" :key="index">{{ item }}</p>
- <button @click="changeFn">changeFn</button>
- </template>
-
- <script>
- import { reactive } from "vue";
- export default {
- name: "App",
- components: {},
- setup() {
- //定义对象
- let job = reactive({
- type: "前端工程师",
- salary: "20k",
- like:{
- a:{
- b:'不告诉你'
- }
- }
- });
- console.log(job);
- //定义数组
- let foodArr = reactive(["刷抖音", "敲代码"]);
- console.log(foodArr);
- // 定义方法
- function changeFn() {
- job.type = "后端开发工程师";
- job.salary = "30k";
- job.content = "写代码"; // 给对象添加属性
- foodArr[0]='买包包' // 通过下标修改数组
- }
- return {
- //setup函数返回值为一个对象
- job,
- changeFn,
- foodArr
- };
- },
- };
- </script>
-
- let data = {
- name: "张三",
- age: 30
- }
- let p = {}
- Object.defineProperty(p, 'name', {
- get() {
- console.log('访问了name属性');
- return data.name
- },
- set(val) {
- console.log('设置name属性');
- data.name = val
- }
- })
-
- //如上存在2个问题:
- // 无法添加和删除属性
- // 无法捕获到修改数组下标改变对应数组
-
-
-
- <template>
- <div id="app">
- <p>{{ person.name }}</p>
- <p>{{ person.age }}</p>
- <p v-if="person.sex">{{ person.sex }}</p>
- <button @click="addSex">添加属性</button>
- <button @click="deleteAge">删除属性</button>
- </div>
- </template>
- <script>
- import Vue from "vue";
- export default {
- name: "App",
- data() {
- return {
- person: {
- name: "张三",
- age: 20,
- },
- };
- },
- components: {},
- methods: {
- addSex() {
- // this.person.sex = "男";
- // console.log(this.person); // 数据被修改,但是vue监测不到
- // this.$set(this.person, "sex", "男"); // 修改为第一种方式,vue可以检测到
- Vue.set(this.person, "sex", "男"); // 修改为第二种方式,vue也可以检测到
- console.log(this.person);
- },
- deleteAge() {
- // delete this.person.age; // age被删除改,但是vue监测不到
- this.$delete(this.person, "age"); // 修改为第一种方式,vue可以检测到
- Vue.delete(this.person, "age"); // 修改为第二种方式,vue可以检测到
- console.log(this.person);
- },
- },
- };
- </script>
-
- <div id="app">
- <p v-for="(item, index) in nameArr" :key="index">{{ item }}</p>
- <button @click="update">添加属性</button>
- </div>
- <script>
- import Vue from "vue";
- export default {
- name: "App",
- data() {
- return {
- nameArr: ["刘备", "关羽"],
- };
- },
- methods: {
- update() {
- // this.nameArr[0] = "张飞"; // 数据被修改了,但是vue 检测不到
- // this.nameArr.splice(0, 1, "张飞"); // 修改为第一种方式,数据可以被检测到
- // this.$set(this.nameArr, 0, "张飞"); // 修改为第二种方式,数据可以被检测到
- Vue.set(this.nameArr, 0, "张飞"); // 修改为第三种方式,数据可以被检测到
- console.log(this.nameArr);
- },
- },
- };
- </script>
-
1、首先看一下vue3是否还存在vue2.x 中的问题。
- <template>
- <div>
- <p>{{ person.name }}</p>
- <p>{{ person.age }}</p>
- <p>{{ person.sex }}</p>
- <button @click="addSex">添加属性</button>
- <button @click="deleteSex">删除属性</button>
- </div>
- </template>
-
- <script>
- import { reactive } from "vue";
- export default {
- name: "App",
- components: {},
- setup() {
- let person = reactive({
- name: "张三",
- age: 20,
- });
- console.log(person);
- //定义添加属性
- function addSex() {
- person.sex = "男";
- console.log(person);
- }
- // 定义删除属性
- function deleteSex() {
- delete person.sex;
- console.log(person);
- }
- return {
- person,
- addSex,
- deleteSex,
- };
- },
- };
- </script>
-
- <template>
- <div>
- <p v-for="(item, index) in person.like" :key="index">{{ item }}</p>
- <button @click="change">修改数组的值</button>
- </div>
- </template>
-
- <script>
- import { reactive } from "vue";
- export default {
- name: "App",
- components: {},
- setup() {
- let person = reactive({
- name: "张三",
- age: 20,
- like: ["打球", "敲代码"],
- });
- console.log(person); // proxy 实例对象
- function change() {
- person.like[0] = "打台球";
- }
- return {
- person,
- change,
- };
- },
- };
- </script>
-
-
2、vue3响应式原理
首先说一下Reflect的作用。
- // Reflect是window下的一个内置对象
- // 1. 使用reflect 访问数据
- let obj = {
- name: '张三',
- age: 20
- }
- console.log(Reflect.get(obj, 'name')); // 张三
- // 2.使用Reflect 修改数据
- Reflect.set(obj, 'age', 50)
- console.log(obj);
-
- //3.使用Reflect删除数据
- Reflect.deleteProperty(obj, 'name')
- console.log(obj);
-
vue3响应原理代码:
通过Proxy代理,拦截对象中任意属性的变化,包括属性的读取,修改、设置、删除。
通过Reflect 反射对被代理对象的属性进行操作。
- let data = {
- name: "张三",
- age: 30
- }
- console.log(Proxy);
- // 使用p 对象代理data, Proxy为window 下的内置代理函数
- let p = new Proxy(data, {
- // 读取属性
- get(target, propName) {
- // target 就是 data
- console.log(`读取p上个${propName}属性`);
- return Reflect.get(target, propName)
- },
- // 修改和设置属性
- set(target, propName, value) {
- // value 为赋的值
- console.log(`修改p的${propName}属性`);
- // target[propName] = value
- Reflect.set(target, propName, value)
-
- },
- //删除属性
- deleteProperty(target, propName) {
- console.log(`删除p上的${propName}属性`);
- // return delete target[propName]
- return Reflect.deleteProperty(target, propName)
- }
- })
-
1、数据定义角度对比:
2、原理角度对比:
3、从使用角度对比:
“组件关系:
父子 props、$panrent
子父 emit自定义事件 refs
兄弟 eventbus中央事件总线 vue3如果需要实现eventbus 安装第三方库mitt
跨层级 provider inject
组件状态共享工具: vuex pinia
- <!--父组件 -->
- <template>
- <p></p>
- <Testvue3 :tit="schoolName">
- <span>123</span>
- </Testvue3>
- </template>
-
- <script>
- import Testvue3 from "@/components/Testvue3";
- export default {
- name: "App",
- components: { Testvue3 },
- setup() {
- let schoolName = "青山"; // 定义要传给子组件的数据
- return {
- schoolName, // 要使用的变量抛出去,这样就可以在页面模板中使用该变量
- };
- },
- };
- </script>
-
- <!-- 子组件 -->
- <template>
- <p>{{ tit }}</p>
- <button>点击事件,子传父</button>
- </template>
-
- <script>
- export default {
- data() {
- return {};
- },
- props: ["tit"],
- setup(props) {
- // 参数props即为父组件传过来的参数
- console.log(props)
- return {
- //setup函数返回值为一个对象
- };
- },
- };
- </script>
-
- <!-- 子组件 -->
- <template>
- <p>{{ tit }}</p>
- <button @click="emit">点击事件,子传父</button>
- </template>
- <script>
- import { reactive } from "vue";
- export default {
- data() {
- return {};
- },
- emits: ["transfer"], // 在子组件中使用emits配置项,接收父组件给我绑定的自定义事件,用法类似于props, // 不加该配置项,控制台会提示警告
- setup(props, context) {
- console.log(11, props);
- console.log(22, context);
- // 定义方法
- function emit() {
- // 子传父 此处不用this,使用context上下文对象
- context.emit("transfer", 666);
- }
- return {
- //setup函数返回值为一个对象
- emit,
- };
- },
- };
- </script>
-
- <!--父组件 -->
- <template>
- <p></p>
- <Testvue3 @transfer="showdata">
- <span>123</span>
- </Testvue3>
- </template>
- <script>
- import Testvue3 from "@/components/Testvue3";
- export default {
- name: "App",
- components: { Testvue3 },
- setup() {
- function showdata(value) {
- console.log(value);
- }
- return {
- showdata,
- };
- },
- };
- </script>
-
同vue2不同,使用计算属性需要引入computed 方法
- <template>
- <p>姓:<input type="text" v-model="data.firstname" /></p>
- <p>名:<input type="text" v-model="data.lastname" /></p>
- <p>姓名:<input type="text" v-model="data.fullname" /></p>
- </template>
-
- <script>
- // 引入对应的计算属性方法
- import { reactive, computed } from "vue";
- export default {
- name: "App",
- setup() {
- let data = reactive({
- firstname: "",
- lastname: "",
- fullname: "",
- });
- // 计算属性--简写
- // data.fullname = computed(() => {
- // return data.firstname + data.lastname;
- // });
- // 计算属性--完整写法
- data.fullname = computed({
- get() {
- return data.firstname + data.lastname;
- },
- set(value) {
- console.log(value);
- data.firstname = value.substr(0, 1);
- data.lastname = value.substr(1);
- },
- });
- return {
- data,
- };
- },
- };
- </script>
-
vue3 中的watch 也是 组合式api中的一个方法,所以使用时,需要引入
- <template>
- <p>{{ sum }} <button @click="sum++">sum++</button></p>
- <p>{{ fullname }} <button @click="fullname += '-'">修改姓名</button></p>
- <p>
- {{ userinfo.name }}--{{ userinfo.age }}--{{ userinfo.job.type }}--{{
- userinfo.job.salary
- }}K
- <button @click="userinfo.age++">修改年龄</button>
- <button @click="userinfo.job.salary++">修改薪水</button>
- </p>
- </template>
- <script>
- // 引入对应的计算属性方法
- import { ref, watch, reactive } from "vue";
- export default {
- name: "App",
- setup() {
- let sum = ref(0);
- let fullname = ref("张三");
- let userinfo = reactive({
- name: "李四",
- age: 20,
- job: {
- type: "web开发",
- salary: 20,
- },
- });
- //1、监听ref定义的响应式数据 immediate初始化就执行watch
- watch(sum, (newvalue, oldvalue) => {
- console.log(newvalue, oldvalue);
- },{immediate:true});
-
- //2、 监听ref定义的多个响应式数据,immediate初始化就执行watch
- watch([sum, fullname], (newvalue, oldvalue) => {
- console.log(newvalue, oldvalue);
- }, { immediate: true });
-
- //3、 监听reactive 定义的响应式数据
- // 注意:此处oldvalue 无效(新值与旧值一样),默认是深度监听,immediate初始化就执行watch
- watch(
- userinfo,
- (newvalue, oldvalue) => {
- console.log(newvalue, oldvalue);
- },
- { immediate: true });
-
- return {
- sum,
- fullname,
- userinfo,
- };
- },
- };
- </script>
-
“watch 和 watchEffect 都能响应式地执行有副作用的回调。它们之间的主要区别是追踪响应式依赖的方式:
- watch 只追踪明确侦听的数据源。它不会追踪任何在回调中访问到的东西。另外,仅在数据源确实改变时才会触发回调。watch 会避免在发生副作用时追踪依赖,因此,我们能更加精确地控制回调函数的触发时机。
- watchEffect,则会在副作用发生期间追踪依赖。它会在同步执行过程中,自动追踪所有能访问到的响应式属性。这更方便,而且代码往往更简洁,但有时其响应性依赖关系会不那么明确。
1、vue3中的生命周期钩子函数与vue2中基本相同,只有如下发生变化,其他都不变.
第一种方式:不使用组合式api的方式使用生命周期函数
- <!-- 子组件 -->
- <template>
- <p>{{ sum }} <button @click="sum++">sum++</button></p> <!--修改sum数据触发update生命周期 -->
- </template>
- <script>
- import { ref } from "vue";
- export default {
- setup() {
- let sum = ref(0);
- return {
- sum,
- };
- },
- beforeCreate() {
- console.log("beforeCreate");
- },
- created() {
- console.log("created");
- },
- beforeMount() {
- console.log("beforeMount");
- },
- mounted() {
- console.log("mounted");
- },
- beforeUpdate() {
- console.log("beforeUpdate"); //页面数据发生改变触发
- },
- updated() {
- console.log("updated"); //页面数据发生改变触发
- },
- beforeUnmount() {
- console.log("beforeUnmount"); //组件卸载前触发
- },
- unmounted() {
- console.log("unmounted"); //组件卸载后触发
- },
- };
- </script>
-
在app.vue 中引入子组件
- <template>
- <Testvue3 v-if="flag"></Testvue3>
- <button @click="flag = !flag">显示/隐藏</button> <!--修改flag 触发 beforeUnmount和 unmounted 生命周期-->
- </template>
- <script>
- import { ref } from "vue";
- import Testvue3 from "@/components/Testvue3";
- export default {
- name: "App",
- components: {
- Testvue3,
- },
- setup() {
- let flag = ref(true);// 修改flag
- return {
- flag,
- };
- },
- };
- </script>
-
- <!-- 子组件 -->
- <template>
- <p>{{ sum }} <button @click="sum++">sum++</button></p>
- </template>
- <script>
- //引入对应的生命周期钩子函数
- import {
- ref,
- onBeforeMount,
- onMounted,
- onBeforeUpdate,
- onUpdated,
- onBeforeUnmount,
- onUnmounted,
- } from "vue";
- export default {
- setup() {
- let sum = ref(0);
-
- onBeforeMount(() => {
- console.log("beforeMount");
- });
- onMounted(() => {
- console.log("mounted");
- });
- onBeforeUpdate(() => {
- console.log("beforeUpdate");
- });
- onUpdated(() => {
- console.log("updated");
- });
- onBeforeUnmount(() => {
- console.log("beforeUnmount");
- });
- onUnmounted(() => {
- console.log("unmounted");
- });
- return {
- sum,
- };
- },
- };
- </script>
-
hook函数定义:本质是一个函数,将setup中的公共逻辑抽离出来放在一个单独的js文件,这样哪个组件使用导入即可。
实现一个点击页面任意位置,在页面中输出当前点击位置的横纵坐标。
- <!-- 子组件 -->
- <template>
- <p>
- <span>鼠标点击位置的X坐标为:{{ point.x }}</span>
- <span>鼠标点击位置的Y坐标为:{{ point.y }}</span>
- </p>
- </template>
- <script>
- import { reactive, onMounted, onBeforeUnmount } from "vue";
- export default {
- setup() {
- let point = reactive({
- x: 0,
- y: 0,
- });
- onMounted(() => {
- document.onclick = function (event) {
- point.x = event.pageX;
- point.y = event.pageY;
- };
- });
- onBeforeUnmount(() => {
- document.onclick = null;
- });
-
- return {
- point,
- };
- },
- };
- </script>
-
- import { reactive, onMounted, onBeforeUnmount } from "vue";
- export function usePoint() {
- let point = reactive({
- x: 0,
- y: 0,
- });
- onMounted(() => {
- document.onclick = function (event) {
- point.x = event.pageX;
- point.y = event.pageY;
- };
- });
- onBeforeUnmount(() => {
- document.onclick = null;
- });
-
- return point // 最后抛出该point
- }
-
- <!-- 子组件 -->
- <template>
- <p>
- <span>鼠标点击位置的X坐标为:{{ point.x }}</span
- >,
- <span>鼠标点击位置的Y坐标为:{{ point.y }}</span>
- </p>
- </template>
- <script>
- // 在子组件中引入该hook方法
- import { usePoint } from "@/hooks/usepoint";
- export default {
- setup() {
- let point = usePoint();
- return {
- point,
- };
- },
- };
- </script>
-
定义:toRef 创建一个ref 响应数据
语法:let name = toRef(person,'name') 将响应对象person中的name属性单独拿出来变成响应属性。
应用:一般用于将响应对象中的某个属性单独提供给外部使用
- <!-- 子组件 -->
- <template>
- <div>
- <p>
- {{ person.name }} -- {{ person.age }} -- {{ person.job.type }} --
- {{ person.job.salary }}
- </p>
- </div>
- </template>
-
- <script>
- import { reactive } from "vue";
- export default {
- setup() {
- let person = reactive({
- name: "张三",
- age: 20,
- job: {
- type: "web前端开发",
- salary: 30,
- },
- });
- return {
- person,
- };
- },
- };
- </script>
-
- <!-- 子组件 -->
- <template>
- <div>
- <p>
- <!-- 在模板中直接使用name,age,type,salary -->
- {{ name }} -- {{ age }} -- {{ type }} --
- {{ salary }}
- </p>
- <p>
- <button @click="name += '-'">修改name</button>
- <button @click="salary++">修改薪水</button>
- </p>
- </div>
- </template>
-
- <script>
- import { reactive, toRef } from "vue";
- export default {
- setup() {
- let person = reactive({
- name: "张三",
- age: 20,
- job: {
- type: "web前端开发",
- salary: 30,
- },
- });
-
- // 将person 中的name 属性转换成ref 响应式数据,这样就可以直接在模板中使用了,以此类推
- let name = toRef(person, "name");
- let age = toRef(person, "age");
- let type = toRef(person.job, "type");
- let salary = toRef(person.job, "salary");
- return {
- name,
- age,
- type,
- salary,
- };
- },
- };
- </script>
- <style scoped>
- /* @import url(); 引入css类 */
- </style>
-
- <!-- 子组件 -->
- <template>
- <div>
- <p>
- {{ name }} -- {{ age }} -- {{ job.type }} --
- {{ job.salary }}
- </p>
- <p>
- <button @click="name += '-'">修改name</button>
- <button @click="job.salary++">修改薪水</button>
- </p>
- </div>
- </template>
-
- <script>
- import { reactive, toRefs } from "vue";
- export default {
- setup() {
- let person = reactive({
- name: "张三",
- age: 20,
- job: {
- type: "web前端开发",
- salary: 30,
- },
- });
- //toRefs返回一个响应对象,该对象中每个属性都变成了响应属性了。这样就可以直接拿来在模板插值表达式中使用了
- let person1 = toRefs(person);
- // console.log(person1);
- return {
- ...person1, // 使用后扩展运算符展开对象
- };
- },
- };
- </script>
- <style scoped>
- /* @import url(); 引入css类 */
- </style>
-
“关于数据响应式设置的问题:
1、如何设置一个响应式数据? ref reactive
2、如何将非响应式数据转为响应式数据? toRef toRefs
3、如何将数据设置为只读数据?不能够修改 readOnly
1、首先下载安装vue3 对应的vue-router
- npm install vue-router@4
-
2、在src目录下新建router目录,在该目录下新建index.js 文件,代码如下
- //1. 从vue-router 引入对应的方法createRouter 和 createWebHashHistory
- import { createRouter, createWebHashHistory } from "vue-router";
- //2.配置路由规则
- const routes = [
- { path: '/home', component: () => import('@/views/Home') },
- { path: '/category', component: () => import('@/views/Category') },
- ]
- //3.创建路由对象
- const router = createRouter({
- // 4. Provide the history implementation to use. We are using the hash history for simplicity here.
- history: createWebHashHistory(),
- routes, // short for `routes: routes`
- })
-
- export default router
-
3、在main.js 中引入并绑定
- // 引入路由
- import router from '@/router'
- // 在全局实例上挂载router,这样每个页面都可以访问路由
- createApp(App).use(store).use(router).mount('#app')
-
路由参数获取
- <template>
- <div>
- 新闻页
- </div>
- </template>
-
- <script lang="ts">
- import { defineComponent } from 'vue'
- import { useRoute } from 'vue-router';
- export default defineComponent({
- setup() {
- // useRoute获取路由参数
- const route = useRoute()
- console.log(route);
- console.log(route.query.id);
- return {}
- }
- })
- </script>
-
- <style scoped></style>
-
路由方法使用
- <template>
- <div>
- Index首页
- <!-- <button @click="$router.push('/news')">新闻</button> -->
- <button @click="goNews">新闻</button>
- </div>
- </template>
-
- <script lang="ts">
- import { defineComponent } from 'vue'
- // 导入路由相关的组合式函数hook use开头的函数
- import { useRouter } from 'vue-router'
- export default defineComponent({
- setup() {
- // 组合式函数必须先调用一次
- // useRouter 获取路由操作方法
- const router = useRouter()
- const goNews = () => {
- // this.$router.push()
- // console.log(router);
- router.push('/news')
- }
- return { goNews }
- }
- })
- </script>
-
- <style scoped></style>
-
1、首先需要安装vuex
- npm install vuex@next --save
-
2、在src目录下创建store 文件夹,该目录下创建index.js文件,代码如下:
- import { createStore } from 'vuex'
- // console.log(createStore);
- export default createStore({
- state: {
- count: 100
- },
- getters: {
- getCount(state) {
- return state.count * 2
- }
- },
- mutations: {
- setTestA(state, value) {
- state.count = value
- }
- },
- actions: {
- },
- modules: {
-
- }
- })
-
-
3、在main.js 引入然后使用挂载
- import { createApp } from 'vue'
- import App from './App.vue'
- // 引入 store
- import store from '@/store'
- console.log(store);
- // 挂载使用 这样全局就可以使用store了
- createApp(App).use(store).mount('#app')
- // console.log(createApp(App));
-
-
4.在页面组件中使用store
- <!-- 子组件 -->
- <template>
- {{ count }} ----{{ double }}
- <button @click="updateFun">修改数据</button>
- </template>
-
- <script>
- import { computed } from "vue";
- import { useStore } from "vuex";
- export default {
- setup() {
- const store = useStore();
- // 必须以计算属性形式输出,否则无法修改state中的数据 如count
- const count = computed(() => {
- return store.state.count;
- });
- const double = computed(() => {
- return store.getters.getCount;
- });
-
- const updateFun = () => {
- store.commit("setTestA", 20);
- };
- return {
- count,
- double,
- updateFun,
- };
- },
- };
- </script>
-
vue官方在使用vue3时,更加推荐使用Pinia状态管理。Pinia和vuex实际一个开发团队在维护。vuex最终版本是4,可以将Pinia看作是vuex5。
src\stores\counter.ts
- import { ref, computed } from 'vue'
- // defineStore store构造函数
- import { defineStore } from 'pinia'
-
- export const useCounterStore = defineStore('counter', () => {
- // 初始化state
- const count = ref(0)
- // 使用计算属性获取结果
- const doubleCount = computed(() => count.value * 2)
- // actions方法 修改state的操作方法
- function increment() {
- count.value++
- // console.log(count)
- }
-
- // 将需要外部使用到的值和方法按需导出
- return { count, doubleCount, increment }
- })
-
-
src\App.vue
- <template>
- <div>
- <button @click="increment"> {{ store.count }}</button>
- <div>{{ store.doubleCount }}</div>
- </div>
- </template>
-
- <script lang="ts">
- import { defineComponent, toRef } from 'vue'
- // 将usestore引入
- import { useCounterStore } from './stores/counter'
- export default defineComponent({
- setup() {
- // 调用store获取对象
- const store = useCounterStore()
- console.log(store);
- // 从store对象中获取state值和修改state的方法
- return { store, increment: store.increment }
- }
- })
- </script>
-
- <style scoped></style>
-