Playing Skill: Vue3.0 comprehensive exploration of new features - to quickly build project based on real Composition Api

Personal blog navigation page (click on the right link to open a personal blog): Daniel take you on technology stack 

The project integrated use of  Vue3.0 new features.

  • Based  Composition API That  Function-based API transformation, with  Vue Clipriority to experience the  Vue3 characteristics
  • Singleton object model components to communicate
  • Use  axios library network request, weui library implementation UI interface
# 安装依赖
npm install
# 在浏览器打开localhost:8080查看页面,并实时热更新
npm run serve
# 发布项目
npm run build

Recommend to use with Visual Studio Code and  Vue 3 Snippets  plug-in code

Dependencies

Here's what to use to rely on, @vue/composition-api with  vue module allows us  Vue2.0 version can be the first to experience the  Vue3.0 new features, axios it is to assist our network request to get the data of the tool library weuiis a set of consistent with the micro-channel native visual basic style library, help us to quickly build project page.

"@vue/composition-api": "^0.3.4",
"axios": "^0.19.0",
"core-js": "^3.4.3",
"vue": "^2.6.10",
"weui": "^2.1.3"

Directory Structure

├── src
│   ├── App.vue                          # 组件入口
│   ├── assets                           # 资源目录
│   ├── stores/index.js                  # 状态管理
│   ├── components                       # 组件目录
│   │   ├── Header.vue                   # 头部组件
│   │   ├── Search.vue                   # 搜索框组件
│   │   ├── Panel.vue                    # 列表组件
│   ├── main.js                          # 项目入口
├── public                               # 模板文件
├── vue.config.js                        # 脚手架配置文件
├── screenshot                           # 程序截图

Composition API

npm install @vue/composition-api --save

Use  npm command to download a  @vue/composition-api later plug-in, after the introduction of the module, need to explicitly call  Vue.use(VueCompositionApi) , according to the document  main.js cited it opens up  Composition API the ability.

// main.js
import Vue from 'vue'
import App from './App.vue'
// 1.引入Composition API模块
import VueCompositionApi from '@vue/composition-api'

Vue.config.productionTip = false
// 2.不要漏了显式调用 VueCompositionApi
Vue.use(VueCompositionApi)

new Vue({
  render: h => h(App),
}).$mount('#app')
npm install weui --save

We also use the  npm installation  weui module, then  main.js introduced  weuithe basis of style library, we can easily build the project page using the micro-channel basis in the global style.

// main.js
import Vue from 'vue'
import App from './App.vue'
// 全局引入 `weui` 的基础样式库
import 'weui'
import VueCompositionApi from '@vue/composition-api'

Vue.config.productionTip = false
Vue.use(VueCompositionApi)

new Vue({
  render: h => h(App),
}).$mount('#app')

Back to  App.vueretain  components the attribute value to empty  <template> the contents of the template, delete the  <style> template, waiting for re-introduction of new components.

<template>
  <div id="app">
    Hello World
  </div>
</template>
<script>
export default {
  name: "app",
  components: {}
};
</script>

In  src/components the first new component directory, the name is  Header.vue written to the following code:

<template>
  <header :style="{
    backgroundColor: color?color:defaultColor
  }">{{title}}</header>
</template>
<script>
import { reactive } from "@vue/composition-api";
export default {
  // 父组件传递进来更改该头部组件的属性值
  props: {
    // 标题
    title: String,
    // 颜色
    color: String
  },
  setup() {
    const state = reactive({
      defaultColor: "red"
    });
    return {
      ...state
    };
  }
};
</script>
<style scoped>
header {
  height: 50px;
  width: 100%;
  line-height: 50px;
  text-align: center;
  color: white;
}
</style>

setup

Here the use of a new property  setup , which is a component of the entrance, so that we can use  Vue3.0 the exposed new interface that runs in the component is instantiated when, props after the property is defined, essentially equivalent to  Vue2.0 release  beforeCreate and  Created these two lives period, setup returns an object, the value of all property to be returned inside, will be merged into  Vue2.0 the  render rendering function which, in a single-file assembly, it will be with the  <template> contents of the template, complete  Model the  View binding between the next version it should also support the return  JSX code snippet.

<template>
  <!-- View -->
  <div>{{name}}</div>
</template>
<script>
import { reactive } from '@vue/composition-api'
export default {
  setup() {
    const state = reactive({ name: 'Eno Yao' });
    // return 暴露到 template 中
    return {
      // Model
      ...state
    }
  }
}
</script>

reactive

In the  setup function inside, we adapt to the new interface, Vue3.0 first of  reactive which mainly deal with it through your object  Proxy processing becomes a responsive object, similar to the  Vue2.0 version  data attribute should be noted that the object after processing with the original objects are not equal, and the object belonging to the target depth of the processed clones.

