vite2 + vue3 项目简易入门和使用经验总结

项目dome地址

gitee.com/Jaction/vit…

vite

cn.vitejs.dev/

Vue3.0 && Vue3.0初体验 一 juejin.cn/post/684790…

安装

cn.vitejs.dev/guide/#scaf…

yarn create @vitejs/app
 

vite.config.js

import {
	defineConfig
} from 'vite'
import vue from '@vitejs/plugin-vue'
const path = require('path')

// https://vitejs.dev/config/
export default defineConfig({
	resolve: {
		alias: {
			// 键必须以斜线开始和结束
			"@": path.resolve(__dirname, "./src"),
		}
	},
	base: './',
	outDir: 'dist',
	plugins: [vue()]
})

 

环境配置

第一种:

yarn add cross-env -D


  "scripts": {
    "dev": "cross-env NODE_ENV=development vite",
    "build": "cross-env NODE_ENV=development vite build",
    "build": "cross-env NODE_ENV=production vite build",
    "serve": "vite preview"
  },
 

第二种:


  "scripts": {
    "dev": "vite --mode development",
    "build:uat": "vite build --mode staging",
    "build:prd":"vite build --mode production",
    "serve": "vite preview"
  },
 
# .env.development
NODE_ENV=development
VITE_APP_TITLE=My App (staging)
 
# .env.staging
NODE_ENV=production
VITE_APP_TITLE=My App (staging)
 
# .env.production
NODE_ENV=production
VITE_APP_TITLE=My App (staging)
 

VITE_ 是必写

使用

let title = import.meta.env.VITE_APP_TITLE
 

教程

setup 函数

setup 函数是一个新的Vue组件, 是Composition API 入口

<template>
</template>
<script>
import { setup } from 'vue'
export default {
   setup(props, context) {
       //这里的props大家应该知道是啥吧,父组件传的值
       // context是什么?
       //在setup()里我们不能用this
       //所以vue2.0里的 this.$emit, this.$psrent, this.$refs在这里都不能用了。
       //context就是对这些参数的集合
       //context.attrs
       //context.slots
       //context.parent 相当于2.0里 this.$psrent
       //context.root 相当于2.0里 this
       //context.emit 相当于2.0里 this.$emit
       //context.refs 相当于2.0里 this.$refs
       ...
   }
}
</script>
<style>
</style>
 

路由router / 路由参数route

import { useRouter, useRoute } from 'vue-router'
import { setup } from 'vue'
export default {
	setup(props, context) {
    // 获取参数
    const route = useRoute()
    const { id } = route.query
    // 路由钩子函数
    const router = useRouter()
    router.beforeEach((to, from) => {
      if (to.meta.index > from.meta.index) {
        state.transitionName = 'slide-left' // 向左滑动
      } else if (to.meta.index < from.meta.index) {
        // 由次级到主级
        state.transitionName = 'slide-right'
      } else {
        state.transitionName = ''   // 同级无过渡效果
      }
    })
    
    const onAdd = () => {
      router.push({ path: '/address-edit', query: { type: 'add', from: state.from }})
    }
    
    return {
      onAdd
    }
    
  }
}
 

声明变量 ref reactive

ref 和 reactive 一样都是实现响应式数据的方法

  • reactive 必须传递一个对象
  • ref() 声明单一基础数据类型时使用 blog.csdn.net/weixin_4329…
import { setup, Reactive, torefs } from 'vue'
export default {
   setup(props, context) {
     		let count = ref(0) // ref(初始值)   无初始值设置为null
    		let name = ref('jeff')
        const obj = reacttive({
        data1: '123',
        data2: {}
    })
    
    return {
      count,
      name,
      ...torefs(obj)// 把obj转为响应式的ref,不然template里获取不到
    }
   }
}
 

Dom

