vue3-setup

关于升级vue3报错

在执行命令

npm install @vue/cli -g

报错内容为一大堆路径,也就是全局vue位值错误

解决方法

删除C:\Users\think\AppData\Roaming\npm\node_modules下的@vue文件(也就是你全局vue下载的文件所在地址),

再次执行命令

步入正题

关于vue3的数据绑定,有多种形式,以下举例

数据单向绑定

<template>
  <p>{{count}}</p>
  <input type="text" v-model="count">
</template>
<script>
export default {
  name: 'App',
  setup(){
    let count = 'web03'
	setTimeout(()=>{
      count = 'https://web03.cn'//这样不能修改 html内容不会发生改变
    },1000)
    return {
      count
    }
  }
}
</script>

在这种情况下,变量count只会显示在p标签内,input中的v-model并不能改变他,所以这样声明相当于是一个静态的变量

数据双向绑定 ref

<template>
  <p>{{count}}</p>
  <input type="text" v-model="count">
</template>

<script>
import {ref} from 'vue'
export default {
  name: 'App',
  setup(){
    let count = ref('web03')setTimeout(()=>{
      //count = 'https://web03'//错误 不能这样修改
      count.value = 'https://web03.cn'//正确 取它的value进行修改 是可以响应到模板的
    },1000)
    return {
      count
    }
  }
}
</script>

引入vue中的ref方法,传入默认参数值,它处理后的变量是响应式的

数据双向绑定 reactive

<template>
  <p>{{state.count}}</p>
  <input type="text" v-model="state.count">
</template>

<script>
import {reactive} from 'vue'
export default {
  name: 'App',
  setup(){
    const state = reactive({
      count: 'web03'
    })
	setTimeout(()=>{
        state.count = 'https://web03.cn'//响应式数据
      },1000)
    return {
      state
    }
  }
}
</script>

reactive方法传入一个对象,里面包含着响应式的变量,html模板中必须要取这个对象下的变量,并且不能对他解构
被解构之后就不是响应式的,以下为错误示例

<template>
  <p>{{count}}</p>
  <input type="text" v-model="count">
</template>

<script>
import {reactive} from 'vue'
export default {
  name: 'App',
  setup(){
    const state = reactive({
      count: 'web03'
    })
    return {
      ...state,//错误
      count:state.count//错误
    }
  }
}
</script>

双向绑定 reactive&toRefs

<template>
  <p>{{count}}</p>
  <input type="text" v-model="count">
</template>

<script>
import {reactive, toRefs} from 'vue'
export default {
  name: 'App',
  setup(){
    const state = reactive({
      count: 'web03'
    })
	setTimeout(()=>{
        state.count = 'https://web03.cn'//响应式数据
      },1000)
    return {
      ...toRefs(state)
    }
  }
}
</script>

通过解构toRefs处理过的state,一样能达到数据响应式

jsx渲染

<template>
  <p>123</p>
</template>

<script>
  import {reactive,h} from 'vue'
  export default {
    name: 'App',
    setup(){
      const state = reactive({
        count: 'web03'
      })
      setTimeout(()=>{
        state.count = 'https://web03.cn'//响应式数据
      },1000)
      return ()=>h('h1',state.count)
    }
  }
</script>

可以直接return一个jsx函数,这样会直接把你template里面原有的内容全部替换

watchEffect 与 watch

案例1

延迟监听

<template>
  <div>
    {{num}}
  </div>
</template>

<script>
  import {reactive,toRefs, watchEffect} from 'vue'
  export default {
    name: 'App',
    setup(){
      const state = reactive({
        num:0
      })
      setInterval(()=>{
        state.num ++
      },1000)
      const stop = () => watchEffect(()=>{
        console.log(state.num)
      })
      setTimeout(()=>{
        stop()//过5秒后监听state的值
      },5000)
      return {
        ...toRefs(state)
      }
    }
  }
</script>

只监听指定时间

<template>
  <div>
    {{num}}
  </div>
</template>

