In the last tutorial we nailed down the ultraman Club prototype using the familiar React and Hooks. In this article, we will use Taro’s built-in routing functionality to achieve multi-page hops and upgrade the previously rudimentary interface with the Taro UI Component library. The finished DEMO is as follows:

Specifically, there are three pages:

  • Home page: shows all posts and a button to add new posts.
  • Post details: Display the entire content of a single post.
  • Personal page: Displays the personal information of the current user.

If you want to get hands-on with this article directly, run the following command to get started quickly:

git clone -b second-part https://github.com/tuture-dev/ultra-club.git
cd ultra-club
Copy the code

The source code for this article is available on Github. If you think we did a good job, please give ❤️ a thumbs up +Github repository + star ❤️

A dozen pages

In this step, we will start implementing the other pages of the project, including:

  • Post detailspost: The details page of a single post is displayed
  • mymine: Display the personal information of the current user (login will be implemented in the next step)

The post details page will reuse the PostCard component written earlier. For ease of administration, we need to introduce a new prop (isList) that determines whether this component is displayed in the home page list or in the post details page.

prompt

The images you need for your project can be downloaded from this link, unpacked and placed in the SRC /images directory.

Taro’s routing function

Routing is central to implementing multi-page applications, and fortunately Taro has already come with it. Specifically, there are only two steps to implement page hopping in Taro:

  1. In the entry file (src/app.jsx) in theAppThe component’sconfigConfiguration mentioned earlier inpagesattribute
  2. Pass in any componentTaro.navigateToTaro.redirectToCan realize the page jump or redirect

Not intuitive? OK, let’s just roll up our sleeves and write.

Configuring all pages

First configure all the pages in the entry file SRC /app.jsx:

import Taro, { Component } from '@tarojs/taro'
import Index from './pages/index'

import './app.scss'

// If you need to enable React Devtools in the H5 environment
// Cancel the following comment:
// if (process.env.NODE_ENV !== 'production' && process.env.TARO_ENV === 'h5')  {
// require('nerv-devtools')
// }

class App extends Component {
  config = {
    pages: ['pages/index/index'.'pages/mine/mine'.'pages/post/post'].window: {
      backgroundTextStyle: 'light'.navigationBarBackgroundColor: '#fff'.navigationBarTitleText: 'WeChat'.navigationBarTextStyle: 'black',},tabBar: {
      list: [{pagePath: 'pages/index/index'.text: 'home'.iconPath: './images/home.png'.selectedIconPath: './images/homeSelected.png'}, {pagePath: 'pages/mine/mine'.text: 'I'.iconPath: './images/mine.png'.selectedIconPath: './images/mineSelected.png',},],},}// The render() function in the App class has no real effect
  // Do not modify this function
  render() {
    return <Index />
  }
}

Taro.render(<App />.document.getElementById('app'))
Copy the code

Notice that we also registered the navigation bar tabBar in config to switch between the Index and mine pages at the bottom.

Add jump logic to the PostCard

We started by adding jump logic to the PostCard component so that when it is clicked, it will go to the post’s details page. The SRC/components/it/index. The JSX modified according to the following code:

import Taro from '@tarojs/taro'
import { View } from '@tarojs/components'

import './index.scss'

