Vue2.0和3.0区别(打包时区别 测试环境和生产环境)及Vue3.0中setup()函数

一、项目初始化

2.0初始化,vue init <模板名称(webpack比较常用)> [项目名称]

vue init webpack cli2-test

3.0初始化,vue create [项目名称]

vue create cli3-test

二、目录结构对比

2.0目录结构

 3.0目录结构

 

三、打包时区别 测试环境和生产环境

3.0版本中项目环境变量配置文件没有了(dev.env.js / prod.env.js)

我们可以通过在项目根目录下手动创建不同环境的配置文件,具体的环境变量名称由package.json中运行参数决定,

下面举个例子添加(开发)development、(生产)production 和 (测试)test 版本的环境变量:

3.0版本中不同环境的webpack配置文件也没有了(webpack.base.conf.js / webpack.dev.conf.js / webpack.prod.conf.js)
同样,我们也可以在项目根目录中创建vue.config.js文件来进行webpack和vue的一些配置:

分析:在开发阶段,process.env.NODE_ENV是development,而打包build后,process.env.NODE_ENV是production,因此无法通过process.env.NODE_ENV来区分测试环境和生产环境,这时我们就需要增加变量(VUE_APP_CURRENTMODE)来区分。这就需要两个配置文件,在项目根目录下新建.env.test和.env.production两个文件。

 .env.development

NODE_ENV=development
VUE_APP_BASEURL=http://127.0.0.1:8989/

.env.production

NODE_ENV=production
VUE_APP_CURRENTMODE=production
VUE_APP_BASEURL=http://api.xxx/
outputDir=dist

.env.test

NODE_ENV=production
VUE_APP_CURRENTMODE=test
VUE_APP_BASEURL=http://api.text.xxx/
outputDir=dist-test

测试环境和正式环境一样都是需要打包所以变量NODE_ENV都是production,其中VUE_APP_CURRENTMODE是用于区分测试环境还是生产环境的变量,VUE_APP_BASEURL变量表示后端api接口地址,outputDir是打包后的输出目录(注意:需要在顶级配置文件vue.config.js(在项目根目录下新建)中配置输出目录,通过 process.env.outputDir 直接获取)

 配置完以上信息后,我们需要在package.json中配置脚本(scripts),用于打包执行的命令。

package.json (通过 --mode来运行不同的环境,打包时来 区别 测试环境和生产环境)

 

npm run serve        //本地运行
npm run build:test   //测试环境打包
npm run build        //正式环境打包
const BASE_URL = process.env.VUE_APP_BASEURL;  //使用参数获取请求接口地址

 四、main.js 文件

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

五、路由router文件

// 可以根据路由模式的不同,后面俩可以只引用一个
import { createRouter, createWebHistory, createWebHashHistory } from 'vue-router'
import Home from '@/views/Home.vue'
 
// 构建我们的页面路由配置,可以看到,这里和原来的写法并无二致。
const routes = [
  {
    path: '/',
    component: Home
  }, {
    path: '/about',
    component: () => import('@/views/About.vue'),
  }
]
 
const router = createRouter({
  // 使用 hash 模式构建路由( url中带 # 号的那种)
  history: createWebHashHistory(),
  // 使用 history 模式构建路由 ( url 中没有 # 号,但生产环境需要特殊配置)
  // history: createWebHistory(),
  routes
})
export default router

得益于 vue3.0 的特性,我们现在不用把组件内容全部包裹在某一个 div 下面了,一个 template 里面可以有多个根节点元素,是没有关系的。

About.vue

<template>
  这里是关于我们的页面
  <router-link to="/">点这里去首页</router-link>
</template>

App.vue

<template>
  <router-view />
</template>

在main.js挂载

import { createApp } from 'vue'
import App from './App.vue'
import router from './router'
 
// 将创建的 App 搞个别名
const app = createApp(App)
 
// 使用路由配置
app.use(router)
 
// 挂载运行
app.mount('#app')

六、setup() 函数

①Home.vue

<template>
  <router-link to="/about">点这里去关于我们页面</router-link>
  <div class="home">
    这里是一个计数器 >>> <span class="red">{{count}}</span> <br>
    <button @click="countAdd">{{btnText}}</button>
  </div>
</template>
 
