Quick Start
- Project source: github.com/Wscats/vue-…
This project comprehensively uses the new features of Vue3.0, suitable for beginners to learn 😁
- Based on the
Composition API
即Function-based API
Carry on the transformation, cooperateVue Cli
, priority experienceVue3
features - Use the singleton object pattern for component communication
- use
axios
Library makes network requests,weui
Libraries implement UI interfaces
# install dependencies
npm install
# Open localhost:8080 in your browser to view the page and hot update it in real time
npm run serve
# Release project
npm run build
Copy the code
It is recommended that the Visual Studio Code and Vue 3 Snippets Code plug-in consume ψ ( ̄∀ ̄) ψ.
Dependencies
The following are the dependencies used in the project. @vue/ composition-API and vUE module enable us to experience the new features of Vue3.0 first. Axios is a tool library to assist us in sending network requests to get data. Weui is a set of basic style library consistent with wechat’s native vision, which is convenient for us to quickly build project pages.
"@vue/composition-api": "^ 0.3.4"."axios": "^ 0.19.0"."core-js": "^ rule 3.4.3"."vue": "^ 2.6.10"."weui": "^ 2.1.3"
Copy the code
Directory Structure
├─ SRC │ ├─ App.vue # ├─ Assets # ├─ Stores/Index.js # State Management │ ├─ Components # │ │ ├─ app.vue # │ ├─ Search. Vue # │ │ ├─ Panel. Vue # List │ ├─ main.js # Public # Template File ├─ Vue.config.js # Scaffolding configuration file ├─ screenshots from screenshotsCopy the code
Composition API
npm install @vue/composition-api --save
Copy the code
After downloading the @vue/composition-api plug-in using the NPM command, you need to explicitly call vue.use (VueCompositionApi) after importing the module. Following the document reference in main.js turns on the Composition API’s ability.
// main.js
import Vue from 'vue'
import App from './App.vue'
// 1. Introduce the Composition API module
import VueCompositionApi from '@vue/composition-api'
Vue.config.productionTip = false
// 2. Don't forget to explicitly call VueCompositionApi
Vue.use(VueCompositionApi)
new Vue({
render: h= > h(App),
}).$mount('#app')
Copy the code
npm install weui --save
Copy the code
We also use NPM to install weui module, and then introduce weui base style library in main.js, so that we can use wechat base style globally to build project pages.
// main.js
import Vue from 'vue'
import App from './App.vue'
// Global introduction of 'weui' base style library
import 'weui'
import VueCompositionApi from '@vue/composition-api'
Vue.config.productionTip = false
Vue.use(VueCompositionApi)
new Vue({
render: h= > h(App),
}).$mount('#app')
Copy the code
Go back to app.vue, leave the components property value empty the contents of the
template, delete the
<template>
<div id="app">
Hello World
</div>
</template>
<script>
export default {
name: "app".components: {}};</script>
Copy the code
Create the first component in the SRC/Components directory and call it header. vue and write the following code:
<template>
<header :style="{ backgroundColor: color? color:defaultColor }">{{title}}</header>
</template>
<script>
import { reactive } from "@vue/composition-api";
export default {
// The parent component is passed in to change the header component's property value
props: {
/ / title
title: String./ / color
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>
Copy the code
setup
Here we use a new property setup, which is a component entry that allows us to use the new interface exposed by Vue3.0. It runs after the component is instantiated and the props property is defined. In Vue2.0’s beforeCreate and Created life cycles, setup returns an object, and all returned property values are merged into Vue2.0’s Render function. It will work with the contents of the
template to complete binding between Model and View, and should support returning JSX snippets in future versions.
<template>
<! -- View -->
<div>{{name}}</div>
</template>
<script>
import { reactive } from '@vue/composition-api'
export default {
setup() {
const state = reactive({ name: 'Eno Yao' });
// return is exposed to the template
return {
// Model. state } } }</script>
Copy the code
reactive
In the setup function, we have adapted the first interface of Vue3.0 to Reactive, which is to process your object by Proxy into a reactive object, similar to the data property of Vue2.0. It should be noted that the processed object is not equal to the original object, and the processed object belongs to the deeply cloned object.
const state = reactive({ name: 'Eno Yao' })
Copy the code
props
In Vue2.0 we can use the props property to communicate with each other. Here we need to define the props property to define the type of the accepted value. Then we can use the first parameter of setup to get the props use.
export default {
props: {
/ / title
title: String./ / color
color: String
},
setup(props) {
// Here we can use the props property passed by the parent component}};Copy the code
We can use this header component in app.vue. With the props above, we can make the header component behave differently depending on the values passed in.
<template>
<div id="app">
<! -- Reuse the component and pass in the props value to render the corresponding state of the component -->
<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>
Copy the code
context
The second argument to the setup function is a context object that contains some useful properties that can be accessed through this in Vue2.0. In Vue3.0, accessing them takes the following form:
setup(props, ctx) {
console.log(ctx) This is not accessible in the setup() function
console.log(this) // undefined
}
Copy the code
The following useful attributes can be accessed:
- root
- parent
- refs
- attrs
- listeners
- isServer
- ssrContext
- emit
After completing header. vue above, we’ll write the Search. Vue Search box component. Go ahead and create the Search.
<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="Search"
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>search</span>
</label>
</form>
<a @click="toggle" href="javascript:" class="weui-search-bar__cancel-btn" id="searchCancel">cancel</a>
</div>
</template>
<script>
import { reactive, toRefs, watch } from "@vue/composition-api";
import store from ".. /stores";
export default {
// Setup corresponds to the 2.x version of the beforeCreate life cycle
setup() {
// Reactive () receives a normal object and returns a reactive data object
const state = reactive({
searchValue: "".// Search the box for two states, focused and unfocused
isFocus: false.inputElement: null
});
// Switch the state of the search box
const toggle = (a)= > {
// Make the input box that appears after clicking on the search automatically focusstate.inputElement.focus(); state.isFocus = ! state.isFocus; };// Listen for the value of the search box
watch(
(a)= > {
returnstate.searchValue; = > {}, ()// Store the input box to the state Store center for component communication
store.setSearchValue(state.searchValue);
// window.console.log(state.searchValue);});return {
// Convert each attribute on state to reactive data in ref form. toRefs(state), toggle }; }};</script>
Copy the code
toRefs
ToRefs is a function that transforms a reactive object created by Reactive () into a normal object, but every attribute node on that object is reactive data of type REF (). With V-model instruction, two-way data binding can be completed, which is very efficient in development.
import { reactive, toRefs } from "@vue/composition-api";
export default {
setup() {
const state = reactive({ name: 'Eno Yao'})}return {
// Return state directly then the data will be non-responsive, MV one-way binding
/ /... state,
// toRefs wraps and returns state so that the data is responsive, MVVM bidirectional binding. toRefs(state), }; }Copy the code
template refs
The input box here has two states, one is the state with the input box and the state without the input box, so we need a Boolean value isFocus to control the state, encapsulating a toggle method to switch the isFocus value between the true and false states.
const toggle = (a)= > {
// the value of isFocus is reversedstate.isFocus = ! state.isFocus; };Copy the code
Then, with the V-bind :class directive, change the state of the search box by having wei-search-bar_focusing class names appear based on the isFocus value.
<div :class="['weui-search-bar', {'weui-search-bar_focusing' : isFocus}]" id="searchBar">
Copy the code
The search input box contains the V-model instruction to receive input from the user for later retrieval logic with the list component, and the REF attribute to get the element node of the tag. With the native method of state.inputelement. Focus (), the cursor will automatically focus on the input box when switching the state of the search box to enhance user experience.
<input
v-model="searchValue"
ref="inputElement"
/>
Copy the code
watch
The watch() function is used to monitor changes in certain data items to trigger certain operations. Before using the watch() function, you still need to import on demand, listen for changes in the searchValue, and then trigger the logic in the callback function, that is, listen for the retrieval value entered by the user. We then trigger the callback logic to store the searchValue value in the store object we created, and then communicate with the panel.vue list component after the aspect:
import { reactive, watch } from "@vue/composition-api";
import store from ".. /stores";
export default {
setup() {
const state = reactive({
searchValue: ""});// Listen for the value of the search box
watch(
(a)= > {
returnstate.searchValue; = > {}, ()// Store the input box to the state Store center for component communicationstore.setSearchValue(state.searchValue); });return{... toRefs(state) }; }};Copy the code
state management
Here we maintain a data store to manage shared state. That is, we create a new store.js that exposes a store object that shares the searchValue of the Panel and Search component. When the search. vue component receives the searchValue from the input box, it places it in the Store object of store.js, and then injects that object into the Search component, both components can share the value in the Store object. For debugging purposes we also wrapped setSearchValue and getSearchValue respectively to manipulate the Store object so that we could track state changes.
// store.js
export default {
state: {
searchValue: ""
},
// Set the search box value
setSearchValue(value) {
this.state.searchValue = value
},
// Get the value of the search box
getSearchValue() {
return this.state.searchValue
}
}
Copy the code
After completing the Search. Vue above, we will write the panel. vue Search box component, continue to create a new panel. vue file under SRC/Components folder, click to view the source code.
<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">To view more</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({
/ / number of pages
page: 1.// List data
news: [],
// Filter the bad list data by the value of the search box
newComputed: computed((a)= > {
// Check whether the input box entered filter criteria, if not return the original news array
if (store.state.searchValue) {
return state.news.filter(item= > {
if (item.title.indexOf(store.state.searchValue) >= 0) {
returnitem; }}); }else {
returnstate.news; }}),searchValue: store.state
});
// Send an Ajax request to get the list data
const loadMore = async() = > {// Get list data
let data = await axios.get("https://cnodejs.org/api/v1/topics", {
params: {
// Number of topics per page
limit: 10./ / number of pages
page: state.page
}
});
// Add pages
state.page += 1;
state.news = [...state.news, ...data.data.data];
};
onMounted((a)= > {
// The request is triggered when the first screen loads
loadMore();
});
return {
// Keep the data responsive. toRefs(state),// View more eventsloadMore }; }};</script>
Copy the code
lifecycle hooks
The lifecycle hooks of Vue3.0 are different from those of the previous versions. The new version is registered with the onXxx() function and also needs to introduce the corresponding lifecycle module locally:
import { onMounted, onUpdated, onUnmounted } from "@vue/composition-api";
export default {
setup() {
const loadMore = (a)= > {};
onMounted((a)= > {
loadMore();
});
onUpdated((a)= > {
console.log('updated! ')
})
onUnmounted((a)= > {
console.log('unmounted! ')})return{ loadMore }; }};Copy the code
Here is a comparison of the old and new versions’ lifecycles:
-> usebeforeCreate
setup()
-> usecreated
setup()
beforeMount
->onBeforeMount
mounted
->onMounted
beforeUpdate
->onBeforeUpdate
updated
->onUpdated
beforeDestroy
->onBeforeUnmount
destroyed
->onUnmounted
errorCaptured
->onErrorCaptured
The new version also provides two new life cycles to help debug code:
- onRenderTracked
- onRenderTriggered
In the Panel list component, we register the onMounted lifecycle and trigger the loadMore request method in it to fetch data from the back end to the data layer. Here we use the AXIos network request library, so we need to install this module:
npm install axios --save
Copy the code
Encapsulating a request list data method, the interface points to the API provided by the OFFICIAL website of Cnode, because axios returns a Promise, so with async and await can perfect write asynchronous logic, and then combined with onMounted life cycle trigger, Bind the method to the View layer’s See More button to complete the first load of the list and click to see more lazy loading.
// Send an Ajax request to get the list data
const loadMore = async() = > {// Get list data
let data = await axios.get("https://cnodejs.org/api/v1/topics", {
params: {
// Number of topics per page
limit: 10./ / number of pages
page: state.page
}
});
// Add pages
state.page += 1;
// Merge list data
state.news = [...state.news, ...data.data.data];
};
onMounted((a)= > {
// The request is triggered when the first screen loads
loadMore();
});
Copy the code
computed
Next, we use another attribute, computed attributes, similar to Vue2.0, and import this module on demand:
import { computed } from '@vue/composition-api';
Copy the code
There are two types of computing attributes: read-only computing attributes and read-write computing attributes:
// Read-only computing properties
let newsComputed = computed((a)= > news.value + 1)
// Can read and write
let newsComputed = computed({
// Evaluates the function
get: (a)= > news.value + 2.// The assignment function
set: val= > {
news.value = news.value - 3}})Copy the code
Here we use readable and writable computed properties to process list data. Remember our last component, search.vue, we can filter list data that is useful to our users by combining the Search values entered by the user in the Search box with computed properties. So we first get the searchValue shared by the search. vue Search box from the shared instance of store, and then use the native string method indexOf and array method filter to filter the list data. Then return the new list data, newsComputed, and render the new list data on the view layer with the V-for instruction. In this way, the original list data, NEWS, can be returned when there is no search box to retrieve values, and the new list data, newsComputed, can be returned when there is a search box to retrieve values.
import store from ".. /stores";
export default {
setup() {
const state = reactive({
// The original list data
news: [],
// Filter the new list data by the value of the search box
newsComputed: computed((a)= > {
// Check whether the input box entered filter criteria, if not return the original news array
if (store.state.searchValue) {
return state.news.filter(item= > {
if (item.title.indexOf(store.state.searchValue) >= 0) {
returnitem; }}); }else {
returnstate.news; }}),searchValue: store.state }); }}Copy the code
Program source code
If the articles and notes can help you or inspire you, please do not be too generous with your likes and stars, your will certainly be my biggest motivation 😁
- Github.com/Wscats/vue-…