vue3.x(vue-cli@4.5) Typescript   element-ui-Plus 

vue3不适用2版本的element-ui,要使用https://element-plus.gitee.io/#/zh-CN/component/installation(element-ui-plus)

安装步骤:vue add element-plus

安装完: main.ts内会新增

import installElementPlus from './plugins/element'

const app = createApp(App)
installElementPlus(app)

把./plugins/element的element文件后缀改为ts

import ElementPlus from 'element-plus'
import 'element-plus/lib/theme-chalk/index.css'
import locale from 'element-plus/lib/locale/lang/zh-cn'

export default (app: any) => { // 加入any类型判断
  app.use(ElementPlus, { locale })
}

成功引入element-ui-plus

vue3写法,新特性

1、setup 函数 setup() 函数是 vue3 中,专门为组件提供的新属性。它为我们使用 vue3 的 Composition API 新特性提供了统一的入口

1.1 执行时机 setup 函数会在 beforeCreate 之后、created 之前执行

ref

示例

<!--在 template 中访问响应式数据,会默认加.value-->
<template>
  <div class="about">
    <h2>欢迎来到红浪漫狗子服务中心</h2>
    <el-button v-for="(item, index) in girls"
               :key="index"
               @click="selectGirlFn(index)">
      {{index}}号技师:{{item}}
    </el-button>
    <p>你选择了【{{selectGirl}}】为你服务</p>
  </div>
</template>

<script lang="ts">
import { Options, Vue } from 'vue-class-component'
import { defineComponent, ref, reactive } from 'vue'

import { defineComponent, ref } from 'vue'

export default defineComponent({
  name: 'about',
  setup () {
    const girls = ref(['大狗子', '二狗子', '三狗子'])
    const selectGirl = ref('')
    const selectGirlFn = (index: number) => {
      // 只在setup函数内部访问ref函数需要加.value
      selectGirl.value = girls.value[index]
    }

    return {
      girls,
      selectGirl,
      selectGirlFn
    }
  }
})
</script>

在 reactive 对象中访问 ref 创建的响应式数据

// template 渲染
<p>{{state.selectGirl}}</p>


setup () {
  const state = reactive({selectGirl})
  console.log(state.selectGirl) // 1
  return { state }
}

reactive toRefs

reactive可以声明变量,直接赋值,不要.value,但是它不是响应式的数据,需要使用toRefs,toRefs() 函数可以将 reactive() 创建出来的响应式对象,转换为普通的对象,只不过,这个对象上的每个属性节点,都是 ref() 类型的响应式数据

<p>{{ count }}</p>
<button @click="increment">+1</button>

import { toRefs, reactive } from 'vue'

setup() {
  const state = reactive({
    count: 0,
    naem: 'zs'
  })

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

  return {
    // 将 state 上的每个属性,都转化为 ref 形式的响应式数据
    ...toRefs(state),
    increment 
  }
}

生命周期,钩子函数

这些生命周期钩子注册函数只能在 setup() 期间同步使用, 因为它们依赖于内部的全局状态来定位当前组件实例(正在调用 setup() 的组件实例), 不在当前组件下调用这些函数会抛出一个错误。

写法

setup() {
    onMounted(() => {
      console.log('mounted!')
    })
    onUpdated(() => {
      console.log('updated!')
    })
    onUnmounted(() => {
      console.log('unmounted!')
    })
  },

与2对应

Vue2.x 的生命周期  |	Vue3.x 的生命周期
beforeCreate     |	使用 setup()
created     	 |  使用 setup()
beforeMount      |	onBeforeMount //组件挂载到节点上之前
mounted          |	onMounted //组件挂载完成后
beforeUpdate     |	onBeforeUpdate //组件更新之前
updated	         |  onUpdated // 组件更新完成后
beforeDestroy    |	onBeforeUnmount //组件卸载之前
destroyed        |	onUnmounted //组件卸载完成后
errorCaptured    |	onErrorCaptured //捕获一个来自子孙组件异常
                 | onActivated //被包含在<keep-alive></keep-alive>中的组件会多出两个生命周期钩子函数,被激活时执行
                 | onDeactivated // 比如a组件切换到b组件,a组件消失时执行
                