<div class="search-wrap" ref="searchWrap">
</div>
import { onMounted } from 'vue'
export default {
  setup() {
    const searchWrap = ref(null)
    onMounted(async () => {
      let $screenHeight = document.documentElement.clientHeight
      console.log('searchWrap.value', searchWrap.value)
      searchWrap.value.style.height = $screenHeight - 100 + 'px'
    })
    
    return {
      searchWrap
    }
  }
}
 

nextTick

export default {
  setup() {
    nextTick(()=> {
      
    })
  }
}
 

方法函数 method

在vue3.0没有methods方法

方法也要放在return 里面

export default {
  setup() {
    // 方法 一
    const goToDetail = (item) => {
      router.push({ path: `/product/${item.goodsId}` })
    }

    // 方法 二
    const tips = () => {
      Toast('敬请期待');
    }
    
    return {
      goToDetail
      tips
    }
  }
}
 

components / props

写法vue 2.0一样

import ziComp from './ziComp.vue'
import { setup } from 'vue'
export default {
  props: ['val'], //这里获取props和 2.0 一样,也可以用对象形式
  components: {
      ziComp
  }, //components方法也是和2.0相同
  setup(props, context) {
      const value = ref(props.val)
      
      const goBack = ()=> {
        if (!props.val) {
          // 处理
        }
      }
      
      return {
        value
        goBack
      }
  }
}
 

emit 事件

// 父级组件
<s-header :name="'生成订单'" @callback="deleteLocal"></s-header>

// 子级组件
<div>{{name}}</div>

export detault {
  props: {
    name: {
      type: String,
      default: ''
    },
    back: {
      type: String,
      detault: ''
    }
  },
  emits: ['callback'],
  setup(props, ctx) {
    const goBack = () => {
      if (!props.name) {
        router.go(-1)
      } else {
        router.push({ path: props.back })
      }
      ctx.emit('callback')
    }
    
    return {
      goBack
    }
    
 	}
}
 

watchEffect 监听 props

<template>
 <div>{{obj.data1}}</div>
</template>
<script>
import { Reactive, watchEffect } from 'vue'
export default {
  props: ['val'], //这里获取props和 2.0 一样,也可以用对象形式
  setup(props, context) {
     watchEffect(() => {  //首次和props改变才会执行这里面的代码
         console.log(props.val)
     })
  }
}
</script>
<style>
</style>
 

watch() 监听器

import { Reactive } from 'vue'
export detault {
  setup(props, context) {
    	let count = ref(0)
      let state = reactive({
        count2: 1
      })
      
      //监听ref类型
      watch(count, (countNew, preCount)) => { //count新值, preCount旧值(count)
        console.log('') //这里是监听数据变化后执行的函数
      }
      
      //监听reactive类型
      watch(()=> state.count2, (count2New, preCount)=> {
        console.log('') //这里是监听数据变化后执行的函数
      }, {lazy: false}) // //在第一次创建不监听
    
    	
  }
  return {
       count
    	 countNew,
    	 count2New
       ...toRefs(state)
   }
}
 

监听多个数据

