【vue3】composition-api使用

文章目录

    • 基础使用
    • typescript中使用
    • vue2升级vue3注意事项
    • 扩展
    • 关于vite
    • vue3+ts

基础使用

  1. markRaw 永远不会转为响应式代理
const target = ref(markRaw(window));  // 永远不会转为响应式代理
return {
      target };
  1. store的使用
import {
      useStore } from 'vuex'
const store = useStore() // 或const { getters, commit } = useStore();
onBeforeMount(() => {
     
  store.commit('setShowBack', false)
})
  1. router的使用

router 是全局路由器router的实例,可以在任何组件内进行访问。的作用是进行路由跳转的,router.go(-1)

route 当前页面的路由信息对象

  1. path:当前路由对象的路径
  2. params:路由中的动态片段
  3. query:路由中查询参数的键值对
  4. router:路由规则所属的路由器
  5. matched:当前匹配的路径中的参数对象
  6. name:当前路径名字
// router实例
import {
      useRouter, useRoute } from 'vue-router'
const router = useRouter();
router.push(`/list/${
       type}`)

// 或者
const {
      currentRoute } = useRouter()
currentRoute.value.path

// 也可以这样获取
import {
      getCurrentInstance} from "vue";
const {
      ctx } = getCurrentInstance();
const routes = computed(() => ctx.$root.$router.options.routes);
// route当前页面路由
const route = useRoute()
route.params.id
  1. provide和inject
import {
      provide, inject} from 'vue'
// 父:传递数据给子组件
provide('title', 'hahaha')

// 子:接收传递过来的数据
const title = inject('title')

5.ref操作dom元素

  • 操作自己的dom
<p ref="pRef">测试ref</p>

setup () {
     
	const pRef = ref(null)
	onMounted(() => {
     
      pRef.value.style.color = 'red'
    })
}
  • 操作子组件的dom
// child.vue
<div>子组件 --- {
     {
     str}}</div>
import {
      ref } from 'vue'
setup () {
     
  const str = ref('子组件默认值')
  const changeStr = (val: string) => {
     
    str.value = val
  }
  return {
     
    str,
    changeStr
  }
}

// parent.vue
<Child ref="childRef" />
import {
      ref } from 'vue'
const childRef = ref(null)
const changeChildContent = () => {
     
   childRef.value.changeStr('来自父组件的值')  // 调用子组件的方法
}
  1. setup获取props
import {
      defineComponent, setup } from "vue"
export default defineComponent({
     
	 name: "Text",
	 props: {
     
	   title: String,
	   type: {
     
	     type: String,
	     default: "default",
	   }
	 },
	setup(props, {
      slots, emit }) {
     
		emit("click", 'hhh');
	}
})
  1. App.component()
import {
      createApp } from "vue";
import Component from "./src/index.vue";
const app = createApp(App);
app.component(Component.name as string, Component);
app.mount("#app");
  1. 使用render函数
import {
      defineComponent, computed, h } from "vue";
export default defineComponent({
     
    name: "VLayout",
    setup(props, {
      slots }) {
     
        const createSpaceItemList=()=>{
     
            console.log(slots)
            return 'eee'
        }
        return ()=>{
     
            return  h( "div",
                {
      class: 'ha-loading', style: 'color: red' }, 
                createSpaceItemList()
            )
        }
    }
})
// 生成 
eee
// 常用于slot
  1. getCurrentInstance方法,用来获取当前组件实例,然后通过ctx获取当前上下文
import {
      defineComponent, getCurrentInstance} from "vue";
export default defineComponent({
     
    setup() {
     
        const {
      ctx } = getCurrentInstance();
        const routes = computed(() => ctx.$root.$router.options.routes);
        console.log(routes)
    }
})
  1. vue3挂载全局属性和方法
  • 挂载到globalProperties
// main.ts  
const app = createApp(App);
app.use(router).use(store)
app.config.globalProperties.$dt = dt
app.mount('#app') // 注意这个要在最后,否则挂载后找不到

// App.vue
import {
      getCurrentInstance } from "vue";
setup(props: any, context: any) {
     
    const {
      ctx }: any = getCurrentInstance();
    const handleClick=()=>{
     
      ctx.$dt.getName()
    }
    return {
     
      handleClick
    }
}
  • 可以简化代码
// main.ts
app.config.globalProperties.$reactive = reactive;

// App.vue
import {
      getCurrentInstance } from "vue";
setup(props: any, context: any) {
     
    const {
      ctx }: any = getCurrentInstance();
    const state = ctx.$reactive({
     
      collapsed: false
    })
}

typescript中使用

怎么找类型:node_modules/ @vue中后缀为.d.ts的就是

  1. router
import {
      useRouter, RouteLocationRaw } from "vue-router";
props: {
     
    to: [Object, String] as PropType<RouteLocationRaw>,  // 类型
},
setup(){
     
	const router = useRouter();
	if (props.to && router) {
     
	  router.push(props.to as RouteLocationRaw);
	  return;
	}
}
  1. CSSProperties
<div :style="colStyle">
import {
      CSSProperties } from "vue";
const colStyle = computed(() => {
     
	const style: CSSProperties = {
     };
	style.paddingTop = `50px`;
	style.paddingBottom = `60px`;
	return style;
});
return {
      colClass, colStyle };
  1. ref和Ref
<div ref="myRef"></div>

import {
      ref, Ref } from "vue";
setup(props, {
      emit }) {
     
    const myRef= ref<unknown>() as Ref<HTMLDivElement>;
    const myReact = myRef.value.getBoundingClientRect();
}

vue2升级vue3注意事项

