Vue3笔记摘录

1.Vue3整体知识概览图

2.ref与reactive具体使用区别
   2-1  基本类型处理
const count1 = ref(0)  使用ref自动转化为数字类型

const count2 = reactive(0) 参数必须是对象类型
  2-2  具体使用过程
// ref 处理对象(自动解包)
const user = ref({
  name: 'John',
  address: {
    city: 'New York'
  }
})

// 等效于 reactive 写法
const user = reactive({
  name: 'John',
  address: reactive({
    city: 'New York'
  })
})

// 访问方式对比
// ref 需要 .value
console.log(user.value.name) 
// reactive 直接访问
console.log(user.name)     

2-3  数组处理区别

1.ref需要.value.push去修改原数组
const list = ref([1,2,3])
list.value.push(4)

2.reactive 可以直接修改
const list_copy = reactive([1,2,3])
list_copy.push(4)
3.传值
    3-1 父子组件传值 普通方式(父传子)
   3-1-1 父组件
    <template>
      <Child :msg='msg' :list="list"/>
    </template>
    <script>
    import Child from './child.vue'
    import { ref, reactive } from 'vue'
    export default {
      components: { Child },
      setup() {
        const msg = ref('父组件传递给子组件的信息info')
        const list = reactive(['苹果', '香蕉', '橘子', '葡萄', '榴莲'])
        return {
          msg,
          list
        }
      }
    }
    </script>

    3-1-2 子组件
    <template>
      <ul>
        <li v-for='(i,index) in list' :key="index">{{ index+1 }}. {{ i }}</li>
      </ul>
    </template>
    <script>
    export default {
      props: ['msg', 'list'],
      setup() {}
    }
    </script>
 3-2  父子组件传值 setup方式(父传子)
3-2-1 父组件
<template>
  <Child :msg='msg' :list="list"/>
