Vue3实战系列:结合 Ant-Design-of-Vue 实践 Composition API

入口页面

首先映入眼帘的是 main.js 的变化:

// Vue 3.0

import { createApp } from 'vue'

import App from './App.vue'

import './index.css'

createApp(App).mount('#app')

// Vue 2.x

import Vue from 'vue'

import App from './App.vue'

new Vue({

  render: h => h(App)

}).$mount('#app')

第一段代码是 Vue 3 的创建 Vue 实例形式,通过 createApp 的形式,你别说,和 React 真的挺像的😄。

第二段是 Vue 2.x 的创建 Vue 实例形式,通过 new 的形式创建。

添加路由 Vue-Router

截止目前,vue-router-next 更新到了 v4.0.0-beta.12 版本。

你如果用 cnpm install vue-router 安装路由,是会下载到 vue-router 3.x 的版本,我们需要使用:

cnpm install vue-router@next -S

安装完毕之后,我们开始配置项目路由,在 src 目录下新建 rourer 文件夹,在文件夹下新建 index.js 文件,添加如下内容:

import {createRouter, createWebHashHistory} from 'vue-router'

export default createRouter({

  history: createWebHashHistory(),

  routes: []

})

Vue 2.x 的路由模式通过 mode 选项为 history 或 hash 去控制。

而在 Vue 3 中,通过 createRouter 创建路由实例,history 属性作为控制路由模式的参数,createWebHashHistory 方法返回的是 hash 模式,createWebHistory 返回的是 history 模式,本项目采用 hash 模式。

同样,我们需要在 mian.js 中引入 router 实例:

import { createApp } from 'vue'

import App from './App.vue'

import router from './router'

import './index.css'

createApp(App).use(router).mount('#app')

添加全局状态 Vuex

vuex 更新到了 v4.0.0-beta.4 版本,所以我们需要用如下指令安装:

cnpm i vuex@next -S

接下来在 src 目录下创建 store 文件夹,再新建 index.js 文件,添加代码如下:

// Vue 3

import { createStore } from 'vuex'

export default createStore({

  state() {

    return {

      author: "十三",

    };

  },

});

对比 Vue 2.x 写法:

// Vue 2.x

import Vuex from 'vuex'

Vue.use(Vuex)

export default new Vuex.Store({

  state,

  mutations,

  actions,

  modules: {}

})

同样是使用新的写法,通过 vuex 内部抛出的 createStore 方法,创建一个 Vuex 实例。

接下来我们将它引入到 main.js 中:

import { createApp } from 'vue'

import App from './App.vue'

import router from './router'

import store from './store'

import './index.css'

// 链式调用

createApp(App).use(router).use(store).mount('#app')

引入 Antd for Vue3 版本组件库

Antdv2.x是唐金州老师(杭州校宝在线)研发的新一代适配 Vue 3.0 的组件库,我们来尝尝鲜,这边我们通过如下命令后下载:

cnpm i --save ant-design-vue@next -S

在 mian.js 内引入 ant-design-vue 组件如下所示:

import { createApp } from 'vue'

import Antd from 'ant-design-vue';

import App from './App.vue'

import router from './router'

import store from './store'

import 'ant-design-vue/dist/antd.css';

import './index.css'

// 本教程采用的是全局引入组件库

createApp(App).use(router).use(store).use(Antd).mount('#app')

测试一下是否成功,顺便解释一下 Vue 3 如何声明变量,以及如何通过方法改变变量,代码如下:

<template>

  <a-button @click="add" type="primary">

    点我加{{ count }}

  </a-button>

  <a-button @click="add2('a')" type="primary">

    点我加a{{ state.a }}

  </a-button>

  <a-button @click="add2('b')" type="primary">

    点我加b{{ state.b }}

  </a-button>

</template>

<script>

import { ref, reactive } from 'vue'

