const target = ref(markRaw(window)); // 永远不会转为响应式代理
return {
target };
import {
useStore } from 'vuex'
const store = useStore() // 或const { getters, commit } = useStore();
onBeforeMount(() => {
store.commit('setShowBack', false)
})
router 是全局路由器router的实例,可以在任何组件内进行访问。的作用是进行路由跳转的,router.go(-1)
route 当前页面的路由信息对象
- path:当前路由对象的路径
- params:路由中的动态片段
- query:路由中查询参数的键值对
- router:路由规则所属的路由器
- matched:当前匹配的路径中的参数对象
- 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
import {
provide, inject} from 'vue'
// 父:传递数据给子组件
provide('title', 'hahaha')
// 子:接收传递过来的数据
const title = inject('title')
5.ref操作dom元素
<p ref="pRef">测试ref</p>
setup () {
const pRef = ref(null)
onMounted(() => {
pRef.value.style.color = 'red'
})
}
// 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('来自父组件的值') // 调用子组件的方法
}
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');
}
})
import {
createApp } from "vue";
import Component from "./src/index.vue";
const app = createApp(App);
app.component(Component.name as string, Component);
app.mount("#app");
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
import {
defineComponent, getCurrentInstance} from "vue";
export default defineComponent({
setup() {
const {
ctx } = getCurrentInstance();
const routes = computed(() => ctx.$root.$router.options.routes);
console.log(routes)
}
})
// 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
})
}
怎么找类型:node_modules/ @vue中后缀为.d.ts的就是
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;
}
}
<div :style="colStyle">
import {
CSSProperties } from "vue";
const colStyle = computed(() => {
const style: CSSProperties = {
};
style.paddingTop = `50px`;
style.paddingBottom = `60px`;
return style;
});
return {
colClass, colStyle };
<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的卸载,改为:
/*
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')
})
import {
Component, Prop, Vue } from 'vue-property-decorator'
@Component
export default class HelloWorld extends Vue {
@Prop() private msg!: string;
}
参考:
官网composition-api
官网
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会针对隔离式编译不起作用的功能向您发出警告
// 安装
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>
持续更新…