vue2.0+vant2.X升级vue3.0+vant3.X

2,314 阅读2分钟

Vue3.0中你需要了解的变动

关于vue3.0的生命周期

3.0.png

2.0.png

区别:

//创建实例
1. vue3创建一个实例对象
const app =Vue.createApp({})

2. vue2c创建一个实例对象
const vm=new Vue({})

//实例对象插件的引入
1. vue3通过链式调用的方式导入插件
app.use(router).user(store).mount('#app')

2.vue2通过参数方式导入插件
new Vue({
    router,
    store,
}).$mount('#app')

自定义指令、全局过滤器

1. 过滤器

a. 局部
//vue2局部过滤器
<template>
  <p>{{ accountBalance | currencyUSD }}</p>
</template>
<script>
export default{
    filters:{
        currencyUSD(value){
            return '$'+value
        }
    }
}
</script>
//vue3局部过滤器改造
<template>
  <p>{{accountInUSD}}</p>
</template>
<script>
export default{
   computed:{
       accountInUSD(){
           return '$'+this.accountBalance
       }
   }
}
</script>
b.全局
//vue2全局过滤器
Vue.filter('currencyUSD',(value)=>{
    return '$'+value
})
//vue3全局过滤器(本质是在全局注册一个全局属性)
app.config.globalProperties.$filters={
   accountInUSD(value){
      return '$'+value
   }
}
<template>
  <p>{{$filters.accountInUSD(accountBalance)}}</p>
</template>

2. 自定义指令

vue2中的自定义指令的api 4.png

vue3中的自定义指令api

5.png

//2.0写法
Vue.directive('highlight', {
  bind(el, binding, vnode) {
    el.style.background = binding.value
  }
})
//3.0写法
app.directive('highlight', {
  beforeMount(el, binding, vnode) {
    el.style.background = binding.value
  }
})

3. 全局组件

Vue.component(component.name, component)

组件

1. 组件

defineComponent的解析

<script>
// defineComponent 可以用于手动渲染函数、TSX 和 IDE 工具支持
// defineComponent以正确推断 setup() 组件的参数类型
// getCurrentInstance获取当前组件实例(注意其中的两个值ctx、proxy),可以获取父组件中的调用的状态
// ref 两种用法1.用于为基本数据类型添加响应式状态 2.表示模板应用
// reactive 用于为对象添加响应式状态 
//toRef用于为源响应式对象上的属性新建一个ref,从而保持对其源对象属性的响应式连接(父组件传递的props数据时,要引用props的某个属性且要保持响应式连接时就很有用)
//toRefs用于将响应式对象转换为结果对象,其中结果对象的每个属性都是指向原始对象相应属性的ref(1.将reactive中响应式数据转换成单个的ref,2.将props数据自动的转换ref)
import { reactive,defineComponent,ref,getCurrentInstance,computed,onActivated,onBeforeMount,toRefs} from 'vue';
import {useRoute} from 'vue-router'
import { useStore } from 'vuex'
export default defineComponent({
  name: 'CommonListConent',
  components: {[List.name]: List},
  props: {
    currentPage: {
      type: Number,
      default: () => 1,
    }
  },
  //setup第二个参数的使用{attrs,slots,emit}
  //attrs可以拿到父组件上面引用时写在上面值
  //<searchInput  name='123231'  />
  //slots可以拿到父组件传过来的插槽
  //<template>
  //<van-search @update:model-value="searchValue" v-model.trim="search" shape="round" :placeholder="placeholder">
    //<template v-slot:[item] v-for="(item, index) in name" :key="index">
      //<slot :name="item"></slot>
    //</template>
  //</van-search>
//</template>
//const name=Object.keys(slots)
  
  
  
  
  setup(props,{emit}) {
    const instance = getCurrentInstance().proxy
    const route=useRoute()
    const state = reactive({
      onFinished: false,
      onLoading: false,
    });
    const root = ref(null)
    const store = useStore();
    const getScrollTop=computed(()=>store.getters['homeIndex/getScrollTop'])
    onActivated(()=>{
      if(Reflect.has(getScrollTop.value, route.path)){
        root.value.$el.scrollTop = getScrollTop.value[route.path]
      }
    })
    const onRefresh=()=>{
      state.freshLoading = true;
      emit('onRefresh');
    },
    const onLoadDisabled=computed(()=>{
      return !instance.onLoad
    })
    const onRefreshDisabled=computed(()=>{
      return !instance.onRefresh
    })
    onBeforeMount(()=>{
      state.onFinished = onLoadDisabled.value
    })
    return{
      ...toRefs(state),
      onRefreshDisabled,
      root,
    }
  },
  emits: ['onRefresh','onLoad'],
})
</script>

2. 函数式组件

// Vue 2 函数式组件
<template functional>
  <component
    :is="`h${props.level}`"
    v-bind="attrs"
    v-on="listeners"
  />
</template>

<script>
export default {
  props: ['level']
}
</script>
//vue3函数式组件
<template>
  <component
    v-bind:is="`h${$props.level}`"
    v-bind="$attrs"
  />
</template>

<script>
export default {
  props: ['level']
}
</script>
//使用$props这样的方式将值呈现在视图上时,不管props中的值是否改变,视图显示值都是最初的方式

