个人vue3-学习笔记

发布于:2025-02-10 ⋅ 阅读:(88) ⋅ 点赞:(0)

声明:这只是我个人的学习笔记(黑马),供以后复习用 。一天学一点,随时学随时更新。明天会更好的!

这里只给代码,不给运行结果,看不出来代码的作用我也该进厂了。。。。。

Day1 使用create-vue创建项目。 

1.检查版本。

node -v

2.创建项目

npm init vue@latest

可以用这个切回国内镜像源

npm config set registry https://registry.npmmirror.com

3. 安装依赖,启动项目

npm install
npm run dev

4.1写法

原始复杂写法setup写法:必须return

<!-- 开关:写组合式组件 -->
<script>
export default {
  setup() {
    console.log('setup')
    const message = 'hello world'
    const logMessage = () => {
      console.log(message)
    }
    return {//只有return返回一个对象,对象中的属性和方法,都可以在模板中使用
      message,
      logMessage,
    }
  },
  beforeCreate() {
    console.log('beforeCreate')
  },
}
</script>

<template>
  <!-- 不再要求唯一的根元素 -->
  <div>
    {
  
  { message }}
    <button @click="logMessage">log</button>
  </div>
</template>

<style scoped></style>

简单的语法糖写法

<script setup>
const message = 'hello world'
const logMessage = () => {
  console.log(message)
}
</script>
<template>
  <!-- 不再要求唯一的根元素 -->
  <div>
    {
  
  { message }}
    <button @click="logMessage">log</button>
  </div>
</template>

<style scoped></style>

注:1.setup选项在beforeCreate钩子之前自动执行 

        2.setup中的this不指向组件实例了,指向undefined

 

4.2 函数调用返回响应式数据

reactive()接受对象类型数据的参数传入并返回一个响应式的对象

<script setup>
// 1.导入函数
import { reactive } from 'vue'
//  2.执行函数 传入一个对象类型的函数 变量接受
const state = reactive({
  count: 0
})
const setCount = () => {
  state.count++
}
</script>
<template>
  <!-- 不再要求唯一的根元素 -->
  <div>
    <button @click='setCount'>
      {
  
  { state.count }}
    </button>
  </div>
</template>

<style scoped></style>

ref()接受简单类型或对象类型数据的参数传入并返回一个响应式的对象 

脚本区域修改ref的响应式数据 必须通过value属性

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

//1.导入ref 函数
import { ref } from 'vue'
//2.执行函数 传入一个简单类型或者对象类型的参数 变量接受
const count = ref(0)
console.log(count)

const setCount = () => {
  //脚本区域修改ref的响应式数据 必须通过value属性
  count.value++
}
</script>
<template>
  <!-- 不再要求唯一的根元素 -->
  <div>
    <button @click='setCount'>
      {
  
  { count }}
    </button>
  </div>
</template>

<style scoped></style>

4.3计算属性函数 

computed 返回计算后的数据(不应该有副作用)

<script setup>
// 1.导入computed
import { computed } from 'vue'
import { ref } from 'vue'
const list = ref([1, 2, 3, 4, 5, 6, 7, 8])

// 2.使用computed return计算后的值 变量接受
const computedList = computed(() => {
  return list.value.filter(item => item > 2)
})

setTimeout(() => {
  list.value.push(9, 10)
}, 3000);
</script>
<template>
  <!-- 不再要求唯一的根元素 -->
  <div>
    原始响应式数据-{
  
  { list }}
  </div>
  <div>
    计算后的响应式数据-{
  
  { computedList }}
  </div>
</template>

<style scoped></style>

 4.4watch函数 

侦听一个或多个数据的变化,数据变化时执行回调函数(参数:immediate(立即执行),deep(深度侦听))

<script setup>
// import {ref,watch} from 'vue'
// const count = ref(0)
// const setCount = () => {
//   count.value++
// }
// //调用watch方法,监听count的变化
// //watch 里面ref对象不需要加.value属性
// watch(count, (newValue, oldValue) => {
//   console.log(`count发生了变化,老值是${oldValue},新值是${newValue}`);
// })