import { setup, Reactive } from 'vue'
export default {
  setup(props, context) {
   let count1 = ref(0)
    let name1 = ref(0)
   let state = reactive({
      count2: 0,
      name2: 'yangy'
   )
    //监听多个reactive类型
   watch(
       [() => state.count2, () => state.name2]
       ([count, name], [preCount, preName]) => { //count新值, preCount旧值
           console.log('') //这里是监听数据变化后执行的函数
       }, 
       {
          lazy: false
   })//在第一次创建不监听
   
   //监听ref类型
  watch(
       [count2, name2]
       ([count, name], [preCount, preName]) => { //count新值, preCount旧值
           console.log('') //这里是监听数据变化后执行的函数
       }, {lazy: false}//在第一次创建不监听)
   
   return {
       count,
       ...toRefs(state)
   }
  }
}
 

computed()计算属性

可创建只读,和可读可写两种

import { setup, Reactive } from 'vue'
export default {
  setup(props, context) {
   let count = ref(0)
   
  setup () {
    	const state = reactive({
        list: []
      })
      const count = ref(0)
      const addCount = computed(() => count.value + 1) //只读 ,count.value变化后执行加1
      
      const addCount2 = computed({
          get:() => count.value + 1,
          set: (value) => count.value = value 
      })    
      // addCount2.value = 10   //赋值方法
      
      const total = computed(() => {
        let sum = 0
        let _list = state.list.filter(item => state.result.includes(item.cartItemId))
        _list.forEach(item => {
          sum += item.goodsCount * item.sellingPrice
        })
        return sum
      })
      
     return {
       	 total
         count
         addCount
         addCount2
     }
  }
  }
}
 

script setup

<HelloWorld></HelloWorld>
<div @click='doClick'></div>
<script setup>
import HelloWorld from './components/HelloWorld.vue'
import msg from "./components/msg.vue"
// props
import { defineProps, defineEmit } from "vue";// props emit
let props = defineProps({
msg: String,
});
let emit = defineEmit(['callback'])
// 事件
function doClick() {
}
// 获取上下文
import {useContext} from 'vue'
// 生命周期 和 声明
import { reactive, onMounted } from "vue";
const msg = ''
const state = reactive({
mag: "我爱祖国"
});
onMounted(()=> {
initData()
})
const	initData = ()=> {
console.log(state.mag)
}
// 类似vue2.0的this, script setup中vue提供getCurrentInstance proxy
import { reactive, onMounted, getCurrentInstance } from "vue";
const { proxy } = getCurrentInstance();
const init = () => {
proxy.$alert('这是一段内容', '标题名称', {
confirmButtonText: '确定',
callback: action => {
proxy.$message({
type: 'info',
message: `action: ${ action }`
});
}
});
};
// 获取路由 和 路由参数
import { reactive, onMounted, getCurrentInstance } from "vue";
const { proxy } = getCurrentInstance();
const init = () => {
let { id } = proxy.$route.query
}
// 或者利用 useRoute useRouter
import { useRoute, useRouter } from 'vue-router'
const route = useRoute()
let { id } = route.query
</script>

vue3生命周期

import { onMounted, onUpdated, onUnmounted } from 'vue'

除去 beforeCreatecreated 之外,在我们的 setup 方法中,有9个旧的生命周期钩子,我们可以在setup 方法中访问

  • onBeforeMount
  • onMounted
  • onBeforeUpdate
  • onUpdated
  • onBeforeUnmount
  • onUnmounted
  • onActivated
  • onDeactivated
  • onErrorCaptured

我们导入它们并在我们的代码中访问它们

import { onBeforeMount, onMounted, onBeforeUpdate, onUpdated, onBeforeUnmount, onUnmounted, onActivated, onDeactivated, onErrorCaptured } from 'vue'
export default {
setup() {
onBeforeMount(() => {
// ... 
})
onMounted(() => { // 异步
// ... 
})
onBeforeUpdate(() => {
// ... 
})
onUpdated(() => {
// ... 
})
onBeforeUnmount(() => {
// ... 
})
onUnmounted(() => {
// ... 
})
onActivated(() => {
// ... 
})
onDeactivated(() => {
// ... 
})
onErrorCaptured(() => {
// ... 
})
}
  • beforeCreate -> use setup()
  • created -> use setup()
  • beforeMount -> onBeforeMount
  • mounted -> onMounted
  • beforeUpdate -> onBeforeUpdate
  • updated -> onUpdated
  • beforeDestroy -> onBeforeUnmount
  • destroyed -> onUnmounted
  • errorCaptured -> onErrorCaptured

store状态管理

yran add vuex@4.0.0-beta.4

index.js

state.js

mutation.js

action.js

// index.js
import { createStore } from 'vuex'
import state from './state'
import actions from './actions'
import mutations from './mutations'
export default createStore({
state,
mutations,
actions,
modules: {}
})
// state.js
export default {
cartCount: 0
}
// mutation.js
export default {
addCart (state, payload) {
state.cartCount = payload.count
}
}
// action.js
import { getCart } from '../service/cart'
export default {
async updateCart(ctx) {
const { data } = await getCart()
ctx.commit('addCart', {
count: data.length || 0
})
}
}
// main.js
import App from './App.vue'
import store from './store'
const app = createApp(App) // 创建实例
app.use(store)
app.mount('#app')

页面中

import { useStore } from 'vuex'
export detault {
setup() {
const store = useStore()
onMounted(()=> {
store.dispatch('updateCart')
})
const handleAddCart = async () => {
store.dispatch('updateCart')
})
return {
handleAddCart
}
}
}

vue-jsx

yarn add @vitejs/plugin-vue-jsx

// vite.config.js
import {
defineConfig
} from 'vite'
import vue from '@vitejs/plugin-vue'
import vueJxs from '@vitejs/plugin-vue-jsx'
// https://vitejs.dev/config/
export default defineConfig({
plugins: [vue(), vueJxs()]
})
// setup写法
<script lang='jsx'>
import { ref } from 'vue'
export default {
setup() {
let counter = ref(0)
let onclick = ()=> {
counter.value ++
}
return ()=> {
<>
<div>comp</div>
<p onClick={onclick}>{counter.value}</p>
</>
}
}
}
</script>

mock数据

yarn add vite-plugin-mock -D

yarn add mockjs -S

// vite.config.js
// vite.config.js
import {
defineConfig
} from 'vite'
import vue from '@vitejs/plugin-vue'
import vueJxs from '@vitejs/plugin-vue-jsx'
import { viteMockServe } from 'vite-plugin-mock';
// https://vitejs.dev/config/
export default defineConfig({
plugins: [vue(), vueJxs(), viteMockServe({ supportTs: false })]
})

在根目录新建mock

比如新建js文件,比如user.js

export default [
{
url: '/api/createUser',
method: 'post',
response: ({ body }) => {
console.log('body>>>>>>>>', body);
return {
code: 0,
message: 'ok',
data: null,
};
},
},
];

role.js

export default [
{
url: '/api/getRoleById',
method: 'get',
response: ({ query }) => {
console.log('id>>>>>>>>', query.id);
return {
code: 0,
message: 'ok',
data: {
roleName: 'admin',
roleValue: 'admin',
},
};
},
},
];

vue-router

yarn add vue-router@next -S

router/index.js

import { createRouter, createWebHashHistory } from "vue-router";
const router = createRouter({
history: createWebHashHistory(),
routes: [
{
path: "/",
component: () => import("../views/index.vue"),
},
],
});
export default router
import { createApp } from "vue";
import App from "./App.vue";
import router from "./router/index";
const app = createApp(App)
app.use(router)
app.mount("#app");

vuex

yarn add vuex@nest -S

// store/index.js
import { createStore } from 'vuex'
export detault createStore({
state: {
counter: 0
},
mutations: {
add(state)=> {
state.counter ++
}
}
})
import { createApp } from "vue";
import App from "./App.vue";
import store from './store'
const app = createApp(App)
app.use(store)
app.mount("#app");
<p @click="$store.commit('add')">
{{$store.state.counter}}
</p>

样式管理

安装 sass

yarn add sass -D

  @import './element-ui.scss'
@import './index.scss'
@import './mixin.scss'
@import './sidebar.scss'

styles目录保存各种样式

element-ui.scss

index.scss

mixin.scss

sidebar.scss

打包build

yarn build

构建打包后,直接在浏览器打开会报cors错误

直接放在服务器就不会报错,正常运行

blog.csdn.net/sayyy/artic…

npm install http-server -g
http-server [path] [options]

直接进入打包后dist文件中,执行http-server命令(默认8080)

直接打开http://127.0.0.1:8080/index.html#/

原创文章,作者:我心飞翔,如若转载,请注明出处:https://www.pipipi.net/14665.html

发表评论

登录后才能评论