</template>
<script>
import Child from './child.vue'
import { ref, reactive } from 'vue'
export default {
  components: { Child },
  setup() {
    const msg = ref('父组件传递给子组件的信息info')
    const list = reactive(['苹果', '菠萝蜜', 香蕉', '橘子', '葡萄', '榴莲'])
    return {
      msg,
      list
    }
  }
}
</script>

3-2-2 子组件
<template>
  <ul>
    <li v-for='(i,index) in list' :key="index">{{ index+1 }}. {{ i }}</li>
  </ul>
</template>
<script setup>
import { defineProps } from 'vue'
const props = defineProps({
  // 第一种写法
  msg: String,
  // 第二种写法
  list: {
    type: Array,
    default: () => []
  }
})
console.log(props)
</script>
     3-3 emit传值(子传父)
父组件
<template>
  <Child @myClick='onMyClick' @increase='onIncrease'/>
</template>
<script setup>
import Child from './child.vue'
const onMyClick = (info) => {
  console.log(info)
}
const onIncrease = (info) => {
  console.log(info)
}
</script>

子组件
<template>
 <button @click="handleClick">按钮</button>
</template>
<script setup>
import { defineEmits, ref } from 'vue'
const info = ref('你好呀')
const emit = defineEmits(['myClick'])
const handleClick = () => {
  emit('myClick', info)
  emit('increase', ref('你好呀_copy'))
}
</script>
 3-4 defineExpose、ref(父传子)
父组件
<template>
  <div>父组件:拿到子组件的message数量 {{ msg }}</div>
  <button @click='callChildFn'>调用子组件的方法</button>
  <Child ref="com"/>
</template>
<script setup>
import { ref, onMounted } from 'vue'
import Child from './child.vue'
const com = ref(null)
const msg = ref('')
onMounted(() => {
  console.log(com, 'com==onmounted')
  msg.value = com.value.message
})
function callChildFn() {
  console.log(com, 'callChildFn==onmounted')
  com.value.show()
  msg.value = com.value.message
}
</script>

子组件
<template>
<div>子组件</div>
</template>
<script setup>
import { defineExpose, ref } from 'vue'
const message = ref('子组件传递消息')
const show = () => {
  console.log('子组件方法')
}
defineExpose({
  message,
  show
})
</script>
3-5 attrs(子传父)
父组件
<template>
  <Child :msg='msg' :msgcopy='msgcopy' title='子组件'/>
</template>
<script setup>
import { ref } from 'vue'
import Child from './child.vue'
const msgcopy = ref('我是你呀')
const msg = ref('你猜我是谁')
</script>


子组件有俩种写法

第一种写法 使用attrs
<template>
<div>子组件: {{ attrs.msg }}--{{ attrs.msgcopy }}--{{ attrs.title }}</div>
</template>
<script setup>
import { useAttrs } from 'vue'
const attrs = useAttrs()
console.log(attrs)
</script>

第二种写法 使用defineProps
<template>
   <div>子组件: {{ msg }}--{{ msgcopy }}--{{ title }}</div>
</template>
<script setup>
   import { defineProps } from 'vue'
   defineProps({
     msg: String,
     msgcopy: String,
     title: String
   })
</script>
3-6 provide、inject(多层级传值)
父组件
<template>
  <div>祖父组件</div>
  <button @click='fn'>改变location的值</button>
  <br/>
  <div>双向数据绑定:</div>
 <ul>
  <li>{{ userInfo.name }}</li>
 </ul>
 <input  v-model='userInfo.name' />
 <Child />
</template>
<script setup>
import { ref, provide } from 'vue'
import Child from './child.vue'
const location = ref('传递祖父的参数')
const userInfo = ref({
  name: '张三',
  age: 18
})
function fn() {
  location.value = '改变值'
}
provide('location', location)
provide('userInfo', userInfo)
</script>

子组件
<template>
    <Sun />
</template>
<script>
import Sun from './sun.vue'
export default {
  components: { Sun }
}
</script>
<style lang="scss" scoped>
</style>

孙组件
<template>
<div>
  <h5>...........孙组件接受参数........</h5>
  <div>1.祖父组件定义provide,孙组件inject接受:{{ location }}</div>
  <p>用户信息:{{ userInfo.name }}</p>
  <br/>
  <br/>
  <div>2.provide inject实现父子组件传值的时候,子组件改变数据也会影响父组件</div>
  <br/>姓名:
  <input v-model="userInfo.name">
</div>
</template>
<script setup>
import { inject } from 'vue'
const location = inject('location')
const userInfo = inject('userInfo')
</script>

再这个里面需要注意的是 readonly
增加readonly后 子组件修改后 不会影响父组件  父组件 子组件和上述一样 唯一区别是孙组件 具体写法如下:
<template>
  <div>祖父组件</div>
  <button @click='fn'>改变location的值</button>
  <br/>
  <div>双向数据绑定:</div>
 <ul>
  <li>{{ userInfo.name }}</li>
 </ul>
 <input  v-model='userInfo.name' />
 <Child />
</template>
<script setup>
import { ref, provide,readonly } from 'vue'
import Child from './child.vue'
const location = ref('传递祖父的参数')
const userInfo = ref({
  name: '张三',
  age: 18
})
function fn() {
  location.value = '改变值'
}
provide('location', location)
provide('userInfo', readonly(userInfo))
</script>
 3-7 v-model 是vue一个语法糖 在vue3玩法更多了

 

3-7-1 单个v-model

父组件
<template>
 <Child v-model='message'/>
</template>
<script setup>
import { ref } from 'vue'
import Child from './child.vue'
const message = ref('父传给子')
</script>

子组件
<template>
   <button @click='handleClick'>修改model</button>
   {{ modelValue }}
</template>
<script setup>
import { defineProps, defineEmits } from 'vue'
defineProps(['modelValue'])
const emit = defineEmits(['update:modelValue'])
function handleClick() {
  emit('update:modelValue', '子改变值')
}
</script>
<style lang="scss" scoped>
</style>

3-7-2 多个v-model

父组件
<template>
 <Child v-model:msg1='message1' v-model:msg2='message2'/>
</template>
<script setup>
import { ref } from 'vue'
import Child from './child.vue'
const message1 = ref('水果1')
const message2 = ref('水果2')
</script>

子组件
<template>
  <div>
    <button @click='handleClick1'>修改msg1</button> {{ msg1 }}
  </div>
  <div>
   <button @click='handleClick2'>修改msg2</button> {{ msg2 }}
  </div>
</template>
<script setup>
import { defineProps, defineEmits } from 'vue'
defineProps({
  msg1: String,
  msg2: String
})
const emit = defineEmits(['update:msg1', 'update:msg2'])
function handleClick1() {
  emit('update:msg1', '蔬菜1')
}
function handleClick2() {
  emit('update:msg2', '蔬菜2')
}
</script>
<style lang="scss" scoped>
</style>

3-8 v-model修饰符 
1.用法的话是v-model.自定义修饰符 有些自定义修饰符比如trim number lazy
2.具体用法
父组件
<template>
 <Child v-model.uppercasefn='message'/>
</template>
<script setup>
import { ref } from 'vue'
import Child from './child.vue'
const message = ref('水果1')
</script>


子组件
<template>
  {{ modelValue }}
</template>
<script setup>
import { defineProps, defineEmits, onMounted } from 'vue'
const props = defineProps(['modelValue', 'modelModifiers'])
const emit = defineEmits(['update:modelValue'])
onMounted(() => {
  console.log('modelModifiers', props.modelModifiers)
  if (props.modelModifiers.uppercasefn) {
    emit('update:modelValue', '蔬菜')
  }
})
</script>
<style lang="scss" scoped>
</style>

注意:如果在子组件中修改v-model.uppercasefn中的uppercasefn改成其他的 那么页面展示的就是水果1
if (props.modelModifiers.uppercasefn) 这个就是判断自定义修饰符有没有在当前props里
3-9 插槽 slot插槽可以理解为传一段html片段 给子组件
3-9-1 最基础的插槽模版
只需要在子组件中使用标签 就会将父组件传进来的HTML内容渲染出来

父组件
<template>
 <Child>
  <div>渲染</div>
 </Child>
</template>
<script setup>
import Child from './child.vue'
</script>

子组件
<template>
  <slot></slot>
</template>
<script setup>
</script>
<style lang="scss" scoped>
</style>
3-9-2 具名插槽  
具名插槽就是在默认插槽的基础上进行分类,可以理解为对号入座
父组件需要使用标签 但是需要在标签上使用v-slot:+‘名称’。
子组件需要在标签里用name=‘名称’ 对应接收

父组件
<template>
 <Child>
  <template v-slot:monkey>
     <div>渲染</div>
  </template>
 <button>我是父组件</button>
 </Child>
</template>
<script setup>
import Child from './child.vue'
</script>

子组件
<template>
  <div>
    <!-- 默认插槽 -->
    <slot></slot>
    <!-- 具名插槽 也就是自定义插槽 -->
    <slot name='monkey'></slot>
  </div>
</template>
<script setup>
</script>
<style lang="scss" scoped>
</style>
3-9-3 作用域插槽

父组件
<template>
 // v-slot='{scope}' 获取子组件传过来的数据
 // :list='list' 把list数据传给子组件
 <Child v-slot='{scope}' :list='list'>
  <div v-if="scope">
    <div>{{ scope.name }}--职业:{{ scope.occupation }}</div>
    <hr/>
  </div>
 </Child>
</template>
<script setup>
import { reactive } from 'vue'
import Child from './child.vue'
const list = reactive([
  { name: '张三', occupation: '学生' },
  { name: '李四', occupation: '老师' },
  { name: '王五', occupation: '医生' },
  { name: '赵六', occupation: '警察' },
  { name: '田七', occupation: '军人' }
])
</script>

子组件
<template>
  <div>
    <slot v-for='item in list' :scope="item"></slot>
  </div>
</template>
<script setup>
import { defineProps } from 'vue'
defineProps({
  list: {
    type: Array,
    default: () => []
  }
})
</script>
<style lang="scss" scoped>
</style>

 后续还会陆续更新vue3相关文章,敬请期待哈!

    评论
    添加红包

    请填写红包祝福语或标题

    红包个数最小为10个

    红包金额最低5元

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

    抵扣说明:

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

    余额充值