import { ref, watch } from 'vue'
const count = ref(0)
const changeCount = () => {
  count.value++
}
const name = ref('cp')
const changeName = () => {
  name.value = 'pc'
}

watch(
  [count,name], 
  (
    [newValue,newName], [oldValue,oldName]
  ) => {
  console.log(`count或者name发生了变化,老值是${[oldValue,oldName]},新值是${[newValue,newName]}`);
})
</script>
<template>
  <!-- 不再要求唯一的根元素 -->
  <div>
    <button @click='changeCount'>修改{
  
  { count }}</button>
  </div>
  <div>
    <button @click='changeName'>修改{
  
  { name }}</button>
  </div>
</template>

<style scoped></style>

immediate先执行一次回调函数

<script setup>
import { ref, watch } from 'vue'
const count = ref(0)
const changeCount = () => {
  count.value++
}
const name = ref('cp')
const changeName = () => {
  name.value = 'pc'
}

watch(
  [count, name],
  (
    [newValue, newName], [oldValue, oldName]
  ) => {
    console.log(`count或者name发生了变化,老值是${[oldValue, oldName]},新值是${[newValue, newName]}`);
  }, {
  immediate: true//先执行一次回调函数
})
</script>
<template>
  <!-- 不再要求唯一的根元素 -->
  <div>
    <button @click='changeCount'>修改{
  
  { count }}</button>
  </div>
  <div>
    <button @click='changeName'>修改{
  
  { name }}</button>
  </div>
</template>

<style scoped></style>

deep:通过watch监听的ref对象默认是浅层侦听的,直接修改嵌套的对象属性不会触发回调执行,需要开启deep

<script setup>
import { ref, watch } from 'vue'
const state = ref({ count: 0, age: 20 })
const changeStateByCount = () => {
  state.value.count++
}
watch(state, () => {
  console.log('count变化了')
}, {
  deep: true//默认监听的整个对象,就是此时age变化,也执行
})

</script>
<template>
  <!-- 不再要求唯一的根元素 -->
  <div>
    <button @click='changeStateByCount'>通过修改</button>
  </div>
</template>

<style scoped></style>

精确监听

<script setup>
// import { ref, watch } from 'vue'
// const state = ref({ count: 0, age: 20 })
// const changeStateByCount = () => {
//   state.value.count++
// }
// watch(state, () => {
//   console.log('count变化了')
// }, {
//   deep: true//默认监听的整个对象,就是此时age变化,也执行
// })

import { ref, watch } from 'vue'
const state = ref({
  name: 'zhangsan',
  age: 20
})

const changeName = () => {
  state.value.name = 'lisi'
}

const changeAge = () => {
  state.value.age = 30
}

watch(
  () => state.value.age,
  () => {
    console.log('age变化了')
  })
//deep有性能损耗 尽量不开启
</script>
<template>
  <!-- 不再要求唯一的根元素 -->
  <div>
    <div> 当前age{
  
  { state.age }}</div>
    <div> 当前name{
  
  { state.name }}</div>
  </div>
  <div>
    <button @click='changeName'>修改name</button>
    <button @click='changeAge'>修改age</button>
  </div>

</template>

<style scoped></style>

———————————————————————————————————————————2025.1.16 0时05分 --困了睡觉吧。 

4.5生命周期函数

<script setup>
//生命周期函数的使用
import { onMounted } from 'vue'
onMounted(() => {
  console.log('组件挂载完成onMounted执行了1')
})
onMounted(() => {
  console.log('组件挂载完成onMounted执行了2')
})
</script>
<template>
  <!-- 不再要求唯一的根元素 -->
  <div>
    
  </div>
  

</template>

<style scoped></style>

4.6组合式API通信 

父传子

父组件

<script setup>
//语法糖下局部组件无需注册可以直接使用
import { ref } from 'vue'
import SonCom from './components/son-com.vue'
const count = ref(100)
setTimeout(() => {
  count.value = 200
}, 2000)
</script>
<template>
  <!-- 不再要求唯一的根元素 -->
  <div class='father'>
    <h2>父组件App</h2>
    <!-- 1.绑定属性 -->
    <SonCom :count="count" message='father-message' />
    <!-- //响应式数据加“:” -->
  </div>