const state = reactive({ name: 'Eno Yao' })

props

In  Vue2.0 we can use the  props property values Sons complete communication, where we need to define  props the attribute values to define the type accepted, then we can use  setup the acquired first parameter  props used.

export default {
  props: {
    // 标题
    title: String,
    // 颜色
    color: String
  },
  setup(props) {
    // 这里可以使用父组件传过来的 props 属性值
  }
};

We  App.vue can use inside the head assembly, with the above  props we can based on the value passed in, so that the head assembly presents a different state.

<template>
  <div id="app">
    <!-- 复用组件,并传入 props 值,让组件呈现对应的状态 -->
    <Header title="Eno" color="red" />
    <Header title="Yao" color="blue" />
    <Header title="Wscats" color="yellow" />
  </div>
</template>
<script>
import Header from "./components/Header.vue";
export default {
  name: "app",
  components: {
    Header,
  }
};
</script>

context

setup The second parameter is a function of context object, context object that contains a number of useful properties, which in  Vue2.0 the need  this to have access to, in  vue3.0 , accessing them into the following form:

setup(props, ctx) {
  console.log(ctx) // 在 setup() 函数中无法访问到 this
  console.log(this) // undefined
}

Specific access to the following useful properties:

  • root
  • parent
  • refs
  • attrs
  • listeners
  • isServer
  • ssrContext
  • emit

Completion of the above  Header.vue we can write  Search.vue the search box components, and then continue  src/components folder below the new  Search.vue document, click View Source .

<template>
  <div :class="['weui-search-bar', {'weui-search-bar_focusing' : isFocus}]" id="searchBar">
    <form class="weui-search-bar__form">
      <div class="weui-search-bar__box">
        <i class="weui-icon-search"></i>
        <input
          v-model="searchValue"
          ref="inputElement"
          type="search"
          class="weui-search-bar__input"
          id="searchInput"
          placeholder="搜索"
          required
        />
        <a href="javascript:" class="weui-icon-clear" id="searchClear"></a>
      </div>
      <label @click="toggle" class="weui-search-bar__label" id="searchText">
        <i class="weui-icon-search"></i>
        <span>搜索</span>
      </label>
    </form>
    <a @click="toggle" href="javascript:" class="weui-search-bar__cancel-btn" id="searchCancel">取消</a>
  </div>
</template>
<script>
import { reactive, toRefs, watch } from "@vue/composition-api";
import store from "../stores";
export default {
  // setup相当于2.x版本的beforeCreate生命周期
  setup() {
    // reactive() 函数接收一个普通对象,返回一个响应式的数据对象
    const state = reactive({
      searchValue: "",
      // 搜索框两个状态,聚焦和非聚焦
      isFocus: false,
      inputElement: null
    });
    // 切换搜索框状态的方法
    const toggle = () => {
      // 让点击搜索后出现的输入框自动聚焦
      state.inputElement.focus();
      state.isFocus = !state.isFocus;
    };
    // 监听搜索框的值
    watch(
      () => {
        return state.searchValue;
      },
      () => {
        // 存储输入框到状态 store 中心,用于组件通信
        store.setSearchValue(state.searchValue);
        // window.console.log(state.searchValue);
      }
    );
    return {
      // 将 state 上的每个属性,都转化为 ref 形式的响应式数据
      ...toRefs(state),
      toggle
    };
  }
};
</script>

toRefs

We can see the top with a lot of new properties, we first introduced  toRefs , the function can be  reactive() created out of responsive objects, converted into ordinary objects, but each attribute node on the object, is  ref() the type of responsive data, with  v-model instructions to complete the two-way data binding, in the development of very efficient.

import { reactive, toRefs } from "@vue/composition-api";
export default {
  setup() {
    const state = reactive({ name: 'Eno Yao' })
  }
  return {
    // 直接返回 state 那么数据会是非响应式的, MV 单向绑定
    // ...state,
    // toRefs 包装后返回 state 那么数据会是响应式的, MVVM 双向绑定
    ...toRefs(state),
  };
}

template refs

Here input box has two states, a state that has no input box and input box state, so we need a boolean value  isFocus to control the state, it encapsulates a  toggle way to let  isFocus the value of true and false switching two states.

const toggle = () => {
  // isFocus 值取反
  state.isFocus = !state.isFocus;
};

Then with the  v-bind:class instructions, let  weui-search-bar_focusing the class name based on  isFocus the value of the decision whether to appear, thereby changing the status of the search box.