新增的钩子函数

除了与 Vue2.x 等效的生命周期之外,composition-api 还新增了以下生命周期钩子用作调试:

onRenderTracked onRenderTriggered 两个钩子函数都接收一个 DebuggerEvent :

export default {
  onRenderTriggered(e) {
    debugger
    // 检查哪个依赖性导致组件重新渲染
  },
}

原2.x钩子函数也能写,写在setup下面,setup()在beforeCreate之前执行。 只要用一种就行,如果混用,同类型的钩子setup里的比2.x的先执行

props(组件传值),context(上下文对象),

&&

Suspense(异步组件),teleport(自由组件)

<template>
  <teleport to="#modal">
    <el-dialog
      title="公告"
      v-model="isShow"
      width="30%"
      center>
      <Suspense>
        <template #default>
          <AsyncShow />
        </template>
        <template #fallback>
          <h3>loading...</h3>
        </template>
      </Suspense>
      <template #footer>
        <span class="dialog-footer">
          <el-button type="primary" @click="close">确 定</el-button>
        </span>
      </template>
    </el-dialog>
  </teleport>
</template>

<script lang="ts">
import { ref, watchEffect, onErrorCaptured } from 'vue'
import AsyncShow from '@/components/AsyncShow.vue'

export default {
  name: 'Modal',
  props: {
    isDialog: {
      type: Boolean,
      default: false
    }
  },
  components: {
    AsyncShow
  },
  setup(props: any, context: any) {
    const isShow = ref(false)
    watchEffect(() => {
      isShow.value = props.isDialog
    })
    const close = () => {
      context.emit('close')
    }
    onErrorCaptured((err) => { // 用来捕获异步请求的异常
      console.log(err)
      return true
    })
    return {
      isShow,
      close
    }
  },
}
</script>

<style lang="scss" scoped>

</style>

teleport 自由组件,可自由展示在想要地方

如index.html,或者其他任意地方

  <body>
    <noscript>
      <strong>We're sorry but <%= htmlWebpackPlugin.options.title %> doesn't work properly without JavaScript enabled. Please enable it to continue.</strong>
    </noscript>
    <div id="app"></div>
    <div id="modal"></div>
    <!-- built files will be auto injected -->
  </body>

watch, computed

setup () {
    const confirmVal = ref('粉红浪漫')
    const data = reactive({
     name: '秋梨膏',
     userList: [{name: '老司机', age: 99}]
    })
    
    const userInfo = computed(() => {
      return data.userList.find(item => item.name === '老司机')
    })
    
    
    //1.watch单个值
    watch(confirmVal, (newVal, oldVal) => {
        console.log(newVal, oldVal)
    })
    
    //2.watch多个值,对象某个属性,取值方法1
    watch([confirmVal, () => data.name], (newVal, oldVal) => {
        console.log(newVal[0], oldVal[0])
        console.log(newVal[1], oldVal[1])
    })
    
    //3.watch多个值,对象某个属性,取值方法2
    watch([confirmVal, () => data.name], [(newConVal, oldConVal), (newName, oldName)] => {
        console.log(newConVal, oldConVal)
        console.log(newName, oldName)
    })
    
    return {
        confirmVal,
        ...toRefs(data),
    }
}

Suspense异步组件

<Suspense>
    <template #default>
      <AsyncShow />
    </template>
    <template #fallback>
       <h3>loading...</h3>
    </template>
</Suspense>

AsyncShow组件,里是一个promise,如果我们要在等待组件获取数据并解析时显示“正在拼了命的加载…”之类的内容,则只需三个步骤即可实现Suspense。