</template>

<style scoped></style>

子组件

<script setup>
//2. 子组件接收数据 defineProps
const props=defineProps({
  message: String,
  count : Number
})
console.log(props)
</script>

<template>
  <div class='son'>
    <h3>子组件SON</h3>
    <div>
      父组件传入的数据-{
  
  { message }}-{
  
  { count }}
    </div>
  </div>
</template>

<style scoped>

</style>

子传父 

  父组件

<script setup>
import SonCom from './components/son-com.vue'
const getMessage = (msg) => {
  console.log(msg)
}
</script>
<template>
  <div class='father'>
    <h2>父组件App</h2>
    <!--1.绑定事件 -->
    <SonCom @get-message='getMessage'/>
  </div>
</template>

<style scoped></style>

子组件

<script setup>
//2.通过 defineEmits 定义一个自定义事件 ->emit(this.emit)
const emit = defineEmits(['get-message'])
const sendMsg = () => {
  emit('get-message', '我是son message')
}

</script>

<template>
  <div class='son'>
    <div>子组件SON</div>
    <button @click='sendMsg'>触发自定义事件</button>
  </div>
</template>

<style scoped>

</style>

4.6组合式API-模版引用 

父组件

<script setup>
import  TestCom from './components/TestCom.vue'
import { onMounted, ref } from 'vue'
//1.调用ref函数-> ref对象
const h1Ref = ref(null)
const comRef = ref(null)
//组件挂载完毕之后才能获取
onMounted(() => {
  console.log(h1Ref.value)
  console.log(comRef.value);
  
})
</script>
<template>
   <!-- 2.通过ref标识绑定ref对象 -->
  <h1 ref="h1Ref">我是dom标签h1</h1>
  <TestCom ref='comRef'/>
</template>

<style scoped></style>

子组件

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

const name = ref('testname')

const setName = () => {
  name.value = 'new testname'
}

defineExpose({//子组件的属性和方法通过 defineExpose暴露给父组件使用
  name,
  setName
})
</script>
<template>
  <div>test</div>
</template>

<style scoped></style>

4.7组合式API-provide和inject

顶层组件向任意的底层组件传递数据和方法,实现跨层组件通信 

顶层组件

<script setup>
import RoomMsgItem from './room-msgitem.vue'
import { provide ,ref } from 'vue'

//1.顶层组件提供数据
provide('data-key', '我是顶层组件提供的数据')

//传递响应式数据
const count = ref(0)
provide('count-key', count)
setTimeout(() => {
  count.value = 100
}, 2000)

//传递方法(谁的数据谁负责)
const setCount = () => {
  count.value++
}
provide('setCount-key', setCount)
</script>
<template>
  <!-- 组件嵌套关系 -->
    <!-- roompage->roommsgitem->roommsgcomment -->
    
  <div class='page'>
    顶层组件
    <RoomMsgItem />
  </div>
</template>

<style scoped></style>

中间组件

<script setup>
import RoomMsgComment from './room-msg-comment.vue'
</script>

<template>
  <div>
    中间组件
    <room-msg-comment/>
  </div>
</template>

<style scoped>

</style>

底层组件 

<script setup>
import { inject } from 'vue'
//2.接收数据
const roomDate=inject('data-key')
//接受顶层组件的响应式数据
const countData=inject('count-key')

//接收方法
const setCount=inject('setCount-key')
</script>
<template>
  <div class='comment'>
    底层组件
    <div>
      来自顶层组件的数据为:{
  
  { roomDate }}
    </div>
    <div>
      来自顶层组件的响应式数据:{
  
  { countData }}
    </div>
    <button @click='setCount'>修改顶层组件的数据{
  
  { countData }}</button>
  </div>
</template>

<style scoped></style>

5.案例演示 

 App.vue

<script setup>
import { onMounted,ref } from 'vue'
import Edit from './components/Edit.vue'
import axios from 'axios'
// TODO: 列表渲染
//思路:声明响应式数据list->调用接口获取数据->后端数据赋值给list ->绑定到table组件

