vue 基础使用

176 阅读3分钟

一、前端环境搭建

参考地址:

blog.csdn.net/qq_42680327…

www.runoob.com/vue3/vue3-i…

image.png image.png image.png image.png

二、基础要点

2.1 setup 语法糖

2.1.1 使用前

setup内定义的变量和方法需要return才能使用

<script>
export default{
  setup(){
    const mes = "this is message"
    const loadMes = ()=>{
      console.log(mes)
    }
    console.log("set up ")
    return{
      mes,
      loadMes
    }
  },
  beforeCreate(){
    console.log("beforeCreate")
  }
}
</script>


<template>
  <div>
    {{ mes }}
    <button @click="loadMes">click me</button>
  </div>
</template>

2.1.2 使用后

不需要return就能试用变量或者方法了


<script setup>

    const mes = "this is message"
    const loadMes = ()=>{
      console.log(mes)
    }
    
</script>

<template>
  <div>
    {{ mes }}
    <button @click="loadMes">click me</button>
  </div>
</template>

2.2 响应式数据

2.2.1 reactive

<script setup>
// 1. 导入函数
import { reactive } from 'vue';
// 2. 执行函数,传入一个对象类型的参数,变量接受
const state = reactive({
  count : 0
})

const setCount = () =>{
  state.count++
}

</script> 

<template>
  <div>
    {{ count }}
    <button @click="setCount">{{ state.count }}</button>
  </div>
</template>

2.2.2 ref

<script setup>
// 1. 导入函数
import { ref } from 'vue';
// 2. 执行函数,传入参数【简单类型 + 对象类型】,变量接受
const count = ref(0)

const setCount = () =>{
  // 脚本区域修改ref产生的相应对象数据,必须通过.value属性
  count.value++
}
</script>

<template>
  <div>
    <button @click="setCount">{{ count }}</button>
  </div>
</template>

2.2.3 比较:reactive vs ref

  1. reactive 不能处理简单类型的数据
  2. ref参数类型支持更好但是必须通过.value访问修改
  3. ref内部的是实现依赖于reactive函数

2.3 计算属性

2.3.1 简单案例

从数组中筛选出数值大于2的元素,并在3秒后追加9,10到数组中


<script setup>
import { ref } from 'vue';
// 原始响应数组
const list = ref([1,2,3,4,5,6,7])

// 1.导入conputrd
import { computed } from 'vue';
// 2.执行函数,return计算之后的值,变量接受
const res = computed(()=>{
  return list.value.filter(item=>item>2)
})

setTimeout(()=>{
  list.value.push(9,10)
},3000)

</script>

<template>
 <div>原始响应数组{{ list }}</div>
 <div>计算后的数组为{{ res }}</div>
</template>

2.3.2 最佳实践

  1. 计算属性不应该有副作用(比如异步请求、修改dom)
  2. 避免直接修改计算属性的值(计算属性应该是只读的)

2.4 watch

2.4.1 元素监听

2.4.1.1 单个元素


<script setup>
// 1.导入watch
import { ref,watch } from 'vue';
const count = ref(0)

// 2.调用watch 监听变化
// ref不许要添加.value
watch(count,(newValue,oldValue) =>{
  console.log("count发生了变化",oldValue,newValue)
})

const setCount = ()=>{
  count.value++
}

</script>

<template>

  <button @click="setCount">+{{ count }}</button>

</template>
image.png

2.4.1.2 多个元素


<script setup>
// 1.导入watch
import { ref,watch } from 'vue';
const count = ref(0)
const name = ref("cp")

const setCount = ()=>{
  count.value++
}

const changName = () =>{
  name.value = "pc"
}

// 2.调用watch 监听变化
// ref需要添加.value
watch([count,name]
  ,(
    [newCount,newName],
    [oldCount,oldName]
    ) =>{
    console.log("count发生了变化",[newCount,newName], [oldCount,oldName])
})

</script>

<template>

  <button @click="setCount">+{{ count }}</button>
  <button @click="changName">+{{ name }}</button>

</template>
image.png

2.4.2 常用参数

2.4.2.1 immediate

