最新公告
  • 欢迎您光临网站无忧模板网,本站秉承服务宗旨 履行“站长”责任,销售只是起点 服务永无止境!立即加入钻石VIP
  • Vue3.0 体验(API 及 TodoList Demo)

    正文概述 掘金(Alex丶Cheng)   2021-01-30   440

    前言

    记得有段时间特别想在Vue中玩TypeScript,但是 Vue2.x对 TypeScript 的支持并不是特别好,一种比较好的实现方式是通过 Vue Class Component 库去实现,主要是通过装饰器来对组件的行为进行修改,通过写Class组件的方式去写组件,从而加上 TypeScript。但是装饰器目前还只是提案,并没有正式纳入规范中。

    终于,2020.9.19凌晨,Vue3.0发布了,它的源码98%都是通过TypeScript写的,并且,通过组合式的方式去编写代码,几乎完美契合TypeScript的编码风格,我们可以随意的在Vue中写TypeScript,而不需要通过各种修饰或者插件去强行辅助我们写TS了。

    Vue3.0 部分 API 尝鲜

    createApp

    返回一个提供应用上下文的应用实例。应用实例挂载的整个组件树共享同一个上下文。可以在 createApp 之后链式调用其它方法。该函数第一个参数接收一个根组件选项的对象,第二个参数可以将 props 传递给应用程序

    createApp(
      App,
      {
        username: 'alex cheng' // 提供 props,App 组件内部通过 props: ['username'] 接收
      }
    ).mount('#app')
    

    provide / inject

    provide 和 inject 启用依赖注入。只有在使用当前活动实例的 setup() 期间才能调用这两者。

    // 父组件
    setup() {
      const globalData = reactive({
        name: 'alex.cheng'
      })
      
      provide('globalData', globalData)
    }
    
    // 子/孙 组件
    setup() {
      const globalData = inject('globalData')
    }
    

    注意: 可以在 setup 中获取,也可以在生命周期(onMounted/onBeforeMount)中获取。但是不能在方法中获取,比如点击事件在方法中打印,会是 undefined,并且Vue会给出警告。

    function showInject () {
      // 获取顶层组件的数据
      const globalObj = inject('globalObj')
      console.log(globalObj)
    }
    

    Vue3.0 体验(API 及 TodoList Demo)

    setup

    一个组件的选项,在创建组件之前执行,代替了beforeCreatecreated钩子函数。它有两个参数,第一个是 props,第二个是当前上下文context,用来代替以前的thisemit方法就挂载在context上。(优先于 data 方法执行)

    并作为组合式 API 的入口点,后续都会在这里做数据处理。

    defineComponent

    顾名思义,这是一个定义组件的方法,传递一个包含组件选项的对象

    import { defineComponent, h } from 'vue'
    
    const DefineComp = defineComponent({
      data () {
        return {
          count: 11
        }
      },
      render () {
        return h(
          'h1',
          {
            class: 'define-comp'
          },
          `${this.count}`
        )
      }
    })
    

    或者是一个setup函数(函数名将作为组件名来使用)

    import { defineComponent, ref } from 'vue'
    
    const HelloWorld = defineComponent(function HelloWorld() {
      const count = ref(0)
      return { count }
    })
    

    getCurrentInstance

    getCurrentInstance 支持访问内部组件实例,用于高阶用法或库的开发。只能在 setup 或生命周期钩子中调用。

    const MyComponent = {
      setup() {
        const internalInstance = getCurrentInstance() // works
    
        const id = useComponentId() // works
    
        const handleClick = () => {
          getCurrentInstance() // doesn't work
          useComponentId() // doesn't work
    
          internalInstance // works
        }
    
        onMounted(() => {
          getCurrentInstance() // works
        })
    
        return () =>
          h(
            'button',
            {
              onClick: handleClick
            },
            `uid: ${id}`
          )
      }
    }
    
    // 在组合式函数中调用也可以正常执行
    function useComponentId() {
      return getCurrentInstance().uid
    }
    

    watch

    Vue3中的 watch 方法和 Vue2 中的watch不太一样,它的第一个参数是要监听的对象,第二个参数是回调函数((newVal, oldVal) => {}),第三个参数是监听属性({ immediate, deep })

      watch(
        () => state.list.length, // 监听 list 数组的长度
        (v = 0) => {
          state.nums = v // 当数组的长度发生变化,将 nums 的值修改
        },
        { immediate: true } // 立即执行
      )
    

    computed

    使用 getter 函数,并为从 getter 返回的值返回一个不变的响应式 ref 对象。

    const count = ref(0)
    const plusOne = computed(() => count.value + 1)
    
    plusOne.value++ // error
    

    如果需要修改计算属性,就需要加上 setter 函数

    onst count = ref(1)
    const plusOne = computed({
      get: () => count.value + 1,
      set: val => {
        // 直接计算 count.value
        count.value = val - 1
      }
    })
    

    watchEffect

    在响应式地跟踪其依赖项时立即运行一个函数,并在更改依赖项时重新运行它。

    reactive | ref

    创建响应式对象或者基础类型变量

    toRef | toRefs | unRef

    快速使用Vue3最新的15个常用API

    TodoList Demo

    每次学习一门新的语言或者一些新的 API, TodoList demo 肯定是跑不掉的。

    看看如何用 Vue3 的 Composition API 来实现一个 todolist demo 吧!

    需求

    界面大概是这样的!

    Vue3.0 体验(API 及 TodoList Demo)

    看到这个界面,大概可以拆分成三个组件,一个是包含输入框和添加按钮的组件(TodoAdd.vue),然后是过滤的组件(TodoFilter.vue),最后是列表组件(TodoList.vue),不过 Todolist 还可以继续拆分,将每条任务当成一个组件(TodoListItem.vue)。

    毫无疑问,这三个组件理应被容器组件(App.vue)包裹起来,并且初始化各功能组件的数据。代码如图:

    Vue3.0 体验(API 及 TodoList Demo)

    Vue3 中最重要的思想就是 Composition API,通过组合的方式,更容易抽离出逻辑处理,并拆分逻辑与结构,降低代码的耦合性。

    如何初始化界面的数据呢 ?

    我们已经知道 setup 方法相当于 Vue2 中的 beforeCreatecreated 钩子,那么在这里我们可以做数据初始化的工作。

    首先,我们在 src 下面创建 composables 文件夹,文件夹下面放组件可能需要用到的逻辑或者方法。接着我们创建一个 useTodo.js 文件,它的作用是获取任务列表,操作列表(添加,删除)。

    // src/composables/useTodos.js
    
    export default function useTodos() {
      const todos = ref([]);
      // 添加 todo
      const addTodo = (todo) => todos.value.push(todo);
    
      // 删除 todo
      const deleteTodo = (id) => {
        const Index = todos.value.findIndex(todo => todo.id === id)
        todos.value.splice(Index, 1)
      }
    
      // 获取远程 todos
      const fetchTodos = async () => {
        const response = await fetch(
          "https://jsonplaceholder.typicode.com/todos?_limit=5"
        );
        const rawTodos = await response.json()
        todos.value = rawTodos.map((todo) => ({
          id: todo.id,
          content: todo.title,
          completed: todo.completed,
        }));
      };
    
      onMounted(() => {
        fetchTodos();
      });
    
      // 返回列表数据,以及操作方法,这里返回的东西,将会在 setup 方法中通过 return 暴露出去
      return {
        todos,
        addTodo,
        deleteTodo
      };
    }
    

    接着回到 App.vue 中,在 setup 方法中,使用 useTodos.js 中的数据和方法。

    setup() {
      // 拿到 todo 清单,以及向 todo 清单添加任务的方法
      const {todos, addTodo, deleteTodo} = useTodos()
    
      return {
        todos,
        addTodo,
        deleteTodo
      }
    }
    

    todos 数据 和 deleteTodo 方法就可以当作 props 传递给 todolist 组件了,addTodo 方法就传递给 todoAdd 组件。

    Vue3.0 体验(API 及 TodoList Demo)

    // todoAdd.vue
    
    setup(props, context) {
      return useEmitAddTodo(context.emit);
    }
    
    // 我们还可以创建组件专属的 composable logic
    function useEmitAddTodo(emit) {
      const todoContent = ref("");
    
      const emitAddTodo = () => {
        if (todoContent.value === '') {
          return alert('请填写明确的任务!')
        }
        const todo = {
          id: Math.random(),
          content: todoContent.value,
          completed: false,
        };
        
        // 通过 emit 方法,调用传递给当前组件的方法
        emit("add-todo", todo);
        todoContent.value = "";
      };
    
      return {
        todoContent,
        emitAddTodo,
      };
    }
    
    

    接着,我们在 composables 文件夹下创建 useFilteredTodo.js 文件,里面存放处理过滤列表的方法和过滤之后的数据。

    // src/composables/useFilteredTodo.js
    
    
    export default function useFilteredTodos(todos) {
      // 通过 ref 创建一个响应式的变量 filter
      const filter = ref("all");
    
      // 过滤 todo
      const filteredTodos = computed(() => {
        switch (filter.value) {
          case "done":
            return todos.value.filter((todo) => todo.completed);
          case "todo":
            return todos.value.filter((todo) => !todo.completed);
          default:
            return todos.value;
        }
      });
    
      return { filter, filteredTodos };
    }
    

    然后在 TodoFilter.vue 组件中导入进去,代码如下:

    结构如下:

    <template>
      <div class="filters">
        <span
          v-for="filter in filters"
          :key="filter.value"
          @click="$emit('change-filter', filter.value)"
          class="filter"
          :class="{ active: selected == filter.value }"
          >{{ filter.label }}</span
        >
      </div>
    </template>
    

    逻辑部分:通过 emit 调用 change-filter 方法,将当前点击的 state 传递出去,改变 useFilteredTodos 中的 filter,由于过滤后的数据,是通过计算属性来处理的,所以当 filter 发生改变,那么计算属性就会重启计算,拿到新的 todo list 数据!

    export default {
      name: "TodoFilter",
      props: ["selected"],
      setup() {
        const filters = reactive([
          { label: "全部", value: "all" },
          { label: "已完成", value: "done" },
          { label: "未完成", value: "todo" },
        ]);
    
        return { filters };
      },
    };
    

    到此,基本上就完成了TodoList Demo 了,通过 Composition API 的方式,我们可以更方便的去组合代码。以前我们将方法都放在 methods 里面,当我们的代码量越来越大的时候,我们就只能通过搜索的方式,在代码里面反复横跳。特别是接手了别人的代码,这种现象尤为明显。

    源码链接:戳这里

    推荐阅读

    • 快速使用Vue3最新的15个常用API
    • TypeScript支持
    • 面向未来的前端构建工具-vite

    下载网 » Vue3.0 体验(API 及 TodoList Demo)

    常见问题FAQ

    免费下载或者VIP会员专享资源能否直接商用?
    本站所有资源版权均属于原作者所有,这里所提供资源均只能用于参考学习用,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担。更多说明请参考 VIP介绍。
    提示下载完但解压或打开不了?
    最常见的情况是下载不完整: 可对比下载完压缩包的与网盘上的容量,若小于网盘提示的容量则是这个原因。这是浏览器下载的bug,建议用百度网盘软件或迅雷下载。若排除这种情况,可在对应资源底部留言,或 联络我们.。
    找不到素材资源介绍文章里的示例图片?
    对于PPT,KEY,Mockups,APP,网页模版等类型的素材,文章内用于介绍的图片通常并不包含在对应可供下载素材包内。这些相关商业图片需另外购买,且本站不负责(也没有办法)找到出处。 同样地一些字体文件也是这种情况,但部分素材会在素材包内有一份字体下载链接清单。
    模板不会安装或需要功能定制以及二次开发?
    请QQ联系我们

    发表评论

    还没有评论,快来抢沙发吧!

    如需帝国cms功能定制以及二次开发请联系我们

    联系作者

    请选择支付方式

    ×
    迅虎支付宝
    迅虎微信
    支付宝当面付
    余额支付
    ×
    微信扫码支付 0 元