• vite + ts 快速搭建 vue3 项目 以及介绍相关特性


    博客地址:https://ainyi.com/98

    Vue3.0,One Piece

    接下来得抽空好好学习了

    vite

    尤大在 Vue 3.0 beta 直播中推荐了 vite 的工具,强调:针对Vue单页面组件的无打包开发服务器,可以直接在浏览器运行请求的 vue 文件
    很新颖,这篇博客用它来搭建一个 vue3 的项目试试

    Vite 是面向现代浏览器,基于原生模块系统 ESModule 实现了按需编译的 Web 开发构建工具。在生产环境下基于 Rollup 打包

    • 快速冷启动服务器
    • 即时热模块更换(HMR)
    • 真正的按需编译

    node >= 10.16.0

    搭建

    使用 vite 搭建项目

    npm init vite-app <project-name>
    

    安装 typescript、vue-router@next、axios、eslint-plugin-vue、sass 等相关插件

    配置

    vite.config.ts

    vite.config.ts 相当于 @vue-cli 项目中的 vue.config.js

    我这简单配置一下:

    import path from 'path'
    
    module.exports = {
      alias: {
        '/@/': path.resolve(__dirname, './src')
      },
      optimizeDeps: {
        include: ['lodash']
      },
      proxy: {}
    }
    

    Router

    在 src 下新建 router 文件夹,并在文件夹内创建 index.ts

    import { createRouter, createWebHistory } from 'vue-router'
    
    const routes = [
      {
        path: '/',
        name: 'Home',
        component: () => import('/@/views/Home.vue')
      },
      {
        path: '/lifeCycle',
        name: 'lifeCycle',
        component: () => import('/@/views/LifeCycle.vue')
      }
    ]
    
    export default createRouter({
      history: createWebHistory('/krry/'),
      routes
    })
    

    ts types

    项目根目录下新建 tsconfig.json 写入相关配置

    {
      "compilerOptions": {
        ...// 其他配置
        "paths": {
          "/@/*": [
            "src/*"
          ]
        },
        "lib": [
          "esnext",
          "dom",
          "dom.iterable",
          "scripthost"
        ]
      },
      "include": [
        "src/**/*.ts",
        "src/**/*.tsx",
        "src/**/*.vue",
        "src/types/images.d.ts",
        "tests/**/*.ts",
        "tests/**/*.tsx"
      ],
      "exclude": [
        "node_modules"
      ]
    }
    

    src 目录下新建 types 文件夹,里面需要配置 ts 的类型

    shims-vue.d.ts

    declare module '*.vue' {}
    

    images.d.ts

    declare module '*.svg'
    declare module '*.png'
    declare module '*.jpg'
    declare module '*.jpeg'
    declare module '*.gif'
    declare module '*.bmp'
    declare module '*.tiff'
    

    main.ts

    import { createApp } from 'vue'
    import router from '/@/router'
    
    import App from '/@/App.vue'
    
    const app = createApp(App)
    app.use(router)
    app.mount('#app')
    

    然后就可以快乐地写代码了

    vue3 知识

    setup

    vue3 中用 setup 函数整合了所有的 api;只执行一次,在生命周期函数前执行,所以在 setup 函数中拿不到当前实例 this,不能用 this 来调用 vue2 写法中定义的方法

    它将接受两个参数:props、context

    // props - 组件接受到的属性 context - 上下文 
    setup(props, context) {
      return {
        // 要绑定的数据和方法
      }
    }
    

    props
    setup 函数中的 props 是响应式的,当传入新的 prop 时,它将被更新
    但是,因为 props 是响应式的,不能使用 ES6 解构,因为它会消除 prop 的响应性

    如果需要解构 prop,可以通过使用 setup 函数中的 toRefs 来安全地完成此操作

    import { toRefs } from 'vue'
    
    setup(props) {
      const { title } = toRefs(props)
      console.log(title.value)
    }
    

    context
    context 暴露三个组件的 property:{ attrs, slots, emit }
    它是一个普通的 JavaScript 对象,不是响应式的,这意味着你可以安全地对 context 使用 ES6 解构

    生命周期

    通过在生命周期钩子前面加上 “on” 来访问组件的生命周期钩子

    因为 setup 是围绕 beforeCreate 和 created 生命周期钩子运行的,所以不需要显式地定义它们
    换句话说,在这两个钩子中编写的任何代码都应该直接在 setup 函数中编写

    setup() {
      onMounted(() => {
        console.log('组件挂载')
      })
    
      onUnmounted(() => {
        console.log('组件卸载')
      })
    
      onUpdated(() => {
        console.log('组件更新')
      })
    
      onBeforeUpdate(() => {
        console.log('组件将要更新')
      })
    
      onActivated(() => {
        console.log('keepAlive 组件 激活')
      })
    
      onDeactivated(() => {
        console.log('keepAlive 组件 非激活')
      })
    
      return {}
    }
    

    ref、reactive

    ref 可以将某个普通值包装成响应式数据,仅限于简单值,内部是将值包装成对象,再通过 defineProperty 来处理的
    通过 ref 包装的值,取值和设置值的时候,需用通过 .value来进行设置
    可以用 ref 来获取组件的引用,替代 this.$refs 的写法

    reactive 对复杂数据进行响应式处理,它的返回值是一个 proxy 对象,在 setup 函数中返回时,可以用 toRefs 对 proxy 对象进行结构,方便在 template 中使用

    使用如下:

    <template>
      <div>
        <div>
          <ul v-for="ele in eleList" :key="ele.id">
            <li>{{ ele.name }}</li>
          </ul>
          <button @click="addEle">添加</button>
        </div>
        <div>
          <ul v-for="ele in todoList" :key="ele.id">
            <li>{{ ele.name }}</li>
          </ul>
          <button @click="addTodo">添加</button>
        </div>
      </div>
    </template>
    
    <script>
    import { ref, reactive, toRefs } from 'vue'
    
    export default {
      setup() {
        // ref
        const eleList = ref([])
        function addEle() {
          let len = eleList.value.length
          eleList.value.push({
            id: len,
            name: 'ref 自增' + len
          })
        }
    
        // reactive
        const dataObj = reactive({
          todoList: []
        })
        function addTodo() {
          let len = dataObj.todoList.length
          dataObj.todoList.push({
            id: len,
            name: 'reactive 自增' + len
          })
        }
    
        return {
          eleList,
          addEle,
          addTodo,
          ...toRefs(dataObj)
        }
      }
    }
    </script>
    

    computed、watch

    // computed
    let sum = computed(() => dataObj.todoList.length + eleList.value.length)
    console.log('setup引用computed要.value:' + sum.value)
    
    // watch
    watch(
      eleList,
      (curVal, oldVal) => {
        console.log('监听器:', curVal, oldVal)
      },
      {
        deep: true
      }
    )
    

    watchEffect

    响应式地跟踪函数中引用的响应式数据,当响应式数据改变时,会重新执行函数

    const count = ref(0)
    // 当 count 的值被修改时,会执行回调
    const stop = watchEffect(() => console.log(count.value))
    
    // 停止监听
    stop()
    

    还可以停止监听,watchEffect 返回一个函数,执行后可以停止监听

    与 vue2 一样:

    const unwatch = this.$watch('say', curVal => {})
    
    // 停止监听
    unwatch()
    

    useRoute、useRouter

    import {useRoute, useRouter} from 'vue-router'
    
    const route = useRoute() // 相当于 vue2 中的 this.$route
    const router = useRouter() // 相当于 vue2 中的 this.$router
    
    route   用于获取当前路由数据
    router  用于路由跳转
    

    vuex

    使用 useStore 来获取 store 对象 从 vuex 中取值时,要注意必须使用 computed 进行包装,这样 vuex 中状态修改后才能在页面中响应

    import {useStore} from 'vuex'
    
    setup(){
      const store = useStore() // 相当于 vue2 中的 this.$store
      store.dispatch() // 通过 store 对象来 dispatch 派发异步任务
      store.commit() // commit 修改 store 数据
        
      let category = computed(() => store.state.home.currentCagegory
      return { category }
    }
    

    博客地址:https://ainyi.com/98

  • 相关阅读:
    emqttd的启动脚本
    vue2的全局变量
    windows 上优雅的安装 node 和 npm
    Intent数据清理
    android 滑动刷新的实验总结
    Android 音量键拦截
    多进程通讯笔记 android aidl
    perl-Thread-Queue for openwrt
    openwrt的编译环境
    高德地图白屏的问题
  • 原文地址:https://www.cnblogs.com/ainyi/p/13927377.html
Copyright © 2020-2023  润新知