export default function PostCard(props) {
  const handleClick = () = > {
    // If it is a list, then click on the event to jump to the post details
    if (props.isList) {
      const { title, content } = props
      Taro.navigateTo({
        url: `/pages/post/post? title=${title}&content=${content}`,}}}return (
    <View className="postcard" onClick={handleClick}>
      <View className="post-title">{props.title}</View>
      <View className="post-content">{props.content}</View>
    </View>)}Copy the code

As you can see, we registered handleClick in the PostCard to respond to click events. In the handleClick function, we use the newly introduced isList attribute to determine whether the component is displayed in the home page list. If so, jump through Taro. NavigateTo.

prompt

If you are sharp-eyed, you must have noticed that we call navigateTo with a query string passing parameters. When we implement the post details page, we will receive the title and Content values passed in.

Next we need to add isList to the PostCard component in the home page module. Modify the SRC/pages/index/index. The JSX, code is as follows:

// import statement...

export default function Index() {
  // Define state and handleSubmit functions...

  return (
    <View className="index">
      {posts.map((post, index) => (
        <PostCard
          key={index}
          title={post.title}
          content={post.content}
          isList
        />
      ))}
      <PostForm
        formTitle={formTitle}
        formContent={formContent}
        handleSubmit={e= > handleSubmit(e)}
        handleTitleInput={e => setFormTitle(e.target.value)}
        handleContentInput={e => setFormContent(e.target.value)}
      />
    </View>)}// ...
Copy the code

Implement “post details” page

Create a POST directory in SRC/Pages, and then create post.jsx and post.scss, the page module and style file, respectively. The post.jsx code looks like this:

import Taro, { useRouter } from '@tarojs/taro'
import { View } from '@tarojs/components'
import { PostCard } from '.. /.. /components'

import './post.scss'

export default function Post() {
  const router = useRouter()
  const { params } = router

  return (
    <View className="post">
      <PostCard title={params.title} content={params.content} />
    </View>
  )
}

Post.config = {
  navigationBarTitleText: 'Post Details',}Copy the code

Notice that we are using the useRouter Hook (Taro only). This Hook is used to retrieve the router from the function component, which is the same as this.$Router from the previous class component. With the Router, we can get the title and content parameters that the PostCard component just passed in when it jumped.

The code for post.scss is as follows:

.mine {
  margin: 30px;
  border: 1px solid #ddd;
  text-align: center;
  height: 90vh;
  padding-top: 40px;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: space-between;
}

.mine-avatar {
  width: 200px;
  height: 200px;
  border-radius: 50%;
}

.mine-nickName {
  font-size: 40;
  margin-top: 20px;
}

.mine-username {
  font-size: 32px;
  margin-top: 16px;
  color: # 777;
}

.mine-footer {
  font-size: 28px;
  color: # 777;
  margin-bottom: 20px;
}
Copy the code

Implement “my” page

Next we implement the “my” page. Create the SRC /pages/mine directory where mine.jsx and mine.scss are created. The page component mine.jsx code is as follows:

import Taro from '@tarojs/taro'
import { View, Image } from '@tarojs/components'

import './mine.scss'
import avatar from '.. /.. /images/avatar.png'

export default function Mine() {
  return (
    <View className="mine">
      <View>
        <Image src={avatar} className="mine-avatar" />
        <View className="mine-nickName">Figure finches sauce</View>
        <View className="mine-username">tuture</View>
      </View>
      <View className="mine-footer">From Toofinch Community with Love ❤</View>
    </View>
  )
}

Mine.config = {
  navigationBarTitleText: 'I',}Copy the code

The style file mine.scss code is as follows:

.mine {
  margin: 30px;
  border: 1px solid #ddd;
  text-align: center;
  height: 90vh;
  padding-top: 40px;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: space-between;
}

.mine-avatar {
  width: 200px;
  height: 200px;
  border-radius: 50%;
}

.mine-nickName {
  font-size: 40;
  margin-top: 20px;
}

.mine-username {
  font-size: 32px;
  margin-top: 16px;
  color: # 777;
}

.mine-footer {
  font-size: 28px;
  color: # 777;
  margin-bottom: 20px;
}
Copy the code

See the effect

It’s time for the exciting acceptance. We should see something like this:

Accelerate development, Taro UI help

When writing a user interface, if you have to write your own component logic and adjust the style of the component every time, it is perfectly fine for learning, but it is very troublesome for the actual development task. In the React community, we have component libraries such as Ant Design that allow us to quickly build a professional and aesthetically pleasing interface. Taro also provides the Taro UI component library, providing us with mature components that can adapt to multiple applications. In this step, we will update the interface with the Taro UI to make it look more like a full-fledged applet.

Let’s first post the updated demo:

As you can see, we made three improvements:

  • Trigger the FloatLayout that creates a new article by clicking a Fab button.
  • After successful publication, a warm Message will be displayed.
  • The PostCard component has been removed from the post details page to make it look more like a body display

Configuration Taro UI

First install Taro UI NPM package:

npm install taro-ui
Copy the code

In order to use taro-UI in H5, we need to add the following configuration to config/index.js:

h5: {
  esnextModules: ['taro-ui']}Copy the code

Upgrade PostForm

First let’s update the PostForm component. We will first try the Taro UI AtButton component to replace the previous Taro built-in component:

import Taro from '@tarojs/taro'
import { View, Form, Input, Textarea, Button } from '@tarojs/components'
import { AtButton } from 'taro-ui'

import './index.scss'

export default function PostForm(props) {
  return (
    <View className="post-form">
      <Form onSubmit={props.handleSubmit}>
        <View>
          <View className="form-hint">The title</View>
          <Input
            className="input-title"
            type="text"
            placeholder="Click enter title"
            value={props.formTitle}
            onInput={props.handleTitleInput}
          />
          <View className="form-hint">The body of the</View>
          <Textarea
            placeholder="Click enter text"
            className="input-content"
            value={props.formContent}
            onInput={props.handleContentInput}
          />
          <AtButton formType="submit" type="primary">submit</AtButton>
        </View>
      </Form>
    </View>)}Copy the code

Notice that we have also removed the

post
from

, since we are going to put the form inside the FloatLayout, so we don’t need it.

prompt

You may be wondering why Taro UI components start with “At”. One is to distinguish them from regular Taro components, and the other is because the team that developed Taro is aotu.io Bump Lab.

Restyle the PostForm component as follows:

.post-form {
  margin: 0 30px;
  padding: 30px;
}

.input-title {
  border: 1px solid #eee;
  padding: 10px;
  font-size: medium;
  width: 100%;
}

.input-content {
  border: 1px solid #eee;
  padding: 10px;
  width: 100%;
  height: 200px;
  font-size: medium;
  margin-bottom: 40px;
}

.form-hint {
  font-size: small;
  color: gray;
  margin-top: 20px;
  margin-bottom: 10px;
}
Copy the code

As mentioned earlier, we are going to put the form for creating a new post in FloatLayout. On the front page module SRC/pages/index/index. The JSX import related components, the code is as follows:

import Taro, { useState } from '@tarojs/taro'
import { View } from '@tarojs/components'
import { AtFab, AtFloatLayout, AtMessage } from 'taro-ui'

import { PostCard, PostForm } from '.. /.. /components'
import './index.scss'

export default function Index() {
  const [posts, setPosts] = useState([
    {
      title: 'Telo Altman'.content: 'Tiro was the only biological son of the father and mother of Otter. ',}])const [formTitle, setFormTitle] = useState(' ')
  const [formContent, setFormContent] = useState(' ')
  const [isOpened, setIsOpened] = useState(false)

  function handleSubmit(e) {
    e.preventDefault()

    const newPosts = posts.concat({ title: formTitle, content: formContent })
    setPosts(newPosts)
    setFormTitle(' ')
    setFormContent(' ')
    setIsOpened(false)

    Taro.atMessage({
      message: 'Published successfully'.type: 'success'})},return (
    <View className="index">
      <AtMessage />
      {posts.map((post, index) => (
        <PostCard
          key={index}
          title={post.title}
          content={post.content}
          isList
        />
      ))}
      <AtFloatLayout
        isOpened={isOpened}
        title="Publish a new article."
        onClose={()= > setIsOpened(false)}
      >
        <PostForm
          formTitle={formTitle}
          formContent={formContent}
          handleSubmit={e= > handleSubmit(e)}
          handleTitleInput={e => setFormTitle(e.target.value)}
          handleContentInput={e => setFormContent(e.target.value)}
        />
      </AtFloatLayout>
      <View className="post-button">
        <AtFab onClick={()= > setIsOpened(true)}>
          <Text className="at-fab__icon at-icon at-icon-edit"></Text>
        </AtFab>
      </View>
    </View>
  )
}

Index.config = {
  navigationBarTitleText: 'home',}Copy the code

Let’s take a look at the new code one by one:

  • First of all, from thetaro-uiImport requiredAtFab,AtFloatLayoutAtMessagecomponent
  • useuseStateHook creates a new stateisOpened(used to record whether the float layer is open) and used to modify the statesetIsOpened
  • inhandleSubmitIn the usesetIsOpened(false)Close the float layer and useTaro.atMessagePop-up Prompt Message
  • inreturnJSX code when added<AtMessage />Component and in the previousPostFormComponent Outer packageAtFloatLayoutComponent, and finally add a float buttonAtFab

On the front page style file SRC/pages/index/index. The SCSS add style is as follows:

.post-button {
  position: fixed;
  right: 60px;
  bottom: 80px;
}
Copy the code

Upgrade it

Next, let’s adjust how the PostCard looks on different pages. Classnames is the most commonly used CSS class composition library, giving you the flexibility to combine CSS classes using JavaScript expressions. For example, we have three CSS classes foo, bar, and foo-bar, which can be combined conditionally with the classNames function:

import classNames from 'classnames`; classNames('foo', 'bar'); / / = > 'foo bar'
classNames('foo', { bar: true }); / / = > 'foo bar'
classNames({ 'foo-bar': true }); / / = > 'foo-bar'
classNames({ 'foo-bar': false }); / / = > '' classNames({ foo: true }, { bar: true }); / / = > 'foo bar' classNames({ foo: true, bar: true }); / / = > 'foo bar'
Copy the code

We also added a new CSS class, postcard__isList, to represent styles in the post list. Modify the SRC/components/it/index. The JSX code is as follows:

import Taro from '@tarojs/taro'
import { View } from '@tarojs/components'
import classNames from 'classnames'

import './index.scss'

export default function PostCard(props) {
  const handleClick = () = > {
    // ...
  }

  return (
    <View
      className={classNames('postcard'{postcard__isList: props.isList })}
      onClick={handleClick}
    >
      <View className="post-title">{props.title}</View>
      <View className="post-content">{props.content}</View>
    </View>
  )
}

PostCard.defaultProps = {
  isList: ' ',}Copy the code

Modify the style of the PostCard component as follows:

.postcard {
  margin: 30px;
  padding: 20px;
}

.postcard__isList {
  border: 1px solid #ddd;
}

.post-title {
  font-weight: bolder;
  margin-bottom: 10px;
}

.post-content {
  font-size: medium;
  color: # 666;
}
Copy the code

Custom theme colors

Taro UI supports a degree of theme customization, using the simplest yet most effective SCSS variable override. We create SRC /custom-theme. SCSS with the following code:

/* Custom Theme */
$color-brand: #02b875;
$color-brand-light: #41ca98;
$color-brand-dark: #02935e;
Copy the code

As you can see, we have defined three SCSS variables, $color-brand, $color-brand-light, and $color-brand-dark, to override the default theme color of Taro UI.

prompt

To see all SCSS variables that can be overridden, refer to the Taro UI default style file. If you are not familiar with SCSS variables, this guide is a good source.

Next we need to import the custom color theme file in the project’s global style file SRC /app.scss as follows:

@import './custom-theme.scss';

@import '~taro-ui/dist/style/components/button.scss';
@import '~taro-ui/dist/style/components/fab.scss';
@import '~taro-ui/dist/style/components/icon.scss';
@import '~taro-ui/dist/style/components/float-layout.scss';
@import '~taro-ui/dist/style/components/textarea.scss';
@import '~taro-ui/dist/style/components/message.scss';
@import '~taro-ui/dist/style/components/avatar.scss';
Copy the code

As you can see, in addition to importing the custom-theme. SCSS we just created, we also imported the styles of the components used in the Taro UI as needed to reduce the size of the packaged application.

After this step of the code, remember to check in the emulator to see if it runs exactly the same as the initial GIF demo!

At this point, “Taro multi-terminal small program development large actual combat” second also ended. Welcome to continue to read the third article, we will explain how to implement multi-login in the Taro framework (wechat applet + Alipay applet + ordinary login).

Want to learn more exciting practical skills tutorial? Come and visit the Tooquine community.

The source code for this article is available on Github. If you think we did a good job, please give ❤️ a thumbs up +Github repository + star ❤️