【vue3基础--重要】

vue3与vue2的区别

1.代码组织方式发生变化

vue2选项式api { data(){},methods:{},watch:{},computed… }
vue3组合式api

2.底层架构发生改变

vue3使用typescript实现,vue2底层使用js* ​

3.数据绑定发生变化

vue2 通过Object.defineProperty() 方式来监听
​vue3 通过Proxy

4.生命周期发生变化

vue3根据vue2生命周期取消了创建前后的生命周期 其他的生命周期+on前缀

全局变量

为了定义一些全局能用的公共变量或方法,可以将变量或方法注入给app.config.globalProperties
步骤1.main.js中定义定义全局属性或方法
app.config.globalProperties.msg = “hello, 我是全局的msg”;
步骤2.组件中通过下面的方法获取:
import { getCurrentInstance } from “vue”;
const { proxy } = getCurrentInstance();
proxy.全局变量或方法名

Vue3在原型上挂载方法

例如我们全局挂载axios

  1. yarn add axios -S 进行全局安装
  2. 在这里插入图片描述
    然后引入并挂载到原型上组件中
  3. import { getCurrentInstance } from "vue";
  4. const { proxy } = getCurrentInstance();// getCurrentInstance() 获取当前组件实例
    proxy.$axios.get("http://elm.cangdu.org/v1/cities?type=guess").then(res => { data.arr = res.data; });就能进行请求了

Vue的生命周期!

在这里插入图片描述

指的是组件实例从创建到销毁的过程,在不同的阶段做不同的事情
主要经常使用的有8个生命周期钩子函数(创建前后,挂载前后,更新前后,销毁前后)

在项目中我们一般在created创建后的钩子函数中进行数据请求,获取本地存储的数据、
在mounted挂载后的钩子函数中获取Dom元素、也可以通过在标签上添加ref属性来获取Dom元素 * vue内获取dom元素尽量使用ref;相当于class * 获取元素使用的是 this.$refs.divbox、(有时候也存在获取不到dom元素的情况,这个时候我们⼀般⽤$nextTick⽅法来解决)

另外三个钩子函数是在keep-alive使用的、