<script>
// ref 是 vue 3.0 的一个重大变化,其作用为创建响应式的值
import { ref } from 'vue'
// 导出依然是个对象,不过对象中只有一个 setup 函数
export default {
  setup () {
    // 定义一个不需要改变的数据
    const btnText = '点这个按钮上面的数字会变'
    // 定义一个 count 的响应式数据,并赋值为 0
    const count = ref(0)
    // 定义一个函数,修改 count 的值。
    const countAdd = () => {
      count.value++
    }
    // 导出一些内容给上面的模板区域使用
    return {
      btnText,
      count,
      countAdd
    }
  }
}
</script>
<style lang="scss">
.home {
  line-height: 2;
  .red {
    color: red;
  }
}
</style>

首先,我们的组件不用写一堆东西了,只需要一个 setup 函数即可。

这样做得好处就是,我们可以把很多零碎的东西拆成公共组件,然后交给其他组件去调用。我写 vue 有一个痛苦的点就是很多的东西我想抽离成组件,但是一拆,就得有 data (), methods 等等一堆。因此,有时候就偷懒,懒得拆了。

现在好了,可以一个函数就是一个组件,多方便啊!

其次,在 setup 函数中 return 出去的东西,可以在模板区域直接使用,也不必理会 this 这个神奇的东西。

然后就是 ref 这个函数,我们可以从 vue 中引入它,它传入一个值作为参数,返回一个基于该值的 响应式 Ref 对象,该对象中的值一旦被改变和访问,都会被跟踪到,通过修改 count.value 的值,可以触发模板的重新渲染,显示最新的值。

②about.vue关于reactive

<template>
  <router-link to="/">点这里去首页</router-link>
  <hr>
  <dl>
    <dt>{{state.name}}</dt>
    <dd>性别:{{state.sex}}</dd>
    <dd>地址:{{state.address}}</dd>
  </dl>
  <button @click="addressChange">更新地址</button>
</template>
<script>
// reactive 是 vue 3.0 的一个重大变化,其作用为创建响应式的对象或数组
import { reactive } from 'vue'
// 导出依然是个对象,不过对象中只有一个 setup 函数
export default {
  setup () {
    // 定义一个 state 的响应式对象数据,并赋值
    const state = reactive({
      name: 'FungLeo',
      sex: 'boy',
      address: '上海'
    })
    console.log(state)
    // 定义一个函数,修改 state 的值。
    const addressChange = () => {
      state.address += '浦东'
    }
    // 导出一些内容给上面的模板区域使用
    return {
      state,
      addressChange
    }
  }
}
</script>

reactive 和 ref 的区别就是,reactive 是处理对象或者数组的。

③生命周期函数: 

setup() : 开始创建组件之前,在 beforeCreate 和 created 之前执行,创建的是 data 和 method 

 life.vue

<template>
  <router-link to="/">点这里去首页</router-link>
  <hr>
  <button @click="changeValue">改变值</button>
  <li>{{ name }}</li>
  <li>{{ age }}</li>
  <li>{{ sex }}</li>
  <div class="home">
    这里是一个计数器 >>> <span class="red">{{count}}</span> <br>
    <button @click="countAdd">点击加数字</button>
  </div>
</template>
<script>
// 你需要使用到什么生命周期,就引出来什么生命周期
import {
  onBeforeMount,
  onMounted,
  onBeforeUpdate,
  onUpdated,
  onBeforeUnmount,
  onUnmounted,
  onActivated,
  ref,
  reactive,
  toRefs
} from 'vue'
// 导出依然是个对象,不过对象中只有一个 setup 函数
export default { 
  setup () {
    const count = ref(0);
    // 定义一个函数,修改 count 的值。
    const countAdd = () => {
      count.value++
    }
    let obj = reactive({
      name: '张三',
      age: 30,
      sex: ''
    })
    let changeValue = ()=>{
      obj.name='李四';
      obj.age=40;
    }
    // 其他的生命周期都写在这里
    onBeforeMount (() => {
      count.value++
      console.log('onBeforeMount', count.value)
    })
    //组件挂载完成后执行的函数(只执行一次)
    onMounted (() => {
      count.value++
      console.log('onMounted', count.value)
    })
    //组件被激活时执行的函数(每次进去都执行)
    onActivated(() => {
      // console.log("刷新");
    });
    // 注意,onBeforeUpdate 和 onUpdated 里面不要修改值,会死循环的哦!
    onBeforeUpdate (() => {
      console.log('onBeforeUpdate', count.value)
    })
    onUpdated (() => {
      console.log('onUpdated', count.value)
    })
    onBeforeUnmount (() => {
      count.value++
      console.log('onBeforeUnmount', count.value)
    })
    onUnmounted (() => {
      count.value++
      console.log('onUnmounted', count.value)
    })   
    return {
      count,
      countAdd,
      ...toRefs(obj),
      changeValue
    }
  }
}
</script>

