Vue3中常用的语法详细分解(响应式数据,声明响应式数据,自定义事件,计算属性,监听器)

简介: Vue3中常用的语法详细分解(响应式数据,声明响应式数据,自定义事件,计算属性,监听器)

1. 创建Vue实例

Vue3使用API一律是函数式风格所以和new告别了。

// Vue3.0
import {createApp} from 'vue'
createApp(App).use(router).use(store).mount('#app')
// Vue2.0
import Vue from 'vue'
new Vue({
  router,
  store,
  render: h => h(App)
}).$mount('#app')

1.1 其他的区别

全局

// vue2
import Vue from 'vue'
Vue.component(...)
// vue3
import {createApp} from 'vue'
let app = createApp(App)
app.component(...)

filter 没有了

全局


Vue.component -> app.component

filter没了 filter -> computed/method

v-model value+input -> value+input || modelValue+update:modelValue

函数h render(h) -> import {h} from ‘vue’

data data: {} || data(){} -> data(){}

异步组件 ()=>import(’…’) -> defineAsyncComponent(()=>import(’…’))

事件 e m i t 、 emit、 emit、on、… -> $emit

其他 …

2. 响应式数据

模板定制

<template>
  <div class="hello" style="border:1px solid">
    <h1 ref="root">{{ msg }}</h1>
    {{state.count}} double is {{double}}
    <button @click="add">+</button>
  </div>
</template>

2.1 声明响应式数据

// Vue2
export default {
  // ....
  data() {
    return {
      state: {
        count: 0
      }
    };
  },
}
// Vue3 reactive 
export default {
  // ....
  setup(){
    const state = reactive({
      count:0
    })
    return {state}
  }
}

2.2 自定义事件

// Vue2
export default {
  // ....
  methods: {
    add() {
      this.state.count++;
    }
  },
}
// Vue3
export default {
  // ....
  setup(){
    const add = () => {
      state.count++
    }
    return {add}
  }
}

2.3 计算属性

// Vue2
export default {
  // ...
  computed: {
    double() {
      return this.state.count * 2;
    }
  },
}
// Vue3
export default {
  // ...
  setup(){
    const double = computed (() => state.count * 2 )
    return {double}
  }
}

2.4 监听器

// Vue2
export default {
  // ...
  watch: {
    count: value => {
      console.log("count is changed:", value);
    }
  }
}
// Vue3
export default {
  // ...
  setup(){
    watch(
      () => state.count,
      value => {
        console.log('state change :',value)
      }
    )
  }
}

2.5 生命周期及其获取Dom元素

// Vue2
<div ref="dom"></div>
export default {
  // ...
  mounted() {
    this.$refs.dom.style.color = "red";
  }
}
// Vue3
<h1 ref="myRef">7777777777777777777</h1>
export default {
  // ...
  setup() {
    // ref 创建一个响应式的数据对象
    const myRef = ref(null);
    onMounted(() => {
      console.dir(myRef);
       const dom = myRef.value
      dom.style.color = 'red'
    });
    return {
      myRef
    }
  },
}

3. API 列表

const {
  createApp,
  reactive, // 创建响应式数据对象
  ref, // 创建一个响应式的数据对象
  toRefs, // 将响应式数据对象转换为单一响应式对象
  isRef, // 判断某值是否是引用类型
  computed, // 创建计算属性
  watch, // 创建watch监听
  // 生命周期钩子
  onMounted,
  onUpdated,
  onUnmounted,
} = Vue

3.1 setup使用composition API的入口

setup函数会在 beforeCreate之后 created之前执行

setup(props,context){
    console.log('setup....',)
    console.log('props',props) // 组件参数
    console.log('context',context) // 上下文对象
} 

3.2 reactive

reactive() 函数接受一个普通对象 返回一个响应式数据对象

const state = reactive({
        count: 0,
        plusOne: computed(() => state.count + 1)
    })

3.3 ref 与 isRef