还有一个页面中我们有时候修改数据时,试图不更新我们可以用
this. s e t ( ) 方 法 来 进 行 更 新 。 t h i s . set()方法来进行更新。 this. set()this.set(需要修改的对象,属性,值)
还可以用 JSON.parse(JSON.stringify("数据”)) 方法来更新视图

Vue3使用监听属性

vue3有两个监听方式,第一种是watch方式

import { computed,watch } from "vue";

 watch(()=>one.flag,(newVal,oldVal)=>{
       one.list.forEach(item=>item.flag=newVal)
    },{
      immediate:true, //立即监听
      deep:true   //深度监听
    });

第二种是
watchEffect(()=>{console.log('watchEffect',num.value)})
watchEffect 是立即执行,watch不会,若想让watch执行一次开启immediate

Vue3使用计算属性

 const ones=computed(()=>{
        let num=0;
        one.list.forEach(item=>{
          if(item.flag){
            num+=item.minnum*item.price
          }
        })
        return num
      })

Vue3的setup

setup有两个参数,一个是props,一个是ctx
props是父子组件传值的数据存在props中,ctx我们一般使用里面的emit,进行子传父
setup还可以在script标签内<script setup></script>就不用return了。
如果这样写,props和ctx怎么获取呢?
setup script语法糖提供了三个新的API来供我们使用:definePropsdefineEmitsuseContext

  • defineProps 用来接收父组件传来的值props。

  • defineEmits 用来声明触发的事件表。

  • useContext 用来获取组件上下文context。


import { useContext, defineProps, defineEmits } from 'vue'
 // defineProps 用来接收父组件传来的值props。
 // defineEmits 用来声明触发的事件表。
 // useContext 用来获取组件上下文context。
const emit = defineEmits(['click'])
const ctx = useContext()
const props = defineProps({  // 可以拿到它的值
  msg: String,
})const sonClick = () => {
  emit('click', ctx)
}

Vue3的vuex

  • vuex是vue的状态(理解为数据)管理工具;主要实现个组件之间的数据共享

5个核心的概念

  • state – 存放状态(数据)

  • getters — 认为是计算属性 (可以对state内的数据进行处理)

  • mutations – 唯一一个更新state内的值的 方法

  • actions — 改变state值的方法;但是 一般 放置 异步的方法;并且需要调用mutations内的方法

  • modules – 模块 (同一类的或者说是 同一模块的单独放置)

获取值

  • state 内的值: $store.state.属性名
  • getters 内的值: $store.getters.属性名
  • mutations内的方法: $store.commit(‘vuex内mutations内的方法名’)
  • actions内的方法: $store.dispatch(‘vuex内actions内的方法名’)

辅助函数(四大金刚);作用就是说可以在页面内直接调用;因此需要映射到页面

  •  值的映射必须写在计算属性内
    
  • mapState,
  • mapGetters,
  • 方法的映射必须写在 methods内
  • mapMutations,
  • mapActions
  • 映射过之后,页面可以直接通过this调用
import { mapState, mapGetters, mapMutations, mapActions } from "vuex";
export default {
  name: "Home",
  // 值的映射必须写在 计算属性内
  computed: {
    ...mapState(["num", "msg"]),
    ...mapGetters({
      getNUmMsg: "getNUmMsg",
    }),
  },
  // 方法的映射必须写在 methods内
  mounted() {
    // 获取state内的值
    console.log(this.$store.state);
    console.log(this.$store.getters);
  },
  methods: {
    // 点击按钮的事件
    addHandle(num) {
      // 讲vuex内的num加1
      // this.$store.state.num++ // 错误的写法
      // this.$store.commit("addNum", num);

      // 辅助函数的写法
      this.addNum(num);
    },
    addActionsHAnldxe() {
      // 原始写法
      // this.$store.dispatch("changeNum");

      // 辅助函数的写法
      this.changeNum();
    },
    ...mapMutations(["addNum"]),
    ...mapActions({
      changeNum: "changeNum",
    }),
  },
};

路由跳转和传参

  • vue2内 使用

    • this.$router – 跳转 传参数
    • this.$route — 接收参数
  • vue3 内 组合api 使用 该如何使用路由呢

    • import {useRoute,useRouter} from ‘vue-router’
    • const route = useRoute – 接收的
    • const router = useRouter – 跳转 传参数
  • vue内的传参数 3 种: params query传参数 动态路由

      *  query 形式的传参数:
       	    * router.push('')
     	      * router.push({}) --------- 里边path或者name;query:{}传的参数
     	    * 刷新不会丢失
     		* 接收参数的时候: route.query
    
    • params传参数
      • router.push({name:‘’,params:{}})
      • name-- 只能使用路由名称
      • params–参数
      • 刷新页面,参数就会丢失
      • 获取参数的时候 router.params
  • 动态路由

    • router.push(‘/about?name=2104&age=9’)

vue router-link标签

在vue-router4.0之前,我们都是使用 tag 来自定义 router-link 渲染成什么标签

	<router-link to='/' tag="span">

在vue-router4.x 之后废弃了 tag 有了v-solt 概念

<router-link custom to="/catcan" v-slot="{ href,route,isActive,navigate,isExactActive}">
    <li @click="navigate">我是路由自定义标签</li>
</router-link>

// custom 属性的意思,就是允许自定义标签,如果不写就会定义成 a 标签
// href 就是解析后的 url
// route 就是解析后的规范的route对象
// navigate 导航的触发函数
// isActive 是否匹配的状态
// isExactActive 是否精准匹配的状态

vue3的组合式api

响应式api:
1.ref:定义单值时使用,通常用于定义基本类型值,例如:number,string,boolean,null,
2.reactive:定义复杂数据结构时使用
3.toRef:将reative对象中的某个属性转换成单个ref的形式
4.computed:计算属性,默认只能get,没有get,除非指定set,才能实现修改

 例如:
let fullName = computed({
  get() {
    return firstName.value + lastName.value;
  },
  set(v) {
    let arr1 = v.split("-");
    console.log("要修改的值:", arr1);
    firstName.value = arr1[0];
    lastName.value = arr1[1];
  },
});

5.nextTick:数据与视图不同步时,但想获取dom更新后的数据

//等绑定,或dom数据更新完才执行操作
nextTick(() => {
t.value.style.border = “1px solid #f00”;
});

5. watch:监听数据的改变

 //1.监听ref值变化
watch(
  firstName,
  (newV, oldV) => {
    console.log("新值:", newV);
    console.log("旧值:", oldV);
  },
  { deep: true }
);

//2.监听reactive值变化
watch(
  () => cartObj.num,
  (newV, oldV) => {
    console.log("新值:", newV);
    console.log("旧值:", oldV);
  },
  { deep: true }
);

watchEffect:

例如:
watchEffect(() => {
console.log(“cartObj.num:”, cartObj.num);
});

总结watcht watchEffect区别:
watch:只有数据改变时才触发
watchEffect:进入页面,可以访问时立即触发,同时数据改变时也会执行

vue3组件通讯

父传子

  • 用defineProps()来接收父级传过来的值
  • 代码演示:

父传:
在父组件的子组件标签上添加自定义属性:

<HelloWorld  msg="我传值了" title="今天天气挺好"></HelloWorld>

子接:
在子组件的js中通过defineProps接收

defineProps({
  msg: {
    //要接收的数据类型
    type: String,
    //必填项
    //required: true,
    //指定默认值
    default: "此处省略",
  },
  title: {
    type: String,
    default: "此处是标题",
  },
});

子传父

  • 跟vue2类似,也是事件监听派发机制

  • 演示代码:

子传:
1.声明要派发的事件
const emit = defineEmits(["go", "play"]);

2.触发事件
 HTML:
   <button @click="goParent">向父级传递数据</button>
   
  JS: 
   const news = "我是hello world组件一条新闻";

   const goParent = () => {
     emit("go", news);
   };

父接:

     <HelloWorld  @go="receive"></HelloWorld>
     
     JS:
     //在父组件中接收子组件传过来的值
       const receive = (v) => {
         title.value = v;
       };

兄弟之间

  • 借助公共组件当桥梁,子(B)传给公共组件A,A再将接收的值传给另一个组件C

  • 集中状态管理工具

    • vuex(vue2推荐)
    • pinia(vue3推荐)
  • 具体使用

    • 安装pinia
    • npm i pinia // “pinia”: “^2.0.14”
//解构pinia中的createPinia用于创建pinia实例
import { createPinia } from "pinia";
//实例化pinia
const store = createPinia();
//注册给app
app.use(store);

定义数据

import { defineStore } from "pinia";

export const userInfo = defineStore("userinfo", {
  //定义要管理的数据
  state: () => {
    return {
      userid: "1001111",
      username: "张三",
      age: 20,
      address: "北京",
    };
  },
  //要处理的业务逻辑方法
  actions: {},
  //通过state处理的计算属性
  getters: {},
});

在组件中使用数据

//引入定义的数据
import { userInfo } from "@/stores/userInfo";

//调用方法
const store = userInfo();

HTML:
<div>{{ store.username }}</div>
<div>{{ store.age }}</div>
<div>{{ store.address }}</div>
<div>共有{{ store.childsLen }}个孩子</div>
<div>count:{{ store.count }}</div>
<button @click="store.changeAge">改变年龄</button>

pinia数据持久化
npm i pinia-plugin-persistedstate
在main.js中引入

//解构pinia中的createPinia用于创建pinia实例

import { createPinia } from "pinia";
import piniaPluginPersistedstate from 'pinia-plugin-persistedstate'


//实例化pinia
const pinia = createPinia();

pinia.use(piniaPluginPersistedstate);

如何实现数据持久化

import { defineStore } from "pinia";

import { useCounterStore } from "./counter";

const useCounter = useCounterStore();

export const userInfo = defineStore("userinfo", {
  //数据持久化
  persist: true,
  //定义要管理的数据
  state: () => {
    return {
      count: useCounter.counter,
      userid: "1001111",
      username: "哈哈哈",
      age: 20,
      address: "北京",
      info: [
        { id: 1001, name: "jack", age: 20 },
        { id: 1002, name: "alice", age: 22 },
        { id: 1003, name: "hanmeimei", age: 18 },
        { id: 1004, name: "zhanglei", age: 19 },
      ],
    };
  },
  //要处理的业务逻辑方法
  actions: {
    changeAge() {
      this.age++;
    },
  },
  //通过state处理的计算属性
  getters: {
    childsLen(state) {
      return state.info.length;
    },
  },
});

如何改变本地存储的名称和改变存储的位置

import { defineStore } from "pinia";

import { useCounterStore } from "./counter";

const useCounter = useCounterStore();

export const userInfo = defineStore("userinfo", {
  //数据持久化
  persist: {
    key: "给一个要保存的名称",
    //保存的位置
    storage: window.sessionStorage,
  },
  //定义要管理的数据
  state: () => {
    return {
      count: useCounter.counter,
      userid: "1001111",
      username: "哈哈哈",
      age: 20,
      address: "北京",
      info: [
        { id: 1001, name: "jack", age: 20 },
        { id: 1002, name: "alice", age: 22 },
        { id: 1003, name: "hanmeimei", age: 18 },
        { id: 1004, name: "zhanglei", age: 19 },
      ],
    };
  },
  //要处理的业务逻辑方法
  actions: {
    changeAge() {
      this.age++;
    },
  },
  //通过state处理的计算属性
  getters: {
    childsLen(state) {
      return state.info.length;
    },
  },
});

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值