Introduction to Vue3.0 + Vant3.0 mobile terminal practice (2) Carousel diagram module packaging and homepage improvement

Following the previous article, the previous article introduced the environment construction and completed the navigation bar module at the bottom, and then continue to improve the home page.

Let's first come to the final renderings:

Record the problems encountered before, the img image src in Vue becomes the problem that "[object Module]" cannot be loaded correctly.

I used "imgUrl" in the js code of the vue project = I require('../asserts/image.png')这种形式。checked a lot of information on the Internet, saying that it is because the file-loader uses the ES module syntax by default, that is import '../image.png'; however, Vue generates the CommonJS module syntax, that is require('../image.png'), the two are inconsistent. Either let file-loader or url-loader adopt CommonJS syntax, or let Vue adopt ES syntax.

But I searched for various files in the project, and couldn't find the option to change esModule: false, so I gave up temporarily.

In the end, I found a compromise. Local images and css resources are placed in the public directory, so that's it.

The local css file is loaded in the index.html file, such as:

 <link rel="icon" href="<%= BASE_URL %>favicon.ico">
 <link rel="stylesheet" href="<%= BASE_URL %>css/font_nbicon.css">

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width,initial-scale=1.0">
    <link rel="icon" href="<%= BASE_URL %>favicon.ico">
	<link rel="stylesheet" href="<%= BASE_URL %>css/font_nbicon.css">
    <title>物联网报警系统</title>
  </head>
  <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>
    <!-- built files will be auto injected -->
  </body>
</html>

The following is the package of the carousel picture module, the local picture is placed in the public directory, and the path can be directly imported when using it:

Create a new Swiper.vue component in the components directory:

<template>
  <van-swipe class="my-swipe" :autoplay="3000" indicator-color="#1baeae">
    <van-swipe-item v-for="(item, index) in list" :key="index">
      <img :src="item.imgUrl" alt="暂无图片">
    </van-swipe-item>
  </van-swipe>
</template>

<script>
export default {
  props: {
    list: Array
  },
  methods: {
   
  }
}
</script>

<style lang='less' scoped>
  .my-swipe {
	  display: flex;
	  flex-shrink: 0;
	  flex-wrap: wrap;
	  width: 100%;
	  padding-top: 45px;
    img {
      width: 100%;
      height: 100%;
    }
  }
</style>

style adjusts the less wording of the interface,

 display: flex; means to use flex layout.

 padding-top: 45px; set aside 45px for the titile on the top of the carousel.

A list is added to the props property of js, the type is Array, which is used as a subcomponent to receive properties.

Next, take a look at how to use it in Home.vue:

import swiper from '@/components/Swiper'

Import it first, and register the components in the components of export default.

Use this in the template tag: <swiper :list="swiperList"></swiper>

Note that setup(), ref, torefs, and reactive are all new usages of Vue3, and setup is a major feature function of Vue3.

The setup function is a function between the two hook functions of the life cycle function beforeCreate and Created.

The setup function is the entry point of the Composition API (composition API).

The variables and methods defined in the setup function finally need to be returned, otherwise they cannot be used in the template.

When the setup function is executed, the Created life cycle method has not been executed, so in the setup function, the variables and methods of data and methods cannot be used.

The setup function can only be synchronous and not asynchronous.

The difference between the old Vue2.0 Options API and the new Vue3.0 Composition API

Vue2.0 Options API convention:

We need to set the receiving parameters in props

We need to set variables in data

We need to set the calculated properties in computed

We need to set the monitoring properties in the watch

We need to set the event method in methods

You will find that Options API has agreed where we should do what we should do, which on the contrary also forces us to split the code to a certain extent.

Now with the Composition API, there is no such agreement anymore, so the code organization is very flexible, and our control code can be written in the setup.

The setup function provides two parameters props and context. The important thing is that there is no this in the setup function. In vue3.0, accessing them becomes the following form: this.xxx=》context.xxx

We don't have this context and the mandatory code separation of the Options API. The Composition API gives us a broader world.

Next, let's talk about ref and reactive. Vue3 was released on the evening of September 18th. The official declaration of reactive data in vue3 gave two methods, ref() and reactive().

