TS+Vue3配置并衍生出一些面试题

1,004 阅读4分钟

vite和@vue/cli区别

@vue/cli更稳定些,提供的模块更多 vite编译速度更快

TS+Vue3安装方式

vue create vuecli-ts-test
vue add typescript 

提示class-style的时候  选择no  

image.png

vue-router配置

router.vuejs.org/zh/guide/es…

添加路由4步:

  1. 安装vue-router@next cnpm install vue-router@next --save

  2. 创建router.ts文件,配置路由

import { createRouter,createWebHashHistory } from "vue-router";

import Home from './components/Home.vue'
import User from './components/User.vue'
// 配置路由
const router = createRouter({
    history: createWebHashHistory(),
    routes: [
        {path: '/',component: Home},
        {path: '/user',component: User}
    ]
})
export default router
  1. 在main.ts中引入router.ts,并挂载
import { createApp } from 'vue'
import App from './App.vue'
import routes from './router' //不能带.ts,不然会报错
let app= createApp(App)
app.use(routes)
app.mount('#app')
  1. 在app.vue根组件中动态加载配置的组件
  <router-view></router-view>

根据链接地址动态的跳转到路由地址

<router-link to='/user'>跳转到user</router-link>

其他同Vue2

集成vuex

  1. 安装vuex@next
cnpm install vuex@next --save
  1. 新建store.ts文件
import {createStore, Store} from 'vuex'
import {ComponentCustomProperties} from 'vue'

// 能在vue中得到this,必须加这些
declare module '@vue/runtime-core' {
// 在传给createStore的state中定义的属性都得在interface中申明,不然在vue中是获取不到的通过store是获取不到state中的元素
    interface State{
        count: number,
        list: string[],
        msg: string
    }
    interface ComponentCustomProperties {
        $store: Store<State>
    }
}

const store = createStore({
    state(){
        return{
            count:1,
            list:['马总','李总'],
            msg:'你好vue'
        }

    },
    mutations:{
        incCount(state:any){
            state.count++

        },
        setCount(state, num){
            state.count = num
        },
        setMsg(state,msg){
            state.msg = msg
        }
    },
    getters: {
        reverseMsg(state){
            return state.msg.split('').reverse().join('')
        },
        num(state){
            return state.count + 10
        }
    },
    actions: {
        incCount(context){
            context.commit('incCount')
        },
        setCount({commit},num){
            commit('setCount',num)
        } 
    }
})
export default store
  1. 在main.ts中引入store.ts,并挂载
app.use(store)
  1. 在vue文件中使用 引入useStore,加上lang="ts"
<script lang="ts">
import { computed, defineComponent } from 'vue';
import { useStore } from 'vuex'
// 比如必须传指定的接口
// defineComponent不能少,启用类型判断
export default defineComponent({
    setup(){
        // 在defineComponent获取store
        const store = useStore()
        let incCount=()=>{
            store.commit('incCount')      
        }
        let incActionCount=()=>{
            store.dispatch('incCount')
        }
        // 获取到store,就能获取到store中的数据
        return {
            count: computed(()=>{
                return store.state.count
            }),
            incCount,
            num: computed(()=>{
                return store.getters.num
            }),
            incActionCount,
            setActionCount:(q:any)=>{
                store.dispatch('setCount',q)
            }
        }
    }
  <、script>

小项目中vuex可以不使用,vue3中可以使用provide和inject来代替

在provide使用一些组件实例 property,以下使用方式则这将不起作用

 data() {
    return {
      todos: ['Feed a cat', 'Buy tickets']
    }
  },
  provide: {
    todoLength: this.todos.length // 将会导致错误 'Cannot read property 'length' of undefined`
  },

要访问组件实例 property,我们需要将 provide 转换为返回对象的函数

provide() {
    return {
      todoLength: this.todos.length
    }
}

在上面的例子中,如果我们更改了 todos 的列表,这个更改将不会反映在注入的 todoLength property 中。这是因为默认情况下,provide/inject 绑定不是被动绑定

可以通过将 ref property 或 reactive 对象传递给 provide 来更改此行为。 也可以分配一个组合式 API computed property

provide() {
    return {
      todoLength: Vue.computed(() => this.todos.length)
    }
 }

怎么增加提供值和注入值之间的响应性?

为了增加提供值和注入值之间的响应性,我们可以在提供值时使用 ref 或 reactive

const location = ref('North Pole')
const geolocation = reactive({
  longitude: 90,
  latitude: 135
})

provide('location', location)
provide('geolocation', geolocation)

当使用响应式提供/注入值时,建议尽可能,在提供者内保持响应式 property 的任何更改

methods: {
    updateLocation() {
      this.location = 'South Pole'
    }
}

有时我们需要在注入数据的组件内部更新注入的数据。在这种情况下,我们建议提供一个方法来负责改变响应式 property

 const updateLocation = () => {
  location.value = 'South Pole'
}
provide('updateLocation', updateLocation)

如果要确保通过 provide 传递的数据不会被注入的组件更改,我们建议对提供者的 property 使用 readonly

provide('location', readonly(location))

setup(props,context)接收两个参数

setup () 内部调用生命周期钩子

image.png

setup 函数中的 props 是响应式的,如果需要解构 prop,可以通过使用 setup 函数中的 toRefs 来完成此操作

因为 props 是响应式的,你不能使用 ES6 解构,因为它会消除 prop 的响应性

setup(props) {
const title = toRef(props, 'title')
console.log(title.value)

setup 函数中的context,不是响应式的,可以解构,暴露三个组件的 property:attrs, slots, emit

setup(props, { attrs, slots, emit }) {
}

attrs 和 slots 是有状态的对象,它们总是会随组件本身的更新而更新。这意味着你应该避免对它们进行解构,并始终以 attrs.x 或 slots.x 的方式引用 property。 请注意,与 props 不同,attrs 和 slots 是非响应式的。如果你打算根据 attrs 或 slots 更改应用副作用,那么应该在 onUpdated 生命周期钩子中执行此操作

执行 setup 时,组件实例尚未被创建

只能访问以下 property:

props /  attrs / slots  /  emit

换句话说,你将无法访问以下组件选项:

data  /  computed  /  methods

setup 可以返回一个对象

setup() {
  const readersNumber = ref(0)
  const book = reactive({ title: 'Vue 3 Guide' })

  // expose to template
  return {
    readersNumber,
    book
  }
}

setup 可以返回一个渲染函数

该函数可以直接使用在同一作用域中声明的响应式状态

 setup() {
    return {
        count: computed(()=>{
            return store.state.count
        })
    }
}

在 setup() 内部,this 不会是该活跃实例的引用

因为 setup() 是在解析其它组件选项之前被调用的,所以 setup() 内部的 this 的行为与其它选项中的 this 完全不同。这在和其它选项式 API 一起使用, setup() 时可能会导致混淆。