首先,在 vue 3.0 中,生命周期是从 vue 中导出引入的,我们需要用到哪些,就导出哪些。

可能不少看官会认为多次一举,但实则不然。vue 提供这么多的生命周期,有几个是我们常用的?在大多数的组件中,我们用不到生命周期。即便是页面级别的应用,可能用到最多的是 onMounted 即可。

当然,那些绑定时间的操作会用到解绑,因此会用到 onUnmounted。其它的生命周期,正常情况下是基本用不到的。所以,通过引入使用的这种设定,可以减少我们的最终编译的项目的体积。而且,这样的引入使用,更加的逻辑清晰。

其次,除 setup 之外,其他的生命周期函数,都是在 setup 里面直接书写函数即可。

Vue3中toRefs对数据进行解构,可以让页面上快速展示内容,toRefs可以把一个响应式对象转换为普通的对象,这样在视图上就可以不用一个个属性点(.) 这样麻烦,直接写上属性就可以,比如上面例子中的属性name,age,sex

④计算属性

computed.vue

<template>
  <router-link to="/">点这里去首页</router-link>
  <hr>
  <div class="home">
    这里是一个计数器 >>> <span class="red">{{count}}</span> <br>
    右边的数字是上面的数字的十倍 >>> <span class="red">{{bigCount}}</span> <br>
    右边的数字是上面的数字的一百倍 >>> <span class="red">{{computeCount['100x']}}</span> <br>
    右边的数字是上面的数字的一千倍 >>> <span class="red">{{computeCount['1000x']}}</span> <br>
    <button @click="countAdd">点这个按钮上面的数字会变</button>
  </div>
</template>
 
<script>
// 需要使用计算属性,也需要从 vue 中导出引入
import { ref, computed } from 'vue'
// 导出依然是个对象,不过对象中只有一个 setup 函数
export default {
  setup () {
    // 定义一个 count 的响应式数据,并赋值为 0
    const count = ref(0)
    // 定义一个函数,修改 count 的值。
    const countAdd = () => {
      count.value++
    }
    // 计算属性,使用计算函数并命名,然后在 return 中导出即可
    const bigCount = computed(() => {
      return count.value * 10
    })
    // 计算多个属性,可以通过返回一个对象的方式来实现
    const computeCount = computed(() => {
      return {
        '100x': count.value * 100,
        '1000x': count.value * 1000,
      }
    })
    // 导出一些内容给上面的模板区域使用
    return {
      count,
      countAdd,
      bigCount,
      computeCount
    }
  }
}
</script>

计算属性和生命周期一样,都是从 vue 中导出引入的。我们把计算属性当成一个函数来使用,直接 return 计算结果即可。 

七、setup() 函数语法糖<script setup>

与组件选项 setup 函数对比, <script setup> 的优点:

  • 更少、更简洁的代码,模板中不需要使用 return {} 暴露变量和方法了,使用组件时不需要主动注册了;
  • 更好的 Typescript 支持,使用纯 Typescript 声明 props 和抛出事件,不会再像 option api 里那么蹩脚了;
  • 更好的运行时性能;

模板中用到东西无需return

组件的自定义方法、定义的数据(响应式和非响应式)、引入的组件都可以直接在模板(template)中使用直接使用,无需return或者注册。

<template>
  <p>{{ num }}</p>
  <button @click="add">num++</button>
</template>

<script setup>
import { ref } from "vue";

const num = ref(0);
function add(){
   num.value++;
}
</script>
<style scoped>
</style>

ref解包

和从 setup() 函数中返回值一样,ref 值在模板中使用的时候会自动解包:

<template>
  <button @click="countAdd">{{ count }}</button>
</template>

<script setup>
import { ref } from 'vue';

const count = ref(0);
// 定义一个函数,修改 count 的值。
const countAdd = () => {
  count.value++
}
</script>

 

posted @ 2023-04-28 15:44  以德为先  阅读(1476)  评论(0编辑  收藏  举报