将异步组件包装在<template #default>标记中 在我们的Async组件的旁边添加一个兄弟姐妹,标签为<template #fallback>。 将两个组件都包装在<suspense>组件中 使用插槽,Suspense将渲染后备内容,直到默认内容准备就绪。然后,它将自动切换以显示我们的异步组件。

==AsyncShow组件==

<template>
  <div>
    <h3>{{result}}</h3>
  </div>
</template>

<script lang="ts">
import { defineComponent } from 'vue'
export default defineComponent({
  name: 'AsyncShow',
  setup() {
    return new Promise((resolve, reject) => {
      setTimeout(() => {
        return resolve({result: '最新迎新年活动:单次消费满888元打88折!!!'})
      }, 1000);
    })
  }
})
</script>

router

import { useRouter } from 'vue-router'

const $router = useRouter()

$router.push('/home')

配合element-ui plus使用

一个登录功能如下:

<template>
  <div class="login">

    <el-form :model="form" 
             :rules="rules"
             ref="formRef" 
             label-width="60px"
             class="form">
      <el-form-item label="账号" prop="loginName">
        <el-input v-model="form.loginName" clearable placeholder="请输入账号">
          <template #suffix>
            <i class="el-input__icon el-icon-user"></i>
          </template>
        </el-input>
      </el-form-item>
      <el-form-item label="密码" prop="password">
        <el-input type="password" v-model="form.password" clearable placeholder="请输入密码">
          <template #suffix>
            <i class="el-input__icon el-icon-key"></i>
          </template>
        </el-input>
      </el-form-item>
      <el-form-item label="">
        <el-button class="login-btn" @click="login">登录</el-button>
      </el-form-item>
    </el-form>
  </div>
</template>
    
    
<script>
import { onMounted, reactive, ref, toRefs, defineComponent } from 'vue'
import { useRouter } from 'vue-router'
import { ElMessage } from 'element-plus'
import { LoginApi } from '@/apis'

import md5 from 'blueimp-md5'
import _ from 'lodash'
import $to from '@/utils/to'


export default defineComponent({
  name: 'Login',
  setup () {
    const $router = useRouter()
    const formRef = ref(null)

    const data = reactive({
      form: {
        loginName: '',
        password: '',
        logintype: 'local',
        url: window.location.href
      },
      bgType: 'wave',
      rules: {
        loginName: [
          { required: true, message: '请输入账号', trigger: 'blur' }
        ],
        password: [
          { required: true, message: '请输入密码', trigger: 'blur' }
        ]
      },
      login: () => {
        const params = {
          loginName: data.form.loginName,
          password: String(md5(data.form.password)).toUpperCase(),
          logintype: 'local',
          url: window.location.href
        }

        formRef.value.validate(async (valid) => {
          if (valid) {
            const [err, data] = await $to(LoginApi.login(params))

            if (err) {
              ElMessage.error(err.data && err.data.message || err.message)
            } else {
              $router.push('/home')
            }
          } else {
            return false
          }
        })
      }
    })

    return {
      ...toRefs(data),
      formRef
    }
  },
})
</script>

因element的form表单需要绑定ref,来实现调用表单方法,所以在 <el-form :model="form" :rules="rules" ref="formRef" label-width="60px" class="form">上绑定ref, 在setup中定义 const formRef = ref(null),关联起来,formRef.value即为form实例对象,和2.x的this.$refs.formRef同样了.当然使用reactive来声明变量也是一样结果,只是要同名

VueX

通过import {useStore} from 'vuex'获取vuex对象。 https://www.cnblogs.com/guiyishanren/p/10657910.html vuex教程文档\

import {useStore} from 'vuex'
import {onMounted} from 'vue'
setup(props, context) {
    
    
  	const store = useStore()
  	
	onMounted(() => {
    
    
		console.log(store.name)
		store.commit('show', '传值')
	})
  }
Logo

旨在为数千万中国开发者提供一个无缝且高效的云端环境,以支持学习、使用和贡献开源项目。

更多推荐