const list = ref([])
 const getList = async () => {
  //接口调用
  const res=await axios.get('/list')//都是mock的假数据,后端没有完成的话,就可以这样
  list.value=res.data
}

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

// TODO: 删除功能
//思路:获取当前行的id->调用接口->更新数据->重新渲染

const onDelete = async (id) =>{
  console.log(id);
  await axios.delete(`/del/${id}`)
  getList()
}
// TODO: 新增功能

// TODO: 编辑功能

</script>

<template>
  <div class="app">
    <el-table :data="list">
      <el-table-column label="ID" prop="id"></el-table-column>
      <el-table-column label="姓名" prop="name" width="150"></el-table-column>
      <el-table-column label="籍贯" prop="place"></el-table-column>
      <el-table-column label="操作" width="150">
        <template #default="{row}">
          <el-button type="primary" link>编辑</el-button>
          <el-button type="danger" @click="onDelete(row.id)" link>删除</el-button>
        </template>
      </el-table-column>
    </el-table>
  </div>
  <Edit />
</template>

<style scoped>
.app {
  width: 980px;
  margin: 100px auto 0;
}
</style>

Edit.vue

<script setup>
// TODO: 编辑
import { ref } from 'vue'
// 弹框开关
const dialogVisible = ref(false)


</script>

<template>
  <el-dialog v-model="dialogVisible" title="编辑" width="400px">
    <el-form label-width="50px">
      <el-form-item label="姓名">
        <el-input placeholder="请输入姓名" />
      </el-form-item>
      <el-form-item label="籍贯">
        <el-input placeholder="请输入籍贯" />
      </el-form-item>
    </el-form>
    <template #footer>
      <span class="dialog-footer">
        <el-button @click="dialogVisible = false">取消</el-button>
        <el-button type="primary" @click="dialogVisible = false">确认</el-button>
      </span>
    </template>
  </el-dialog>
</template>

<style scoped>
.el-input {
  width: 290px;
}
</style>

mock的假数据

import Mock from "mockjs"
// 内存模拟数据
const arr = []
for (let i = 0; i < 10; i++) {
  arr.push({
    id: Mock.mock("@id"),
    name: Mock.mock("@cname"),
    place: Mock.mock("@county(true)"),
  })
}
export default [
  {
    url: "/list",
    method: "get",
    response: () => {
      return arr
    },
  },
  {
    url: "/del/:id",
    method: "delete",
    response: (req) => {
      const index = arr.findIndex((item) => item.id === req.query.id)
      if (index > -1) {
        arr.splice(index, 1)
        return { success: true }
      } else {
        return { success: false }
      }
    },
  },
  {
    url: "/edit/:id",
    method: "patch",
    response: ({ query, body }) => {
      const item = arr.find((item) => item.id === query.id)
      if (item) {
        item.name = body.name
        item.place = body.place
        return { success: true }
      } else {
        return { success: false }
      }
    },
  },
]

新增和编辑功能就不写了 

 

Day 2 pinia和项目起步 

1.1添加pinia到项目 

import './assets/main.css'

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

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

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

//3.把pinia 实例加入到app应用中

createApp(App).use(pinia).mount('#app')

定义store

// stores/counter.js
import { defineStore } from 'pinia'

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

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

使用

<script setup>
// 1.导入use 打头的方法
import {useCounterStore} from '@/stores/counter'
//2.执行方法得到store实例对象
const counterStore = useCounterStore()
console.log(counterStore)
</script>

<template>
  <div>

  </div>
  <button @click='counterStore.increment'>{
  
  { counterStore.count }}</button>
</template>

<style scoped>
</style>

1.2getter 计算属性

 counter.js

// stores/counter.js
import { ref } from 'vue'
import { defineStore } from 'pinia'
import { computed } from 'vue' 

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

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

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

  return {
     count, 
     increment, 
     doubleCount 
    }
})

App.vue