export default {

  setup() {

    const count = ref(0)

    const state = reactive({

      a: 0,

      b: 0,

    })

    const add = () => {

      count.value += 1

    }

    const add2 = (type) => {

      state[type] += 1

    }

    return {

      state,

      count,

      add,

      add2

    }

  }

}

</script>

如上述代码所示,Vue 3 新增的 setup 方法,颠覆了之前传统的 options 属性方式,我们可以将业务逻辑都写在 setup 方法中。

我们有两种声明变量的形式:

ref:它用于声明简单的基础类型变量,如单个数字、boolean、字符串等等。

reactive:它用于对象引用类型的复杂变量。

所有声明好的变量和方法,如果想在 template 模板里使用的话,必须在 setup 方法里 return,否则无法调用。记住返回什么就是声明,如返回 count,模板中就用 {{ count }},返回 state,模板中就使用 {{ state.a }} 。效果如下所示:

待办事项 TODO

首先我们新建 views 文件夹用于放置页面组件,在 views 内新建 todo.vue 文件,如下所示:

<template>

  <div id="components-layout-demo-basic">

    <a-layout>

      <a-layout-header>待办事项</a-layout-header>

      <a-layout-content>内容</a-layout-content>

    </a-layout>

  </div>

</template>

<script>

import { ref, reactive } from 'vue'

export default {

  setup() {

  }

}

</script>

<style scoped>

  #components-layout-demo-basic {

    min-height: 100vh;

    max-width: 40%;

    margin: 0 auto;

    background-color: #ededed;

  }

  #components-layout-demo-basic .ant-layout-header,

  #components-layout-demo-basic .ant-layout-footer {

    background: #7dbcea;

    text-align: center;

    color: #fff;

  }

</style>

引入 antd-v 的布局组件,再给一些基础样式。

然后前往 App.vue 和 router/index.js 做如下改动:

// App.vue

<template>

  <router-view></router-view>

</template>

<script>

export default {

  name: 'App'

}

</script>

import {createRouter, createWebHashHistory} from 'vue-router'

export default createRouter({

  history: createWebHashHistory(),

  routes: [

    {

      path: '/todo',

      component: () => import('../views/todo.vue')

    }

  ]

})

最后页面出现如下所示,代表配置成功:

添加新增待办事项输入框:

<template>

  <div id="components-layout-demo-basic">

    <a-layout>

      <a-layout-header>待办事项</a-layout-header>

      <a-layout-content>

        <a-input-search

          v-model:value="todo"

          placeholder="请输入要代办的事项"

          size="large"

          @search="addTodo"

        >

          <template v-slot:enterButton>

            <a-button>新增</a-button>

          </template>

        </a-input-search>

      </a-layout-content>

    </a-layout>

  </div>

</template>

<script>

import { ref, reactive } from 'vue'

import { ref, reactive } from 'vue'

export default {

  setup() {

    const todo = ref('')

    const addTodo = (value) => {

      console.log(value)

    }

    return {

      todo,

      onSearch

    }

  }

}

</script>

如下图所示:

添加“待办事项”和“已办事项”模板,代码如下:

<template>

  <div id="components-layout-demo-basic">

    <a-layout>

      <a-layout-header>待办事项</a-layout-header>

      <a-layout-content>

        <a-input-search

          v-model:value="todo"

          placeholder="请输入要代办的事项"

          size="large"

          @search="addTodo"

        >

          <template v-slot:enterButton>

            <a-button>新增</a-button>

          </template>

        </a-input-search>

        <h2 class="title">待办事项</h2>

        <a-card title="标题">

          <template v-slot:extra>

            <a-switch />

          </template>

          内通

        </a-card>

        <h2 class="title">已办事项</h2>

        <a-card title="标题">

          <template v-slot:extra>

            <a-switch />

          </template>

          内通

        </a-card>

      </a-layout-content>

    </a-layout>

  </div>

</template>

<script>

import { ref, reactive } from 'vue'

export default {

  setup() {

    const todo = ref('')

    const addTodo = (value) => {

      console.log(value)

    }

    return {

      todo,

      onSearch

    }

  }

}

