马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。
您需要 登录 才可以下载或查看,没有账号?立即注册
×
Vue2+Vue3 130~180集(Vue3)学习条记
一、create-vue搭建vue3项目
create-vue是vue官方新的脚手架工具,底层切换到了vite
步调:
- 检察环境条件
node -v版本必要在16.0及以上
- 创建一个vue应用
npm init vue@latest
这一指令会安装并实验create-vue
二、项目目次和关键文件
- index.html提供挂载点
- src/assets图片、样式文件的目次
- components封装的小组件
- App.vue中
template和script位置变更
template中允许有多个根元素
使用组件时不必要注册了,引入后直接就可以使用
- main.js
基于crate-vue创建实例
通过mount设置挂载点
三、组合式API
1、setup选项
- 实验机遇早于beforecreate
- setup函数中获取不到this(this是undefined的)
- 特点:可以提供数据也可以提供函数,但是都要return才气在模板中应用
怎样化简?<script setup>语法糖简化代码 只需界说不必要reture(语法糖主动帮我们reture)
2、reactive和ref函数
(1)reactive
作用:吸收对象范例数据的参数传入并返回一个相应式的对象
核心步调:
- 从vue包中导入reactive函数
- 在<script setup>中实验reactive函数并传入范例为对象的初始值,并使用变量吸收返回值
- <script setup>
- import {reactive} from 'vue'
- const state = reactive({
- count:100
- })
- </script>
复制代码 (2)ref
作用:吸收简朴范例大概对象范例的数据传入并返回一个相应式的对象
核心步调:
- 从vue包中导入ref函数
- 在<script setup>中实验ref函数并传入初始值,使用变量吸收ref函数的返回值
本质:是在原有传入数据的底子上,外层包了一层对象,包成了复杂数据范例,包成复杂范例之后再借助reactive实现的相应式,注意:脚本中访问简朴的数值数据,必要通过.value,在template模板中,不必要加.value
保举以后声明数据同一使用ref
3、computed(盘算属性)
核心步调:
- <script setup>
- import {computed} from 'vue'
- const computedState = computed(()=>{
- return 基于响应式数据做计算之后的值
- })
- </script>
复制代码 4、watch函数
作用:侦听一个或多个数据的变革,数据变革时实验回调函数
(1)侦听单个数据
- 导入watch函数
- 实验watch函数传入要侦听的相应式数据(ref对象)和回调函数
- <script setup>
- import {watch} from 'vue'
- const count = ref(0)
- watch(count,(newValue,oldValue)=>{
- console.log('count发生了变化')
- })
- </script>
复制代码 (2)侦听多个数据
- <script setup>
- import {watch} from 'vue'
- const count = ref(0)
- watch(
- [count,name],
- ([newCount,newName],[oldCount,oldName])=>{
- console.log('count发生了变化')
- }
- )
- </script>
复制代码 (3)immediate立刻实验
一进页面立刻实验一次- <script setup>
- import {watch} from 'vue'
- const count = ref(0)
- watch(count,(newValue,oldValue)=>{
- console.log('count发生了变化')
- },{
- immediate: true
- })
- </script>
复制代码 (4)deep深度监视
一进页面立刻实验一次- <script setup>
- import {watch} from 'vue'
- const count = ref(0)
- watch(count,(newValue,oldValue)=>{
- console.log('count发生了变化')
- },{
- deep: true
- })
- </script>
复制代码 默认watch是浅层监视,即
ref(简朴范例)可以直接监视,ref(复杂范例)监视不到复杂范例内部数据的变革 除非复杂范例的地点被修改
(5)准确侦听对象的某个属性
准确监听age属性- watch(()=>userInfo.value.age,(newValue,oldValue)=>{
- console.log(newValue,oldValue)
- })
复制代码 三、生命周期函数
四、父子通讯
(1)父传子
步调:1.在父组件中,以给子组件添加属性的方式传值 2.在子组件中,通过props吸收(借助编译器宏)
注意:子组件中script由于写了setup。以是无法直接设置props,必要通过编译器宏- const props = defineProps({
- car:String,
- money:Number
- })
复制代码 (2)子传父
步调:1.父组件中给子组件标签通过@绑定变乱 2.子组件内部通过emit方法触发变乱(借助编译宏)- //App.vue
- <script setup>
- import SonCom from '@/components/son-com.vue'
- import {ref} from 'vue'
- const money = ref(100)
- const getMoney=()=>{
- money.value+=10
- }
- const changeFn=(newMoney)=>{
- money.value=newMoney
- }
- </script>
- <template>
- <div>
- <h3>
- 父组件 - {{ money }}
- <button @click="getMoney">挣钱</button>
- </h3>
- <SonCom
- car="宝马车"
- :money="money" 父传子1.给子组件添加属性
- @changeMoney="changeFn"></SonCom> 子传父4.在父组件中通过@事件名监听
- </div>
- </template>
- <style scoped>
- </style>
- //son-com.vue
- <script setup>
- //由于写了setup,所以无法直接配置props选项
- //需要借助编译器宏,接收子组件传递的数据
- const props = defineProps({ 父传子2.通过编译器宏生成props方法
- car:String,
- money:Number
- })
- const emit = defineEmits(['changeMoney']) 子传父2.通过编译器宏生成emit方法
- console.log(props);
- const buy=()=>{ 子传父3.触发自定义事件,传递参数
- emit('changeMoney',5)
- }
- </script>
- <template>
- <!-- 对于props传递过来的数据,模板中可以直接使用 -->
- <div class="son">
- 我是子组件 - {{ car }} - {{ money }} 父传子3.模板中可以直接使用通过props传递过来的数据/props.xxx使用
- <button @click="buy">花钱</button> 子传父1.绑定自定义事件
- </div>
- </template>
- <style scoped>
- .son {
- border:1px solide black;
- padding:30px;
- }
- </style>
复制代码 五、模版引用
通过ref标识获取真实的dom对象大概组件实例对象
步调:
- 调用ref函数天生一个ref对象
- 通过ref标识绑定ref对象到标签
- 通过ref对象.value即可访问到绑定的元素(dom必须渲染完)
默认环境下<script setup>语法糖下组件内部的属性和方法是不开放给父组件访问的,可以通过defineExpose编译宏指定哪些属性和方法允许访问- //App.vue
- <script setup>
- import TestCom from '@/components/test-com.vue'
- import {onMounted,ref} from 'vue'
- // 模版引用(可以获取dom也可以获取组件)
- // 1.调用ref函数,生成一个ref对象
- // 2.通过ref标识,进行绑定
- // 3.通过ref对象.value即可访问到绑定的元素(必须渲染)
- const inp = ref(null)
- //生命周期钩子,作用是确保dom渲染完
- onMounted(()=>{
- // console.log(inp.value)
- // inp.value.focus()
- })
- const clickFn = () => {
- inp.value.focus()
- }
- const testRef = ref(null)//调用ref函数生成一个ref对象
- const getCom = () => {
- console.log(testRef.value.count)
- testRef.value.sayHi()
- }
- </script>
- <template>
- <div>
- <input ref='inp' type="text">
- <button @click="clickFn">点击让输入框聚焦</button>
- </div>
- <!-- 绑定ref对象到标签 -->
- <TestCom ref="testRef"></TestCom>
- <button @click='getCom'>获取组件</button>
- </template>
- <style scoped>
- </style>
- //test-com.vue
- <script setup>
- const count = 999
- const sayHi = () => {
- console.log('打招呼')
- }
- defineExpose({
- count,
- sayHi
- })
- </script>
- <template>
- <div>
- 我是用于测试的组件-{{ count }}
- </div>
- </template>
- <style scoped>
- </style>
复制代码 六、provide和inject
作用:顶层组件向恣意的底层组件通报数据和方法,实现跨层组件通讯
顶层组件通过provide提供数据,底层组件通过inject获取数据
传平凡数据步调:
- const message = inject('key')
复制代码 传相应式数据步调:
- const count = ref(1000)
- provide('count',count)
复制代码- const count = inject('count')
复制代码 跨层通报方法
顶层组件可以向底层组件通报方法,底层组件调用方法可向顶层组件传参或修改顶层组件中的数据- //App.vue
- const setCount=()=>{
- count.value++
- }
- provide('setCount-key',setCount)
- //bottom-com.vue
- const setCount=inject('setCount-key')
复制代码- //App.vue
- <script setup>
- import CenterCom from '@/components/center-com.vue'
- import { provide,ref } from 'vue'
- //1.跨层传递普通数据
- provide('theme-color','pink')
- //2.跨层传递响应式数据
- const count = ref(100)
- provide('count',count)
- setTimeout(() => {
- count.value=500
- }, 2000)
- //3.跨层级传递函数=>给子孙后代传递可以修改数据的方法
- provide('changeCount' , (newCount) => {
- count.value = newCount
- })
- </script>
- <template>
- <div>
- <h1>我是顶层组件</h1>
- <CenterCom></CenterCom>
- </div>
- </template>
- <style scoped>
- </style>
- //center-com.vue
- <script setup>
- import BottomCom from './bottom-com.vue'
- </script>
- <template>
- <div>
- <h2>我是中间层组件</h2>
- <BottomCom></BottomCom>
- </div>
- </template>
- <style scoped>
- </style>
- //bottom-com.vue
- <script setup>
- import {inject} from 'vue'
- const themeColor=inject('theme-color')
- const count=inject('count')
- const changeCount=inject('changeCount')
- const clickFn=()=>{
- changeCount(10000)
- }
- </script>
- <template>
- <div>
- <h3>我是底层组件-{{ themeColor }}-{{ count }}</h3>
- <button @click="clickFn">更新count</button>
- </div>
- </template>
- <style scoped>
- </style>
复制代码 七、新特性defineOptions宏
配景:有<script setup>之前,假如要界说props、emits可以添加一个与setup平级的属性,但有了<script setup>之后,setup属性没有了就没法添加与其平行的属性了。为相识决这一题目引入了defineProps和defineEmits两个宏办理了props和emits这两个属性,但是其他的属性并没有办理。
可以界说除props、emits、expose、slots之外的恣意选项(这几个属性已经存在对应的宏函数了)- <script setup>
- defineOptions({
- name:'xxx',
- inheritAttrs:false,
- ...其他更多自定义属性
- })
- </script>
复制代码 八、新特性defineModel
- <Child v-model=''>
- 等于
- <Child :modelValue='' @update:modelValue=''>
复制代码 原始写法:- //父
- const txt = ref('12345')
- <MyInput v-model='txt'></MyInput>
- //子
- <script setup>
- defineProps({
- modelValue:String
- })
- const emit = defineEmits(['update:modelValue'])
- </script>
- <template>
- <input
- type='text'
- :value="modelValue"
- @input="e=>emit('update:modelValue',e.target.value)"
- >
- </template>
复制代码 新版本写法:- //父
- const txt = ref('12345')
- <MyInput v-model='txt'></MyInput>
- //子
- <script setup>
- import { defineModel } from 'vue'
- const modelValue=defineModel()
- // modelValue.value可以直接修改
- </script>
-
- <input
- type='text'
- :value="modelValue"
- @input="e => modelValue = e.target.value"
- >
复制代码 见效必要设置 vite.config.js- import { fileURLToPath, URL } from 'node:url'
- import { defineConfig } from 'vite'
- import vue from '@vitejs/plugin-vue'
- // https://vitejs.dev/config/
- export default defineConfig({
- plugins: [
- vue({
- script: {
- defineModel: true
- }
- }),
- ],
- resolve: {
- alias: {
- '@': fileURLToPath(new URL('./src', import.meta.url))
- }
- }
- })
复制代码 九、Pinia
1、先容
Pinia是Vue的最新的状态管理工具,是Vuex的更换品
- 去掉了mutations(有state、actions(既支持同步也支持异步)、getters)
- 提供了符合组合式风格的API(和Vue3新语法同一)
- 去掉了moduls概念,每一个store都是一个独立的模块
- 共同TypeScript更友好
2、添加Pinia到Vue项目
npm create vue@latest
- import { createApp } from 'vue'
- import { createPinia } from 'pinia'
- import App from './App.vue'
- const pinia = createPinia()
- const app = createApp(App)
- app.use(pinia)
- app.mount('#app')
复制代码 3、Pinia根本语法
- //counter.js
- import {defineStore} from 'pinia'
- //定义store
- //defineStore(仓库的唯一标识,()=>{})
- export const useCounterStore = defineStore('counter',()=>{ 基于useCounterStore函数就可以使用defineStore仓库
- //声明数据 state-count
- const count = ref(0)
- //声明操作数据的方法action(普通函数)
- const addCount = () => count.value++
- //声明基于数据派生的计算属性getters(computed)
- const double = computed(()=>count.value*2)
- //声明数据 state-msg
- const msg = ref('hello pinia')
-
- return {
- count,
- addCount,
- double
- ...
- msg,
- }
- })
- //App.vue
- import {useCounterStore} from ''
- const counterStore = useCounterStore() //返回一个对象
- {{counterStore.count}}-{{counterStore.double}}
- <button @click="counterStore.addCount">+</button>
复制代码 4、action异步实现
- //channels.js
- import {defineStore} from 'pinia'
- export const useChannelStore = defineStore('channel',()=>{
- //声明数据
- const channelList = ref([])
- //声明操作数据的方法
- const getList = async=>{
- //支持异步(直接写异步请求)
- const {data:{data}}=await axios.get('')
- channelList.value = data.channels
- console.log(data.channels)
- }
- //声明getters相关
- return{
- channelList,
- getList
- }
- })
- //App.vue
- import {useChannelStore} from ''
- const channelStore = useChannelStore()
- <button @click='channelStore.getList'>获取频道数据</button>
- <ul>
- <li v-for='item in channelStore.channelList' :key='item.id'>{{item.name}}</li>
- </ul>
复制代码 5、Pinia-storeToRefs方法
不能直接对store举行解构,会丢失相应式,必要使用storeToRefs方法- import {storeToRefs} from 'Pinia'
- const {count,msg}=storeToRefs(counterStore)
- action可以直接解构
复制代码 6、Pinia恒久化
https://prazdevs.github.io/pinia-plugin-persistedstate/zh/guide/config.html
作用:操纵后会将设置了恒久化的数据存入当地,即革新页面后数据也不会重置
npm i pinia-plugin-persistedstate
- import { createPinia } from 'pinia'
- import piniaPluginPersistedstate from 'pinia-plugin-persistedstate'
- const pinia = createPinia()
- pinia.use(piniaPluginPersistedstate)
复制代码- import { defineStore } from 'pinia'
- import { ref } from 'vue'
- export const useStore = defineStore(
- 'main',
- () => {
- const someState = ref('hello pinia')
- return { someState }
- },
- //在声明并return完后进行配置
- {
- persist: true,
- },
- )
复制代码 指定state中哪些数据必要恒久化- import { defineStore } from 'pinia'
- export const useStore = defineStore('store', {
- state: () => ({
- save: {
- me: 'saved',
- notMe: 'not-saved',
- },
- saveMeToo: 'saved',
- }),
- persist: {
- pick: ['save.me', 'saveMeToo'],
- },
- })
复制代码 |