<script>
  import {reactive,toRefs,ref, watchEffect} from 'vue'
  export default {
    name: 'App',
    setup(){
      const state = reactive({
        num:0
      })
      const count = ref(0)
      setInterval(()=>{
        state.num ++
        count.value++
      },1000)
      const stop = watchEffect(()=>{
        console.log(count.value)
      })
      setTimeout(()=>{
        stop()//只监听5秒
      },5000)
      return {
        ...toRefs(state)
      }
    }
  }
</script>

案例2

父组件

<template>
  <div>
    <p>123</p>
    <hello-world :count="count"></hello-world>
  </div>
</template>

<script>
  import HelloWorld from './components/HelloWorld'
  import {reactive,toRefs} from 'vue'
  export default {
    name: 'App',
    components: {
      HelloWorld
    },
    setup(){
      const state = reactive({
        count: 'web03'
      })
      setTimeout(()=>{
        state.count = 'https://web03.cn'//响应式数据
      },1000)
      return {
        ...toRefs(state)
      }
    }
  }
</script>

子组件-watch版

<template>
    <h1>{{ count }}</h1>
</template>

<script>
import {watch} from 'vue'
export default {
  name: 'HelloWorld',
  props: {
    count: String
  },
  setup(props){
    // watch监听指定的值,只有指定的值发生改变,才会触发回调函数 初始加载不触发
    watch(()=>{
      return props.count
    },(newValue)=>{
      console.log(newValue)//两秒后打印https://web03.cn
    })
  }
}
</script>

子组件-watchEffect版

<template>
    <h1>{{ count }}</h1>
</template>

<script>
import { watchEffect} from 'vue'
export default {
  name: 'HelloWorld',
  props: {
    count: String
  },
  setup(props){
    //初始加载时  props发生变更时 都会触发回调
    watchEffect(()=>{
      console.log(props.count)//直接打印web03 2秒后打印https://web03.cn
    })
  }
}
</script>

总结watch与watchEffect的区别
1、watch可以监听指定的props变化,而watchEffect监听所有的props变化

2、watch在初始加载时不会触发回调,只有被监听的值发生改变才触发,而watchEffect会在加载时触发一次,并且props任意一个发生改变都会触发回调

不要去解构props,不然会失去响应式

不要去改变props,它在当前组件是不可变的,可以通知父级去改变它

关于 context.attrs与props

<template>
    <h1>{{ attrs.count }}</h1>
</template>
<script>

export default {
  name: 'HelloWorld',
  // props: {
  //   count: String
  // },
    /**
     * setup的第二个参数是context
     * 它包含了{attrs,emit,slots}
     * @param props
     * @param context
     */
  setup(props,context){
      return{
          attrs: context.attrs
      }
  }
}
</script>

以上代码仍然能够取得父组件传过来的count参数,并且是响应式的
注意
如果写了props如props: {count: String},将不能在context.attrs取到props的值count,他们是不能共存的

子调用父方法 emit

父组件

<template>
  <div>
    <p>父:{{num}}</p>
    <hello-world :num="num" @addNum="addNum"></hello-world>
  </div>
</template>

<script>
  import HelloWorld from './components/HelloWorld'
  import {reactive,toRefs} from 'vue'
  export default {
    name: 'App',
    components: {
      HelloWorld
    },
    setup(){
      const state = reactive({
        num: 3
      })
      const addNum = (n) => {
        state.num += n
      }
      return {
        ...toRefs(state),
        addNum
      }
    }
  }
</script>

子组件

<template>
    <div>
        <h1>子:{{ num }}</h1>
        <button @click="onAdd">add</button>
    </div>
</template>
<script>

export default {
  name: 'HelloWorld',
  props: {
    num: Number
  },
    emits: ['addNum'],//注册emit事件
  setup(props, context){
        const onAdd = ()=> {
            context.emit('addNum', 1)
        }
      return{
          onAdd
      }
  }
}
</script>

emit在context中,要调用父方法,必须在父定义的子组件中写入方法 如 @addNum="addNum"和vue2一样
但是有所不同的是,子调用父方法,需要emits中注册

以上内容为个人学习vue3.0笔记,如想更官方的解析,请查阅官方文档

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值