</script>

<style scoped>

  #components-layout-demo-basic {

    min-height: 100vh;

    max-width: 40%;

    margin: 0 auto;

    background-color: #ededed;

  }

  #components-layout-demo-basic .ant-layout-header,

  #components-layout-demo-basic .ant-layout-footer {

    background: #7dbcea;

    color: #fff;

    text-align: center;

  }

  .title {

    margin: 0;

    padding: 10px;

  }

</style>

效果如下:

接下来我们来添加代办的相应逻辑:

<template>

  <div id="components-layout-demo-basic">

    <a-layout>

      <a-layout-header>待办事项</a-layout-header>

      <a-layout-content>

        <a-input-search

          v-model:value="todo"

          placeholder="请输入要代办的事项"

          size="large"

          @search="addTodo"

        >

          <template v-slot:enterButton>

            <a-button>新增</a-button>

          </template>

        </a-input-search>

        <h2 class="title">待办事项</h2>

        <a-card :title="`${index + 1}、${item.time}`" v-for="(item, index) in todos" :key="item.id">

          <template v-slot:extra>

            <a-switch v-model:checked="item.done" @change="handleCheck(item, true)" />

          </template>

          {{ item.content }}

        </a-card>

        <h2 class="title">已办事项</h2>

        <a-card :title="`${index + 1}、${item.time}`" v-for="(item, index) in dones" :key="item.id">

          <template v-slot:extra>

            <a-switch v-model:checked="item.done" @change="handleCheck(item, false)" />

          </template>

          内通

        </a-card>

      </a-layout-content>

    </a-layout>

  </div>

</template>

<script>

import { ref, reactive, computed } from 'vue'

export default {

  setup() {

    const todo = ref('')

    const time = `${new Date().getFullYear()}-${new Date().getMonth()}-${new Date().getDate()}`

    const state = reactive({

      todoList: [

        {

          id: 1,

          done: false,

          time: time,

          content: '前往老八食堂,共进午餐'

        },

        {

          id: 2,

          done: false,

          time: time,

          content: '和giao哥合唱一曲'

        },

        {

          id: 3,

          done: false,

          time: time,

          content: '做点阳间的需求'

        }

      ]

    })

    // 添加待办事项

    const addTodo = (value) => {

      if(!value) {

        message.error('请输入待办事项')

        return

      }

      state.todoList.push({

        content: value,

        id: Date.now(),

        time: time,

        done: false

      })

      todo.value = ''

    }

    // 通过计算属性,计算出生成的代办事项列表

    const todos = computed(() => {

      return state.todoList.filter(item => !item.done)

    })

    // 通过计算属性,计算出生成的已办列表

    const dones = computed(() => {

      return state.todoList.filter(item => item.done)

    })

    // 修改状态方法

    const handleCheck = (item ,status) => {

      item.done = status

    }

    return {

      todo,

      addTodo,

      state,

      todos,

      dones,

      handleCheck

    }

  }

}

</script>

<style scoped>

  #components-layout-demo-basic {

    min-height: 100vh;

    max-width: 40%;

    margin: 0 auto;

    background-color: #ededed;

  }

  #components-layout-demo-basic .ant-layout-header,

  #components-layout-demo-basic .ant-layout-footer {

    background: #7dbcea;

    color: #fff;

    text-align: center;

  }

  .title {

    margin: 0;

    padding: 10px;

  }

</style>

深圳网站建设www.sz886.com

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 157,198评论 4 359
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 66,663评论 1 290
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 106,985评论 0 237
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,673评论 0 202
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 51,994评论 3 285
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,399评论 1 211
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,717评论 2 310
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,407评论 0 194
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,112评论 1 239
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,371评论 2 241
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 31,891评论 1 256
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,255评论 2 250
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 32,881评论 3 233
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,010评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,764评论 0 192
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,412评论 2 269
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,299评论 2 260