<script setup>
// 1.导入use 打头的方法
import { useCounterStore } from '@/stores/counter'
//2.执行方法得到store实例对象
const counterStore = useCounterStore()
console.log(counterStore)
</script>

<template>
  <div>
    {
  
  { counterStore.doubleCount }}
  </div>
  <button @click='counterStore.increment'>{
  
  { counterStore.count }}</button>

</template>

<style scoped></style>

1.3action异步 

 App.vue

<script setup>
// 1.导入use 打头的方法
import { onMounted } from 'vue'
import { useCounterStore } from '@/stores/counter'

//2.执行方法得到store实例对象
const counterStore = useCounterStore()
console.log(counterStore)

onMounted(() => {
 counterStore.getList()
})
</script>

<template>
  <div>
    {
  
  { counterStore.doubleCount }}
  </div>
  <button @click='counterStore.increment'>{
  
  { counterStore.count }}</button>
  <ul>
    <li v-for='item in counterStore.list' :key='item.id'>{
  
  { item.name }}</li>

  </ul>
</template>

<style scoped></style>

counter.js

// stores/counter.js
import { ref } from 'vue'
import { defineStore } from 'pinia'
import { computed } from 'vue'
import  axios  from 'axios'

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

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

  //getter定义计算属性
  const doubleCount = 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 {
    count,
    increment,
    doubleCount,
    list,
    getList
  }
})

1.4storeToRefs和调试 

直接解构赋值(响应式丢失)

<script setup>
// 1.导入use 打头的方法
import { onMounted } from 'vue'
import { useCounterStore } from '@/stores/counter'

//2.执行方法得到store实例对象
const counterStore = useCounterStore()
console.log(counterStore)

//直接解构赋值(响应式丢失)
const{ doubleCount, increment, list ,count }=counterStore

// 触发action
onMounted(() => {
 counterStore.getList()
})
</script>

<template>
  <div>
    {
  
  { doubleCount }}
  </div>
  <button @click='counterStore.increment'>-{
  
  { count }}</button>
  <ul>
    <li v-for='item in counterStore.list' :key='item.id'>{
  
  { item.name }}</li>

  </ul>
</template>

<style scoped></style>

保持数据响应式

<script setup>
// 1.导入use 打头的方法
import { onMounted } from 'vue'
import { useCounterStore } from '@/stores/counter'
import {storeToRefs} from 'pinia'

//2.执行方法得到store实例对象
const counterStore = useCounterStore()
console.log(counterStore)

//直接解构赋值(响应式丢失)
// const{ doubleCount, increment, list ,count }=counterStore

//方法包裹(保持响应式)
const{ doubleCount, increment, list ,count }=storeToRefs(counterStore)


// 触发action
onMounted(() => {
 counterStore.getList()
})
</script>

<template>
  <div>
    {
  
  { doubleCount }}
  </div>
  <button @click='counterStore.increment'>-{
  
  { count }}</button>
  <ul>
    <li v-for='item in counterStore.list' :key='item.id'>{
  
  { item.name }}</li>

  </ul>
</template>

<style scoped></style>

 方法直接从原来的counterStore中结构赋值

<script setup>
// 1.导入use 打头的方法
import { onMounted } from 'vue'
import { useCounterStore } from '@/stores/counter'
import { storeToRefs } from 'pinia'

//2.执行方法得到store实例对象
const counterStore = useCounterStore()
console.log(counterStore)

//直接解构赋值(响应式丢失)
// const{ doubleCount, increment, list ,count }=counterStore

//方法包裹(保持响应式)
const { doubleCount,  list, count } = storeToRefs(counterStore)

//方法直接从原来的counterStore中结构赋值
const{ increment } = counterStore


// 触发action
onMounted(() => {
  counterStore.getList()
})
</script>

<template>
  <div>
    {
  
  { doubleCount }}
  </div>
  <button @click='increment'>-{
  
  { count }}</button>
  <ul>
    <li v-for='item in counterStore.list' :key='item.id'>{
  
  { item.name }}</li>

  </ul>
</template>

<style scoped></style>

 

 

 

 

 

 

 

 

 

 

 


网站公告

今日签到

点亮在社区的每一天
去签到