vue3中的ref使用

1.使用

<template> 
  <div ref="root">This is a root element</div>
</template>
const root = ref(null)//声明的名要和上面的ref中的名相同,DOM元素将在初始化后分配给ref

2. v-for中的用法

2.0写法
 <van-checkbox :name="res" :ref="`checkboxes${elemIndex}${index}`" icon-size="16px" />
 <div class="left">
    <img :src="res.imgUrl ? res.imgUrl : require('@/assets/images/shopLogo.png')" alt />
 </div>
 3.0写法
  <van-checkbox :name="res" :ref="el=>{if(el) setCheckboxes(el,`${elemIndex}${index}`,resIndex)}" @click.stop icon-size="16px" />
  <div class="left">
   <img :src="res.imgUrl ? res.imgUrl : require('@/assets/images/shopLogo.png').default" alt />
  </div>
 

6.png

vue3.0中的插件(vueX vueRouter)

1. vuex

//2.0写法
import Vue from 'vue'
import Vuex from 'vuex'
import createPersistedState from 'vuex-persistedstate'
import modules from './store'

Vue.use(Vuex)
const store = new Vuex.Store({
  plugins: [createPersistedState({
    storage: window.sessionStorage
  })],
  modules
})

//3.0写法
import { createStore } from 'vuex';
import createPersistedState from 'vuex-persistedstate';
import modules from './store';

export default createStore({
  plugins: [createPersistedState({
    storage: window.sessionStorage,
  })],
  modules,
});

2. vuerouter

//2.0用法
import Vue from 'vue'
import Router from 'vue-router'
import routes from './routes'
Vue.use(Router)
const router = new Router({
  routes
})
router.beforeEach((to, from, next) => {
})
router.afterEach(() => {
})
//3.0用法
import { createRouter, createWebHashHistory } from 'vue-router';
import routes from './routes'
const router = createRouter({
  history: createWebHashHistory(),
  routes,
});
router.beforeEach((to, from, next) => {
})
router.afterEach(() => {
})

使用v-bind.sync(对某一个 prop 进行“双向绑定”)

//2.0写法
this.$emit('update:title', newValue)
//<ChildComponent :title="pageTitle" @update:title="pageTitle = $event" />
<ChildComponent :title.sync="pageTitle" />
//3.0写法
<ChildComponent v-model:title="pageTitle" />

Vant3中你需要了解的变动(未完)

1.关于组件引入的一些误区

2.关于vant3.0中api参数声明

vant2.0和vant3.0中第一个大的区别就在于数据创建的位置不同

//vant2中创建的位置
export default { 
    data() { 
        return { 
            show: false, 
        }; 
    }, 
    methods: { 
        showPopup() { 
            this.show = true; 
        }, 
    }, 
};
//vant3中创建的位置
import { ref } from 'vue'; 
export default { 
    setup() { 
        const show = ref(false); 
        const showPopup = () => { show.value = true; }; 
        return { 
            show, 
            showPopup, 
        }; 
    }, 
};

但是其实vant3.0中的数据创建还是可以在data中进行创建,方法也可以在method中使用,如果你在升级的过程中不想进行过多的改造,你可以保持源码不变,只改哪些页面在运行时,无法使用的地方(记住这个只是让你快速的升级自己的项目,但是后续还是需要修改的,按照标准走)

3.关于vant3.0中Popup、ActionSheet、Dialog与vant2.x中的不同

在vant3.0中Popup、ActionSheet、Dialog(组件调用方式)与vant2在页面中使用时都在v-model后面加了show,升级时需要批量修改你使用到了Popup中的地方

//Popup
//vant2使用方式
<van-popup v-model="show">内容</van-popup>
//vant3中使用方式
<van-popup v-model:show="show">内容</van-popup>

//ActionSheet
//vant2使用方式
<van-action-sheet v-model="show" :actions="actions" @select="onSelect" />
//vant3中使用方式
<van-action-sheet v-model:show="show" :actions="actions" @select="onSelect" />

//Dialog
//vant2使用方式
<van-dialog v-model="show" title="标题" show-cancel-button> <img src="https://img01.yzcdn.cn/vant/apple-3.jpg" /> </van-dialog>
//vant3中使用方式
<van-dialog v-model:show="show" title="标题" show-cancel-button> <img src="https://img.yzcdn.cn/vant/apple-3.jpg" /> </van-dialog>

4.关于vant3.0中Dialog的beforeClose与vant2.x中的不同

vant3中beforeClose中以promise方式进行回调

//vant2使用方式
function beforeClose(action, done) { 
  if (action === 'confirm') { 
    setTimeout(done, 1000); 
  } else { 
    done(); 
  } 
 } 
Dialog.confirm({ title: '标题', message: '弹窗内容', beforeClose, });
//vant3使用方式
const beforeClose = (action) => 
  new Promise((resolve) => { 
    setTimeout(() => { 
      if (action === 'confirm') { 
        resolve(true); 
      } else { 
        // 拦截取消操作
        resolve(false); 
       } 
      }, 1000); 
  }); 
 Dialog.confirm({ title: '标题', message: '弹窗内容', beforeClose, });