<div :class="['weui-search-bar', {'weui-search-bar_focusing' : isFocus}]" id="searchBar">

Here the search input box into  v-model instructions for receiving user input information, to facilitate later retrieval logic performed with the list of components, but also into  ref property, for obtaining the  <input/> element node tag, with the state.inputElement.focus() native methods in the search box to switch when the state of the input box cursor autofocus enhance the user experience.

<input
  v-model="searchValue"
  ref="inputElement"
/>

watch

watch() Function is used to monitor changes in certain data items, thus triggering certain operations, before using the on-demand or need to import, monitor  searchValue the changes, then the trigger logic inside the callback function, i.e. the value entered by the user to retrieve the listener, then triggers the callback function logic  searchValue value stored into our create  store objects inside, rear, and aspects  Panel.vue list data communication components:

import { reactive, watch } from "@vue/composition-api";
import store from "../stores";
export default {
  setup() {
    const state = reactive({
      searchValue: "",
    });
    // 监听搜索框的值
    watch(
      () => {
        return state.searchValue;
      },
      () => {
        // 存储输入框到状态 store 中心,用于组件通信
        store.setSearchValue(state.searchValue);
      }
    );
    return {
      ...toRefs(state)
    };
  }
};

state management

Here we maintain a shared data management status, which means that we create a new  store.js expose a  store target share  Panel and  Search component  searchValue values, when the  Search.vue components received from the input box  searchValue to retrieve values, you put  store.js the  store object, then the object injected into the  Search assembly, the two assemblies can share  store the value of the object, in order to facilitate debugging we also were encapsulated  setSearchValue and  getSearchValue come operating the  store objects, so that we can track the change in the state.

// store.js
export default {
    state: {
        searchValue: ""
    },
    // 设置搜索框的值
    setSearchValue(value) {
        this.state.searchValue = value
    },
    // 获取搜索框的值
    getSearchValue() {
        return this.state.searchValue
    }
}

Completion of the above  Search.vue we immediately write  Panel.vue the search box components, and then continue  src/components folder under a new  Panel.vue file.

<template>
  <div class="weui-panel weui-panel_access">
    <div v-for="(n,index) in newComputed" :key="index" class="weui-panel__bd">
      <a href="javascript:void(0);" class="weui-media-box weui-media-box_appmsg">
        <div class="weui-media-box__hd">
          <img class="weui-media-box__thumb" :src="n.author.avatar_url" alt />
        </div>
        <div class="weui-media-box__bd">
          <h4 class="weui-media-box__title" v-text="n.title"></h4>
          <p class="weui-media-box__desc" v-text="n.author.loginname"></p>
        </div>
      </a>
    </div>
    <div @click="loadMore" class="weui-panel__ft">
      <a href="javascript:void(0);" class="weui-cell weui-cell_access weui-cell_link">
        <div class="weui-cell__bd">查看更多</div>
        <span class="weui-cell__ft"></span>
      </a>
    </div>
  </div>
</template>
<script>
import { reactive, toRefs, onMounted, computed } from "@vue/composition-api";
import axios from "axios";
import store from "../stores";
export default {
  setup() {
    const state = reactive({
      // 页数
      page: 1,
      // 列表数据
      news: [],
      // 通过搜索框的值去筛选劣列表数据
      newComputed: computed(() => {
        // 判断是否输入框是否输入了筛选条件,如果没有返回原始的 news 数组
        if (store.state.searchValue) {
          return state.news.filter(item => {
            if (item.title.indexOf(store.state.searchValue) >= 0) {
              return item;
            }
          });
        } else {
          return state.news;
        }
      }),
      searchValue: store.state
    });
    // 发送 ajax 请求获取列表数据
    const loadMore = async () => {
      // 获取列表数据
      let data = await axios.get("https://cnodejs.org/api/v1/topics", {
        params: {
          // 每一页的主题数量
          limit: 10,
          // 页数
          page: state.page
        }
      });
      // 叠加页数
      state.page += 1;
      state.news = [...state.news, ...data.data.data];
    };
    onMounted(() => {
      // 首屏加载的时候触发请求
      loadMore();
    });
    return {
      // 让数据保持响应式
      ...toRefs(state),
      // 查看更多事件
      loadMore
    };
  }
};
</script>

lifecycle hooks

Vue3.0 The life cycle of the hook and not the same as before, the new version are based on  onXxx() the function registered, the same need to introduce the life cycle of corresponding local modules:

import { onMounted, onUpdated, onUnmounted } from "@vue/composition-api";
export default {
  setup() {
    const loadMore = () => {};
    onMounted(() => {
      loadMore();
    });
    onUpdated(() => {
      console.log('updated!')
    })
    onUnmounted(() => {
      console.log('unmounted!')
    })
    return {
      loadMore
    };
  }
};