ref 将给定的值(确切的说是基本数据类型 ini 或 string)创建一个响应式的数据对象

isRef 其实就是判断一下是不是ref生成的响应式数据对象

 // 定义创建响应式数据
    const time = ref(new Date())
    // 设置定时器为了测试数据响应
    setInterval(() => time.value = new Date(), 1000)
    // 判断某值是否是响应式类型
    console.log('time is ref:', isRef(time))
    console.log('time', time)
    console.log('time.value', time.value)
    // 我们看看模板里面我们这样展示
    template: `
        <div>
            <div>Date is {{ time }}</div>
        </div>
    `

3.4 toRefs

toRefs就是ref的批量操作

toRefs 可以将reactive创建出的对象展开为基础类型

1.
// 如果不用toRefs
    const state = reactive({
        count: 0,
        plusOne: computed(() => state.count + 1)
    })
    return {
        state
    }
    // 模板渲染要这样写
    template: `
    <div>
        <div>count is {{ state.count }} </div>
        <div>plusOne is {{ state.plusOne }}</div>
    </div>
    `
    // 我们再看看用了toRefs
    const state = reactive({
        count: 0,
        plusOne: computed(() => state.count + 1)
    })
    return {
        ...toRefs(state)
    }
    // 模板渲染要这样写
    template: `
    <div>
        <div>count is {{ count }} </div>
        <div>plusOne is {{ plusOne }}</div>
    </div>
    `

3.5 watch 定义监听器

这个其实没有什么新东西,需要手动指定

watch(() => 谁,()=>{})
watch(() =>[a,b....], ()=>{})
watch(() => state.count * 2, val => {
        console.log(`count * 2 is ${val}`)
 })

3.5.1 watchEffect 自动监听

自动监听,当watchEffect内部使用了某个值会自动监听这个值变化,当这个值变化的时候触发

 watchEffect((invalidate) => { 
  console.log('a变了',a)     
 })
invalidate: 参数是一个函数,放监听器失效的时候触发。监听器什么时候会失效?stop的时候、或者组件销毁
invalidate(()=>{})

3.5.2 停止监听

 let stop = watchEffect((invalidate) => {})
 let stop1 = watch(() => 谁,()=>{})
 stop()
 stop1()

3.6 ffect 副作用函数

响应式对象修改会触发这个函数

    // 副作用函数
    effect(() => {
        console.log('数值被修改了..',state.count)
    })

3.7 computed 计算属性

const state = reactive({
    count: 0,
    plusOne: computed(() => state.count + 1)
})

3.8 provide/inject 依赖注入

