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

目录

1. 创建Vue实例

1.1 其他的区别

 2. 响应式数据

2.1 声明响应式数据

2.2 自定义事件

2.3 计算属性

2.4 监听器

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

3. API 列表

3.1 setup使用composition API的入口

3.2 reactive

 3.3 ref 与 isRef

 3.4 toRefs

 3.5 watch 定义监听器

 3.5.1 watchEffect 自动监听

 3.5.2 停止监听

3.6 ffect 副作用函数

 3.7 computed 计算属性

3.8 provide/inject 依赖注入

toRaw 与 markRaw

unRef 、toRef、customRef

customRef:自定义ref 

4. Teleport 组件

4.1 Suspense - 异步组件好帮手

5. 路由Vue-router

5.1 创建路由

 5.2 使用路由

6.0 统一状态管理Vuex

6.1 创建Vuex

6.2 使用Vuex


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创建出的对象展开为基础类型

// 如果不用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};
  }
};

猜你喜欢

转载自blog.csdn.net/m0_67063430/article/details/129497711
今日推荐