// 把vue2的卸载,改为:
/*
	npm uninstall vue vue-template-compiler vue-router vuex vue-loader -D
*/
"vue": "^3.0.0-rc.5",
"@vue/compiler-sfc": "^3.0.0-rc.10",
"vue-loader": "^16.0.0-beta.5",
"vue-router": "^4.0.0-beta.4",
"vuex": "^4.0.0-beta.4"

// webpack.config.js
// 之前的是 const VueLoaderPlugin = require('vue-loader/lib/plugin')
const {
      VueLoaderPlugin } = require('vue-loader') 
{
     
  test: /\.vue$/,
  loader: 'vue-loader',
  options: {
     
    compilerOptions: {
     
      preserveWhitespace: false,
    }
  }
},

单元测试

// 这两个包也要跟着升级:
"@vue/test-utils": "^2.0.0-beta.0",
"vue-jest": "^5.0.0-alpha.1"

// HelloWorld.spec.ts
import {
      mount } from '@vue/test-utils'
import HelloWorld from '@/HelloWorld.vue'

test('displays message', async () => {
     
  const wrapper = await mount(HelloWorld)

  // Assert the rendered text of the component
  expect(wrapper.find('p').text()).toBe('0')
  await wrapper.find('button').trigger('click')
  expect(wrapper.find('p').text()).toBe('1')
})

扩展

  1. vue-property-decorator
import {
      Component, Prop, Vue } from 'vue-property-decorator'
@Component
export default class HelloWorld extends Vue {
     
  @Prop() private msg!: string;
}

参考:
官网composition-api

关于vite

官网
vite的原理是:利用浏览器支持es6的import,碰到import会对其进行解析,为每次导入提出http请求。vite开发服务器拦截这些请求,并在必要时执行代码转换,如.vue文件的导入会在发送回浏览器前进行编译

特点:
1、vite支持.vue中使用ts或.ts文件
2、vite仅对.ts做转译,不执行类型检查,类型检查有IDE和构建过程负者(您可以在构建脚本中运行 tsc --noEmit ,为不生成输出文件)
3、vite使用esbuild编译工具做ts编译(不支持一些功能,还需要配置tsconfig.js,比如枚举、隐式),而不是ts官网的tsc

您必须在 tsconfig.json 的 editorOptions 下设置 " isolatedModules":true,以便TS会针对隔离式编译不起作用的功能向您发出警告
【vue3】composition-api使用_第1张图片

vue3+ts

// 安装
npm i vue@^3.0.0-alpha.9 @vue/compiler-sfc@^3.0.0-alpha.9 vue-loader@^16.0.0-alpha.1  typescript  ts-loader  -D

// tsconfig.json
{
     
  "compilerOptions": {
     
      "allowJs": true,
      "allowSyntheticDefaultImports": true,
      "declaration": false,
      "esModuleInterop": true,
      "experimentalDecorators": true,
      "module": "es2015",
      "moduleResolution": "node",
      "noImplicitAny": false,
      "noLib": false,
      "sourceMap": true,
      "strict": true,
      "strictPropertyInitialization": false,
      "suppressImplicitAnyIndexErrors": true,
      "target": "es5",
      "baseUrl": "."
  },
  "exclude": [
      "./node_modules"
  ],
  "include": [
      "./src/**/*.ts",
      "./src/**/*.vue"
  ]
}
// webpack.config.js
const path = require('path')
const {
      VueLoaderPlugin } = require('vue-loader')
const HtmlWebpackPlugin = require('html-webpack-plugin')
const {
      CleanWebpackPlugin } = require('clean-webpack-plugin')

module.exports = (env = {
     }) => ({
     
  mode: env.prod ? 'production' : 'development',
  devtool: env.prod ? 'source-map' : 'inline-source-map',
  entry: path.resolve(__dirname, './src/main.js'),
  output: {
     
    path: path.resolve(__dirname, './dist'),
    publicPath: '/'
  },
  resolve: {
     
    alias: {
     
      'vue': '@vue/runtime-dom'
    }
  },
  module: {
     
    rules: [
      {
     
        test: /\.vue$/,
        use: 'vue-loader'
      },
      {
     
        test: /\.css$/,
        use: [
          'style-loader',
          'css-loader'
        ]
      },
      {
     
        test: /\.ts$/,
        loader: 'ts-loader',
        options: {
     
          appendTsSuffixTo: [/\.vue$/],
        }
      }
    ]
  },
  plugins: [
    new VueLoaderPlugin(),
    new CleanWebpackPlugin(),
    new HtmlWebpackPlugin({
     
      template: path.resolve(__dirname, './public/index.html'),
      filename: 'index.html'
    })
  ],
  devServer: {
     
    inline: true,
    hot: true,
    stats: 'minimal',
    contentBase: __dirname,
    overlay: true,
    publicPath: '/',
    historyApiFallback: true
  }
})

// package.json
"scripts": {
     
  "dev": "webpack-dev-server",
  "build": "webpack --env.prod",
},

// src/main.js
import {
      createApp } from 'vue'
import App from './App.vue'
createApp(App).mount('#app')

// src/shims-vue.d.ts
declare module '*.vue' {
     
  import {
      defineComponent } from 'vue';
  const Component: ReturnType<typeof defineComponent>;
  export default Component;
}
declare function showAuthor(author: string): string

// src/App.vue
<template>
  <div>
    {
     {
      count }}
    <button @click="handleClick()">点击+1</button>
  </div>
</template>

<script lang="ts">
import {
      defineComponent, ref , toRefs, reactive} from 'vue'
export default defineComponent({
     
    setup() {
     
      const state = reactive({
     
        count: 0
      })

      const handleClick = () => {
     
        state.count++
      }

      return {
       ...toRefs(state), handleClick }
    }
  })
</script>

持续更新…

你可能感兴趣的:(vue技术栈)