// 外部组件
setup(){ 
  provide(名字,值【可以是任何类型】)  
}
// 内部
setup(){ 
  const a = inject(名字,可选参:默认值)

toRaw 与 markRaw

toRaw 拿出reactive、ref、readonly这个方法转换前的原始互数据,对原始数据操作不会被监听

markRaw 保持一个数据永远是原始数据不会被监听

unRef 、toRef、customRef

unRef :获取ref对象的原始数据,那为什么不用toRaw

toRaw连着value一起拿,获取出来就是 => {value:xxx}

unRef是ref专用 => xxx

toRef: 也是把一个数据转成ref对象,但是的ref专有一些区别

let json = {a:12}
const b = ref(json.a)
b.value++ 
console.log(json,b)  // {a:12} // {value:13}
const a = toRef(json,'a')
a.value++ 
console.log(json,a)  // {a:13} // {value:13}

ref toRef

相当于把原始数据拷贝,以后操作与原始数据无关 依然存在引用关系

改ref对象后模板会重新渲染 不会触发模板渲染

customRef:自定义ref

function myCustomRef(){
  let _val = 12 
  return customRef((track,trigger)=>{
    return {
      get(){
        track()
        return _val
      },
      set(newVal){
        _val = newVal
        // 通知vue,请重新渲染
        trigger()
      }
    }
  })
}
setup(){
    const arr = myAjax('xxxx',[])
    return {
        arr
    }
}
function myAjax(url,initval){
  let _data = initval 
  return customRef((track,trigger)=>{
    axios(url).then(res=>{
      _data = res._data
      trigger()
    })
    return {
      get(){
        track()
        return _data
      },
      set(newVal){
        _data = newVal
        // 通知vue,请重新渲染
        trigger()
      }
    }
  })
}

Vue2                     |                Vue3

--------------------------------------------------

beforeCreate             |             setup(替代)

created                   |             setup(替代)

beforeMount            |            onBeforeMount

mounted                   |            onMounted

beforeUpdate             |               onBeforeUpdate

updated                   |               onUpdated

beforeDestroy             |              onBeforeUnmount

destroyed                 |               onUnmounted

errorCaptured             |               onErrorCaptured

4. Teleport 组件

Teleport 提供了一种干净的方法,允许我们控制在 DOM 中哪个父节点下渲染了 HTML

// vue3 新添加了一个默认的组件就叫 Teleport,我们可以拿过来直接使用,它上面有一个 to 的属性,它接受一个css query selector 作为参数,这就是代表要把这个组件渲染到哪个 dom 元素中
  <teleport to="#modal">
    <div id="center">
      <h1>this is a modal</h1>
    </div>
  </teleport>

4.1 Suspense - 异步组件好帮手

定义一个异步组件,在 setup 返回一个 Promise,AsyncShow.vue

<template>
  <h1>{{result}}</h1>
</template>
<script lang="ts">
import { defineComponent } from 'vue'
export default defineComponent({
  setup() {
    return new Promise((resolve) => {
      setTimeout(() => {
        return resolve({
          result: 42
        })
      }, 3000)
    })
  }
})
</script>

使用 async await 改造一下异步请求, 新建一个 DogShow.vue 组件

<template>
  <img :src="result && result.message">
</template>
<script lang="ts">
import axios from 'axios'
import { defineComponent } from 'vue'
export default defineComponent({
  async setup() {
    const rawData = await axios.get('https://dog.ceo/api/breeds/image')
    return {
      result: rawData.data
    }
  }
})
</script>
<Suspense>
  <template #default>
    <async-show />
    <dog-show />
  </template>
  <template #fallback>
    <h1>Loading !...</h1>
  </template>
</Suspense>

5. 路由Vue-router

5.1 创建路由

// Vue2
const router = new VueRouter({
  mode: 'history',
  base: process.env.BASE_URL,
  routes:  [
    // 路由配置不变
  ]
})
// Vue3
const router = createRouter({
  history: createWebHistory(process.env.BASE_URL),
  routes:  [
    // 路由配置不变
  ]
})

5.2 使用路由

// Vue2
export default {
  name: "Home",
  methods: {
    goHome() {
      this.$router.push('Home')
    }
  }
};
// Vue3
export default {
  setup() {
    const router = useRouter()
    const goHome = () => router.push('Home')
    return { goHome};
  }
};

6.0 统一状态管理Vuex

6.1 创建Vuex

// Vue2
export default new Vuex.Store({
  state: {
    count:1
  },
  mutations: {
    inc(state){
      state.count ++ 
    }
  },
  actions: {
  },
  modules: {
  }
})
// Vue3
export default Vuex.createStore({
  state: {
    count:1
  },
  mutations: {
    add(state){
      state.count ++ 
    }
  },
  actions: {
  },
  modules: {
  }
});

6.2 使用Vuex

// Vue2
export default {
  name: "Home",
  data() {
    return {
        state: this.$store.state
    };
  },
  computed: {
    double() {
      return this.$store.state.count * 2;
    },
  },
  methods: {
    add() {
      this.$store.commit("add");
    }
  }
};
// Vue3
import { computed,  reactive } from "vue";
import { useStore } from "vuex";
export default {
  setup() {
    const store = useStore()
    const state = store.state
    const double = computed(() => store.state.count * 2)
    const add = () => {
      store.commit("add");
    };
    return { state, add ,double};
  }
};
相关文章
|
28天前
|
缓存 JavaScript UED
Vue3中v-model在处理自定义组件双向数据绑定时有哪些注意事项?
在使用`v-model`处理自定义组件双向数据绑定时,要仔细考虑各种因素,确保数据的准确传递和更新,同时提供良好的用户体验和代码可维护性。通过合理的设计和注意事项的遵循,能够更好地发挥`v-model`的优势,实现高效的双向数据绑定效果。
128 64
|
1月前
|
监控 JavaScript 算法
深度剖析 Vue.js 响应式原理:从数据劫持到视图更新的全流程详解
本文深入解析Vue.js的响应式机制,从数据劫持到视图更新的全过程,详细讲解了其实现原理和运作流程。
|
1月前
|
JavaScript 数据管理 Java
在 Vue 3 中使用 Proxy 实现数据双向绑定的性能如何?
【10月更文挑战第23天】Vue 3中使用Proxy实现数据双向绑定在多个方面都带来了性能的提升,从更高效的响应式追踪、更好的初始化性能、对数组操作的优化到更优的内存管理等,使得Vue 3在处理复杂的应用场景和大量数据时能够更加高效和稳定地运行。
63 1
|
JavaScript 前端开发
vue通过监听实现相同路径的视图重新加载
最近在做一个项目,前端菜单路径如下: { path: '/oa/workflow/process/:status', component: sys_workflow_process, ...
1266 0
|
1月前
|
JavaScript API 开发者
Vue是如何进行组件化的
Vue是如何进行组件化的
|
7天前
|
JavaScript 关系型数据库 MySQL
基于VUE的校园二手交易平台系统设计与实现毕业设计论文模板
基于Vue的校园二手交易平台是一款专为校园用户设计的在线交易系统,提供简洁高效、安全可靠的二手商品买卖环境。平台利用Vue框架的响应式数据绑定和组件化特性,实现用户友好的界面,方便商品浏览、发布与管理。该系统采用Node.js、MySQL及B/S架构,确保稳定性和多功能模块设计,涵盖管理员和用户功能模块,促进物品循环使用,降低开销,提升环保意识,助力绿色校园文化建设。
|
1月前
|
JavaScript 前端开发 开发者
vue学习第一章
欢迎来到我的博客!我是瑞雨溪,一名热爱前端的大一学生,专注于JavaScript与Vue,正向全栈进发。博客分享Vue学习心得、命令式与声明式编程对比、列表展示及计数器案例等。关注我,持续更新中!🎉🎉🎉
41 1
vue学习第一章
|
1月前
|
JavaScript 前端开发 索引
vue学习第三章
欢迎来到瑞雨溪的博客,一名热爱JavaScript与Vue的大一学生。本文介绍了Vue中的v-bind指令,包括基本使用、动态绑定class及style等,希望能为你的前端学习之路提供帮助。持续关注,更多精彩内容即将呈现!🎉🎉🎉
30 1
|
1月前
|
缓存 JavaScript 前端开发
vue学习第四章
欢迎来到我的博客!我是瑞雨溪,一名热爱JavaScript与Vue的大一学生。本文介绍了Vue中计算属性的基本与复杂使用、setter/getter、与methods的对比及与侦听器的总结。如果你觉得有用,请关注我,将持续更新更多优质内容!🎉🎉🎉
38 1
vue学习第四章
|
1月前
|
JavaScript 前端开发 算法
vue学习第7章(循环)
欢迎来到瑞雨溪的博客,一名热爱JavaScript和Vue的大一学生。本文介绍了Vue中的v-for指令,包括遍历数组和对象、使用key以及数组的响应式方法等内容,并附有综合练习实例。关注我,将持续更新更多优质文章!🎉🎉🎉
25 1
vue学习第7章(循环)

热门文章

最新文章