Two-way data binding, Vue provides a total of two types of data response monitoring, a bit of React Hooks. The ref function passes in a value as a parameter and returns a responsive Ref object based on the value. Once the value in the object is changed and accessed, it will be tracked, just like our rewritten sample code, by modifying count. The value of value can trigger the re-rendering of the template and display the latest value.
In fact, in addition to the ref function, Vue3.0 also provides another function that can create a reactive object, that is, the reactive function. Let's talk about why we need to provide two APIs

The ref writing method is simple, but it also has drawbacks. After trying it was found that it can only monitor some simple data such as numbers, strings, and Booleans.

Ref modification data needs to use the form of count.value=xxx , while reactive only needs to use state.reactiveField=value.

Reactive needs toRefs to convert into reactive objects when returning.

The toRefs function can transform the reactive object created by reactive into an ordinary object, and each node on this object is a ref() type of reactive data.

In Vue, you can directly use ref (in the template), and Vue will automatically add .value. The use of ref in Js requires .value.

The setup function must have a return value, it must return an object.

The setup function has a props parameter, which is used to receive props, which is the property defined on the component (same as vue2), but the received props must be defined in the props property first, otherwise it will not be received.

All the life cycle writing of vue2 is compatible with vue3, and in vue3, the life cycle is added with the on prefix, which needs to be imported and written in the setup() function.

<template>
	<div>
		<header class="home-header wrap" :class="{'active' : headerScroll}">
		  <div class="header-search">
		    <span class="app-name">物联网报警系统</span>
		  </div>
		</header>
		 <nav-bar />
		 <swiper :list="swiperList"></swiper>
		 <div class="category-list">
		   <div v-for="item in categoryList" v-bind:key="item.categoryId" @click="tips">
		     <img :src="item.imgUrl">
		     <span>{
   
   {item.name}}</span>
		   </div>
		 </div>
	</div>
</template>

<script>
import navBar from '@/components/NavBar'
import swiper from '@/components/Swiper'
import { getHome } from '@/service/home'
import { Toast } from 'vant'
import { reactive, onMounted , toRefs} from 'vue'
export default {
	name: 'home',
	components: {
	  navBar,
	  swiper
	},
	setup() {
		const state = reactive({
		  swiperList: [] ,// 轮播图列表
		  categoryList: [
		   {
		      name: '查看设备',
		      imgUrl: '/image/kj1.png',
		      categoryId: 100001
		    }, {
		      name: '用户信息',
		      imgUrl: '/image/kj2.png',
		      categoryId: 100002
		    }, {
		      name: '充值中心',
		      imgUrl: '/image/kj3.png',
		      categoryId: 100003
		    },{
		      name: '功能预留',
		      imgUrl: '/image/kj4.png',
		      categoryId: 100004
		    }, {
		      name: '全部',
		      imgUrl: '/image/kj5.png',
		      categoryId: 100005
		    }
		  ],
		  })
		  
		onMounted(async () => {
			Toast.loading({
			  message: '加载中...',
			  forbidClick: true
			});
			const { data } = await getHome()
			console.log(data)
			state.swiperList = data.swiperLists
			Toast.clear()
		})
		
		const tips = () => {
		  Toast('敬请期待');
		}
		
		return {
		  ...toRefs(state),
		   tips
		}
	}
}
</script>

<style lang="less" scoped >
  @import '../common/style/mixin';
 .home-header {
	 position: fixed;
	 left: 0;
	 top: 0;
	 .wh(100%, 45px);
	 .fj(center);
	 line-height: 45px;
	 padding: 0 15px;
	 .boxSizing();
	 font-size: 15px;
	 color: #fff;
	 background: #39A2FD;
	 z-index: 10000;
	 
	 .app-name {
		 padding: 0 5px;
		 color: #ffffff;
		 font-size: 18px;
	}
  }
  .category-list {
    display: flex;
    flex-shrink: 0;
    flex-wrap: wrap;
    width: 100%;
    padding-bottom: 13px;
    div {
      display: flex;
      flex-direction: column;
      width: 20%;
      text-align: center;
      img {
        .wh(36px, 36px);
        margin: 13px auto 8px auto;
      }
    }
  }
</style>

At this point, the basic design of the homepage is completed, and the detailed design process of the personal center page will be introduced next. Let's take a screenshot first:

 

Guess you like

Origin blog.csdn.net/qq8864/article/details/113662454