在创建时立即触发回调

watch(count,(newValue,oldValue) =>{
  console.log("count发生了变化",oldValue,newValue)
},{
  immediate:true
})
image.png

2.4.2.2 deep

默认watch监听的ref对象默认是浅层监听的,

直接修改嵌套对象属性不会触发回调执行,需要开启deep属性

image.png
<script setup>

import { ref,watch } from 'vue';
const state = ref({count:0})

const setCount = ()=>{
  //直接修改count
 state.value.count++
}

watch(state,() =>{
  console.log("count发生了变化")
})



</script>

<template>

  <button @click="setCount">+{{ state.count }}</button>

</template>

添加 deep:true 后,直接修改对象的属性将会触发监听事件

image.png

2.4.2.3 精确监听

若有多个元素,只想深度监听其中某一个,可选择精确监听

只有点击 age 才会触发监听事件

watch(
  () => state.value.age,
  () => {
    console.log("数值变换了")
  }
)
image.png

2.5 生命周期

image.png

2.5.1 简单案例

** mounted**

若存在多个生命周期函数,则按照定义顺序执行

image.png

2.6 父子通信

2.6.1 父传子

2.6.1.1 基础案例

<script setup>
// set语法糖下局部组件无需注册直接可以使用
import son from "./Son.vue"

</script>

<template>
  <div class="father">
    <h2>父组件fa</h2>
    <son message="fa send message"></son>
  </div>

</template>

<script setup>
  
  const props = defineProps({
    message:String
  })

  console.log(props)

</script>

<template>
    <div class="son">
        <h3>子组件son</h3>
        <div>
            父组件传入的数据_{{message}}
        </div>

    </div>

</template>

页面

image.png image.png

2.6.1.2 传递响应式数据

image.png

2.6.2 子传父

<script setup>

import son from "./Son.vue"
import {ref} from "vue"

const get = (msg) =>{
  console.log(msg)
}


</script>

<template>
  <son @send-msg="get"></son>

</template>

<script setup>
  
  const emit = defineEmits(['sendMsg'])

  const send = ()=>{
    emit('sendMsg','this is son msg')
  }

</script>

<template>
   <button @click="send">send</button>
</template>
image.png

页面

image.png

2.6.3 总结

image.png

2.7 ref模板引用

2.7.1 基础用法

主页面

<script setup>
import test from "./Test.vue"
import {onMounted, ref} from "vue"
// 调用ref函数 -> ref 对象
const h1Ref = ref(null)
const testRef = ref(null)


// 组件挂载完毕后才能获取
onMounted(()=>{
  console.log(h1Ref.value)
  console.log(testRef.value)
})


</script>

<template>
 
   <h1 ref="h1Ref">我是h1</h1>
    <test ref="testRef"></test>
 
</template>

组件页面

<script setup>
import { ref } from 'vue';

  
  const name = ref("test name")
  const setName = ()=>{
    name.value = "test new name"
  }

  defineExpose({
    name,setName
  })

</script>

<template>
  <h3>我是test组件</h3>
</template>

页面

image.png

image.png

2.7.2 defineExpose

若想获取子组件的属性以及方法,可在子组件内使用defineExpose

image.png

image.png

2.8 provide 和 inject

  1. 顶层组件通过provide提供数据
  2. 底层组件通过inject组件获取数据

2.8.1 简单案例

top.vue

<script setup>
import {onMounted, provide, ref} from "vue"
import mid from "./Mid.vue"
// 顶层组件提供数据
provide("top","from top")

</script>

<template>
  <div class="top">
      顶层组件
      <mid></mid>
  </div>
 
</template>

<style scoped>
.top{
  margin-left: 20px;
}

</style>

mid.vue

<script setup>
  import baseOne from "./Base.vue"
</script>

<template>
   <div class="mid">
      中间组件
      <baseOne></baseOne>
  </div>
</template>

<style scoped>
.mid {
  margin-left: 40px;
}
</style>

base.vue

<script setup>
import { inject, ref } from 'vue';

  // 接受数据
  const fromTop = inject("top")

</script>