The following is a comparison of the old and new versions of the life cycle:

  • <s>beforeCreate</s> -> use setup()
  • <s>created</s> -> use setup()
  • beforeMount -> onBeforeMount
  • mounted -> onMounted
  • beforeUpdate -> onBeforeUpdate
  • updated -> onUpdated
  • beforeDestroy -> onBeforeUnmount
  • destroyed -> onUnmounted
  • errorCaptured -> onErrorCaptured

While the new version also offers two new lifecycle helps us to debug the code:

  • onRenderTracked
  • onRenderTriggered

In the  Panel list of components, we registered  onMounted lifecycle and trigger inside the request method  loadMore to get data from back-to-data layer, we use here is the  axios network request to the library, so we need to install the module:

npm install axios --save

A method of encapsulating data list request, the interface points to  Cnode official website provides  API , due  axios returns  Promise , so mating  async and  await perfectly prepared asynchronous logic, and then combined with onMounted the life cycle of the trigger, and the method to bind to the view button for more layer on the list for the first time to complete loading and click to see more lazy loading functionality.

// 发送 ajax 请求获取列表数据
const loadMore = async () => {
  // 获取列表数据
  let data = await axios.get("https://cnodejs.org/api/v1/topics", {
    params: {
      // 每一页的主题数量
      limit: 10,
      // 页数
      page: state.page
    }
  });
  // 叠加页数
  state.page += 1;
  // 合并列表数据
  state.news = [...state.news, ...data.data.data];
};
onMounted(() => {
  // 首屏加载的时候触发请求
  loadMore();
});

computed

Then we use another property  computed to calculate property, with  Vue2.0 very similar use, also need to import the module as needed:

import { computed } from '@vue/composition-api';

Calculating two types of properties, and the read-only attribute calculation readable and writable calculated properties:

// 只读计算属性
let newsComputed = computed(() => news.value + 1)
// 可读可写
let newsComputed = computed({
  // 取值函数
  get: () => news.value + 2,
  // 赋值函数
  set: val => {
    news.value = news.value - 3
  }
})

Here we use to read and write property calculation processing table data, on a component we remember  Search.vue it, we can combine retrieve the value entered by the user in the search box, with the  computed calculated attributes to the list of useful filter our data users, so we first from  store examples of shared get inside  Search.vue the search box is shared  searchValue , and a method using a primary string  indexOf and array method  filter to filter data list, and return to the list of new data  newsComputed, and in the view layer with  v-for instructions to render the new data list, to do so either return to the original list of data when we do not retrieve the value of the search box  news , and returns a new list of data when there is a search box to retrieve the value  newsComputed.

import store from "../stores";
export default {
  setup() {
    const state = reactive({
      // 原列表数据
      news: [],
      // 通过搜索框的值去筛选后的新列表数据
      newsComputed: computed(() => {
        // 判断是否输入框是否输入了筛选条件,如果没有返回原始的 news 数组
        if (store.state.searchValue) {
          return state.news.filter(item => {
            if (item.title.indexOf(store.state.searchValue) >= 0) {
              return item;
            }
          });
        } else {
          return state.news;
        }
      }),
      searchValue: store.state
    });
  }
}

Attached Java / C / C ++ / machine learning / Algorithms and Data Structures / front-end / Android / Python / programmer reading / single books books Daquan:

(Click on the right to open there in the dry personal blog): Technical dry Flowering
===== >> ① [Java Daniel take you on the road to advanced] << ====
===== >> ② [+ acm algorithm data structure Daniel take you on the road to advanced] << ===
===== >> ③ [database Daniel take you on the road to advanced] << == ===
===== >> ④ [Daniel Web front-end to take you on the road to advanced] << ====
===== >> ⑤ [machine learning python and Daniel take you entry to the Advanced Road] << ====
===== >> ⑥ [architect Daniel take you on the road to advanced] << =====
===== >> ⑦ [C ++ Daniel advanced to take you on the road] << ====
===== >> ⑧ [ios Daniel take you on the road to advanced] << ====
=====> > ⑨ [Web security Daniel take you on the road to advanced] << =====
===== >> ⑩ [Linux operating system and Daniel take you on the road to advanced] << = ====

There is no unearned fruits, hope you young friends, friends want to learn techniques, overcoming all obstacles in the way of the road determined to tie into technology, understand the book, and then knock on the code, understand the principle, and go practice, will It will bring you life, your job, your future a dream.

Published 47 original articles · won praise 0 · Views 276

Guess you like

Origin blog.csdn.net/weixin_41663412/article/details/104877320