开始学习vue3

621 阅读3分钟

vue3基础

一、组件

1、基本操作props,emit,v-model

  • 父组件通过v-bind将数据传给子组件 <child :visible="pvisible" />,
  • 如果需要子组件修改visivle值需要使用v-model的形式 <child v-model:visible="pvisible" />
  • 子组件接收,使用父组件的传入值
...(){
name: 'child',
props: {
    visible: Boolean,
},
setup(props, { emit }){
    const { visible } = toRefs(props);
    // 修改visible
    emit('update:visible', false);
    return {
        visible
    }
}

2、父组件调用子组件方法

  • 父组件中
...
<child v-model:visible="pvisible" ref="childRef" />
...
setup(){
    const childRef = ref();
    const xxx = () => {
        childRef.value.setvisible(true)
    }
    return {
        childRef,
        xxx
    }
}
  • 子组件:
import { useContext } from 'vue';
...
setup(props,{emit}){
    const setvisible = (boo) => {
        // boo ==true
    }
    
    // 子组件给父组件需要使用expose暴露该方法
    const { expose } = useContext();
    expose({
      setvisible,
    });
    // 未暴露出的api
}

3、动态注册全局组件

(1)在src/components下创建global/FristC.vue,

在vue2中,可以直接在global文件夹下创建index.js文件注册global,但vue3的组件注册是通过app.component创建,而app是通过createApp创建,所以在vue3中只能写在main.ts文件中,如下:

const app = createApp(App)

app
  .use(router)
  .use(store)
  ...

  // 动态注册公共组件
const requireComponent = import.meta.globEager("./components/global/*.vue")
Object.keys(requireComponent).forEach((item: any) => {
  const componentConfig:any = requireComponent[item]
  const name = item.split("/").pop().split(".")[0]
  app.component(name,componentConfig.default || componentConfig)
})

app.mount('#app')

此处有个关于加载模块的问题,在webpack中我们可以直接使用require.context('./', false, /.vue$/)引入模块,可在vite中不支持, 而vite2.0 提供了 glob模式 的模块导入。这里使用import.meta.globEager("./components/global/*.vue")

(2).vue2+webpack实现

// register global
function changeStr(str) {
  return str.charAt(0).toUpperCase() + str.slice(1)
}
const requireComponent = require.context('./', false, /\.vue$/) //  /[A-Za-z0-9-_]+\.(vue|js)$/
const install = Vue => {
  requireComponent.keys().forEach(fileName => {
    const config = requireComponent(fileName)
    const componentName = changeStr(fileName.replace(/^\.\/(.*)\.\w+$/, '$1'))
    Vue.component(componentName, config.default || config)
  })
}
export default install

二、状态管理

1.安装

yarn add vuex

2、model

model/user.ts

// state
const state = {
    tabsList: []
}
const getters = {}
const actions = {}
const mutations = {
    // 添加tagsview
    ADD_TAGS(state,route){
        // 添加标签页
        const isExists = state.tabsList.some((item) => item.fullPath == route.fullPath)
        if (!isExists) {
            // 
            state.tabsList.push(
                Object.assign({}, route)
            )
        }
        return true
    }
}
export default {
    namespace: true,
    state,
    getters,
    actions,
    mutations
}

2. store使用

import { useStore } from 'vuex';
import { useRoute } from 'vue-router';
...
setup() {
        const store = useStore()
        const currentRoute = useRoute();
        // 添加当前路由信息到tagsview
        store.commit('ADD_TAGS', currentRoute);

        return () => (
            <>
                <h1>{store.state.title}</h1>
            </>
        );
    }

三、环境相关

1、使用 Vite 快速构建 Vue 项目

$ yarn create vite-app <project-name>
$ cd <project-name>
$ yarn
$ yarn dev

2、ts

yarn add --dev typescript

项目根目录创建配置文件:tsconfig.json:

可使用.tsx(About.tsx)

import { defineComponent } from 'vue';
export default defineComponent({
    name: 'App',
    setup() {
        return () => (
            <>
                <h1>About</h1>
            </>
        );
    }
});

参照github.com/justwiner/v…

3、使用ant-design-vue2.0(按需加载)

  • 安装 yarn add ant-design-vue@next
  • yarn add babel-plugin-import
  • babel.config.js文件中添加配置
plugins: [
    [
      'import',
      { libraryName: 'ant-design-vue', libraryDirectory: 'es', style: 'css' }
    ]
  ]

vite2 中使用vite-plugin-babel-import处理babel

  • yarn add vite-plugin-babel-import -D
  • vite.connfig.ts 文件添加:
import vitePluginImport from 'vite-plugin-babel-import';
...
plugins: [
    ...
    vitePluginImport([
      {
        libraryName: 'ant-design-vue',
        libraryDirectory: 'es',
        style(name) {
          if (/popconfirm/.test(name)) {
            // support multiple style file path to import
            return 'ant-design-vue/es/popover/style/index.css'
          }
          if (name === 'row' || name === 'col') {
            return 'ant-design-vue/es/grid/style/index.css'
          }
          return `ant-design-vue/lib/${name}/style/index.css`;
        },
        ignoreStyles: []
      },
    ]),
  ],
  • antd使用less,安装less yarn add less less-loader
  • 配置vue.config.js
css: {
   loaderOptions: {
     less: {
       javascriptEnabled: true
     }
   }
 }

JavascriptEnabled 在less3.0之前是默认true,但是在3.0版本之后是默认false,因此需要手动设置true,否则会报错

  • 使用: 创建antd.ts文件
import type { App } from 'vue'
import { Button } from 'ant-design-vue'
import 'ant-design-vue/dist/antd.css'

export function setupAntd(app: App<Element>) {
    app.use(Button)
}

在main.ts文件引入

import { setupAntd } from "./plugins/antd"
...
setupAntd(app)

6、使用ant-design-vue2.0更换主题颜色

  • 安装插件less less-loader vite-plugin-style-import
  • 修改vite.config文件
...
import styleImport from 'vite-plugin-style-import'
...
plugins: [
    styleImport({
      libs: [
        {
          libraryName: 'ant-design-vue',
          esModule: true,
          resolveStyle: (name) => {
            return `ant-design-vue/es/${name}/style/index`
            // if (/popconfirm/.test(name)) {
            //   // support multiple style file path to import
            //   return 'ant-design-vue/es/popover/style/index.css'
            // }
            // if (name === 'row' || name === 'col') {
            //   return 'ant-design-vue/es/grid/style/index.css'
            // }
            // return `ant-design-vue/lib/${name}/style/index.css`;
          }
        }
      ]
    }),
    ...
],
css: {
    preprocessorOptions: {
      less: {
        modifyVars: { // 更改主题在这里
          'primary-color': '#FF4B07',
          'link-color': '#FF4B07',
          'border-radius-base': '2px'
        },
        javascriptEnabled: true
      }
    }
  },

使用即可

注意是在vite.config文件中添加css配置,如果是使用vite-plugin-style-import插件,就替换掉上面按需加载中的vite-plugin-babel-import

5、添加mock(插件配置,环境变量)

安装依赖

yarn add mockjs -S
yarn add vite-plugin-mock cross-env -D

参照vite-plugin-mock www.npmjs.com/package/vit…

插件配置 vite.config.js中

...
import { viteMockServe } from "vite-plugin-mock"

// https://vitejs.dev/config/
export default defineConfig({
  plugins: [
    vue(),
    // 配置mock
    viteMockServe({
      // default
      mockPath: 'mock',
    })
  ]
})

添加mock文件:mock/test.ts

import { MockMethod } from 'vite-plugin-mock';
export default [
  {
    url: '/api/get',
    method: 'get',
    response: ({ query }) => {
      return {
        code: 0,
        data: {
          name: 'vben',
        },
      };
    },
  },
  {
    url: '/api/post',
    method: 'post',
    timeout: 2000,
    response: {
      code: 0,
      data: {
        name: 'vben',
      },
    },
  },
] as MockMethod[];

app.vue中调用

...
setup() {
    ....
    fetch("/api/get")
      .then((resp) => resp.json())
      .then((data) => console.log(data));

    ...
    return {}
  },

可配置环境变量.env.development

VITE_TOKEN=54321asdfgh

修改package.json,添加模式mock

....
"scripts": {
    ...
    "mockdev": "cross-env NODE_ENV=development vite",
    ....
  },

可在vue文件中读取环境变量.env.development中的VITE_TOKEN

// 读取环境变量值
console.log(import.meta.env.VITE_TOKEN);

vue-cli2/vue-cli3区别

1、vue-cli2/vue-cli3的关于下载模板

起初需求前端存放的静态文件(一些模版)供用户下载修改后上传。

    downloadIn() {
      const link = document.createElement("a");
      link.href = `?`; // 这里是地址
      link.setAttribute("download", `订单导入模版.xlsx`);
      document.body.appendChild(link);
      link.click();
    }

vue-cli2存放static下

/static/file/xxxx.xlsx

link.href = '/static/file/xxxx.xlsx'

vue-cli3存放在public下

/public/file/xxxx.xlsx

link.href = '/file/xxxx.xlsx'

prototype

全局设置变量,挂载echart main.js 引入

import * as echarts from "echarts";
import "echarts/theme/macarons"; // echarts theme
  • vue2 Vue.prototype.$echarts = echarts

  • vue3

const app = createApp(App);
app.config.globalProperties.$echarts = echarts;