<template>
  <div class = "base">
    底层组件
    <div>
      来自顶层组件的数据为{{ fromTop }}
    </div>
    <div>
      来自顶层组件的响应式数据为
    </div>
  </div>
</template>

<style scoped>
.base{
  margin-left: 60px;
}

</style>

视图

image.png

image.png

2.8.2 传递响应式数据

image.png

2.8.3 跨层传递方法

image.png

2.8.4 总结

image.png

三、 进阶要点

3.1 Pinia

3.1.1 简单使用

3.1.1.1 依赖下载

控制台输入npm install pinia

image.png

3.1.1.2 注册pinia

import './assets/main.css'

import { createApp } from 'vue'
import App from './Top.vue'

// 1.导入createPinia
import { createPinia } from 'pinia'

// 2.执行方法得到实例
const pinia = createPinia()

// 把pinia 实例加入app应用中
createApp(App)
    .use(pinia)
    .mount('#app')

image.png

3.1.1.3 创建store

// 导入一个方法 defineStore
import {defineStore} from "pinia"
import { ref } from "vue"

export const  useCounterStore = defineStore('counter',()=>{
    // 定义数据(state)
    const count = ref(0)

    // 定义修改数据的方法(action 同步+异步)
    const inc = ()=>{
        count.value++ 
    }

    // 以对象的方式return
    return{
        count,
        inc
    }

})
image.png

3.1.1.4 调用Store

<script setup>
// 导入方法
import {useCounterStore} from "@/stores/counter"
// 执行方法得到的store实例对象
const counter = useCounterStore()
console.log(counter);

</script>

<template>
  <div>{{ counter.count }}</div>
  <button @click="counter.inc">click me</button>

</template>

点击按钮后可如期增长数字

image.png

3.1.2 getters 实现计算属性

image.png

image.png

3.1.3 action 实现异步

3.1.3.1 修改store

// 导入一个方法 defineStore
import {defineStore} from "pinia"
import { computed, ref } from "vue"
import axios from 'axios'

export const  useCounterStore = defineStore('counter',()=>{
    // 定义数据(state)
    const count = ref(0)

    // 定义修改数据的方法(action 同步+异步)
    const inc = ()=>{
        count.value++ 
    }

    // getter 定义 => 计算属性
    const doublueCount = computed(()=>count.value * 2)

    // 定义异步action
    const list =ref([])
    const getList = async () =>{
        const res = await axios.get("http://geek.itheima.net/v1_0/channels")
        list.value = res.data.data.channels
    }


    // 以对象的方式return
    return{
        count,
        inc,
        doublueCount,
        list,
        getList
    }

})
image.png

3.1.3.2 异步调用

<script setup>
// 导入方法
import {useCounterStore} from "@/stores/counter"
import { onMounted } from "vue";
// 执行方法得到的store实例对象
const counter = useCounterStore()
console.log(counter);

onMounted(()=>{
  counter.getList()
})

</script>

<template>
  
  <button @click="counter.inc">click me</button>

  <div>{{ counter.count }}</div>

  <div>{{ counter.doublueCount }}</div>

  <ul>
    <li v-for="item in counter.list" :key="item.id">
      {{ item.name }}
    </li>
  </ul>

</template>
image.png #### 3.1.3.3 调用结果 image.png

3.1.4 storeToRefs

3.1.4.1 解构数值

image.png

3.1.4.2 解构方法

image.png

3.1.5 调试

image.png

3.2 router

3.2.1 依赖下载

控制台输入npm install vue-router image.png

3.2.2 路由注册

main.js 中添加路由信息

image.png

3.2.3 编写路由

主页默认重定向到login页面,并定义login页面相关路由信息

image.png
import  { createRouter, createWebHashHistory } from "vue-router"
import Login from "../views/Login.vue"


// 定义路由
const routers = [{
    path:"/",
    redirect:"/Login"
},{
    path:"/Login",
    name:"Login",
    component:Login
}]

// 创建router实例
const router = createRouter({
    history:createWebHashHistory(),
    routes:routers
})

// 导出router实例
export default router

3.2.4 主页添加路由

image.png image.png