We developed an open source tool based on Git for technical practice tutorial writing, all our tuq community tutorials are written with this tool, welcome Star

If you want to quickly learn how to use it, please read our tutorial documentation

This article is written by PFTom, a member of the Tufinch community. Welcome to join tufinch community to create wonderful free technical tutorials for the development of the programming industry.

If you think we wrote well, remember to like + follow + comment three times, encourage us to write a better tutorial 💪

Small program world disputes, large apps have been building their own small program flow entrance, hoping to benefit businesses, users at the same time, but also to consolidate their own flow barriers, we are already familiar with wechat small program, Alipay small program, we may also know that there have been headlines small program, QQ light application, etc., Today, we bring you a new small program, which is to be released by the e-commerce giant JINGdong. How will the small program of the e-commerce giant bring changes to the Internet in China? Let’s wait and see! And today we will take you to use Taro to write jingdong small program, and complete the multi-page blog can post articles small program.

Initialize the project code

We will use Taro, an open source multi-terminal unified development solution developed by the team of JINGdong Concave Lab, to develop our jingdong applet. First let’s take a look at the final result:

Prepare the environment

Initialize the project manually

Make sure you have the Node.js environment installed, and don’t check out another Node.js article from Tooquet.com for a complete node.js environment configuration.

Once you have installed the latest Node.js environment, use the package management tool Npm that comes with Node installation to create an Taro project, open the terminal, and run the following command:

$ npx @tarojs/cli init jd-mp
Copy the code

After running the above command, you should see the following output from the terminal:

Wait a moment, when the following message appears on the terminal, it means that the project initialization is successful!

Yarn Install v1.21.1 info No lockfile found. [1/4] Considerations packages... [2/4] Fetching packages... [3/4] Linking dependencies... [4/4] Building fresh packages... success Saved lockfile. Donein158.43S. project JD-MP created successfully! Please go to the project directory JD-MP and start working! 😝Copy the code

As you can see, I spent 158.43s, so the initial project may take a bit longer. Please be patient. If you don’t see the above words on the terminal at the end, you may have a problem.

prompt

By default, the.gitignore file is not generated after initializing the project using the command above, which will result in many files under node_modules/** in your version system. So we need to manually add a.gitignore file in the initialized jD-mp project root directory and add the corresponding rules as follows:

Dist # ignores the directory generated by the build project after node_modulesCopy the code

Use prepared code

If you have installed the Node environment but don’t want to or are having trouble initializing the project yourself, Clone the initial project code we prepared for you and then follow this tutorial to make improvements to it.

If you prefer Github, run the following command to get the initial code:

$ git clone https://github.com/tuture-dev/jd-miniprogram.git
Copy the code

If you prefer Gitee, run the following command to get the initial code:

$ git clone https://gitee.com/tuture/jd-miniprogram.git
Copy the code

Instead of using commands to initiate the Taro project yourself, Clone has prepared the code for you to manually install dependencies. Open the terminal and enter the following command to install dependencies:

$ cd jd-miniprogram && npm install
Copy the code

Ok, so we’ve got the initial code, and then you have to actually write the code, isn’t that a bit of an expectation? We can try to develop a jingdong small program soon!

Configure the JD development environment

Install the JD running script

Since jingdong mini program has just come out and has not been officially promoted, the script for the Taro initialization project does not generate a jingdong mini program startup dependency. Therefore, we need to manually install the corresponding startup dependency by opening the command line and executing the following command in the jD-MP project root directory to install it:

$ npm install @tarojs/taro-jd
Copy the code

After installation, we also need to add the following two scripts to package.json to start jingdong mini program project:

{" name ":" jd - mp ", "version" : "1.0.0", "private" : true, "description" : "the first jingdong small program", "templateInfo" : {" name ": "default", "typescript": false, "css": "sass" }, "scripts": { // ... "build:quickapp": "taro build --type quickapp", "build:jd": "taro build --type jd", // ... "dev:quickapp": "npm run build:quickapp -- --watch", "dev:jd": "npm run build:jd -- --watch" }, "author": "", "license": "MIT", "dependencies": { // ... "@ tarojs/taro - jd" : "^ 2.1.5", / /... } / /... }Copy the code

After installing and adding the corresponding commands, we can run our jingdong applet by executing the following commands in the terminal project root directory:

$ npx taro build --type jd --watch
Copy the code

Note that the –watch parameter is added so that when we modify the content in the editor (such as VSCode) and save it, the project will compile the update automatically, and then refresh the developer tool to see the effect of the change. This command will actually run the script command we added in package.json:

"dev:jd": "npm run build:jd -- --watch"
Copy the code

Sign up for jingdong mini program

After the above configuration and the project is started, we need to register a jingdong applet and get the AppId of the corresponding applet. You can visit the official website of Jingdong Applet, register the applet according to the steps, create the project, and then get the AppId of the project, similar to the following:

Then download jingdong developer tools, create a small program project, and enter the obtained AppId:

And click the folder icon circled above in jd Developer to open the JD-MP project created above, but please note that we need to select the dist directory compiled in the project:

At this time, your project is running, after opening, you will see the following effect in jingdong small program developer tools:

Of course, the effect of the above instruction is my final project, you should see a Hello World 🥳🥳🥳 when you open it for the first time

Write the first JD component and configure the style

Everything is ready to start writing our jingdong small program!

Write your first JD component

Taro 3.x.x allows you to write applications like React, Vue, and Nerve. Taro 3.x.x allows you to write applications like React, Vue, and Nerve. Enable Vue readers to also use Taro to write applets.

Now that can only use the React, so let’s trendy, use the React Hooks to simplify component, open the SRC/pages/index/index. The JSX, heavy class components constitute a functional component, and add a bit to post related content:

import Taro from "@tarojs/taro";
import { View, Button, Textarea } from "@tarojs/components";
import "./index.scss";

export default function Index() {
  return (
    <View className="index">
      <Textarea
        placeholder="Write a good tutorial..."
        className="post-input"
        autoHeight
      />
      <Button className="post-button">published</Button>
    </View>); } index. config = {navigationBarTitleText: "home"};Copy the code

As you can see, we changed the class component into a functional component and imported and added two components, Textarea and Button, from @tarojs/ Components for post form content entry and Posting.

Config, which exists only in the page-level component, is used to define some properties of the page. For example, navigationBarTitleText is the title of the page. Represents the top title in the applet:

Add styles to components

When we add the above two components, the component’s native style is relatively common. In order to make our small program more professional, we add some styles to it. In fact, when we use Taro to develop jingdong small program, the writing style is almost the same as we usually develop Web applications. Define the corresponding class name in the component and import the CSS file, then write the style in the CSS file.

Open the SRC/pages/index/index. The SCSS, add the corresponding style file is as follows:

.index {
  display: flex;
  flex-direction: column;
  align-items: center;
}

.post-input {
  margin-top: 24px;
  background: #fff;
  width: 80%;
  min-height: 80px;
  padding: 16px 30px;
  border: 1px solid #eee;
  font-size: 14px;
}

.post-button {
  margin-top: 24px;
  width: calc(80% + 60px);
  border-radius: 0;
  background-color: #00bc87;
  color: white;
}
Copy the code

After adding styles, our application looks like this:

So, are you getting a little professional? 🤓

Use React Hooks and handle events

After writing the first component, we tried to handle our post content input, at this time of the event processing is involved, before we need to put in the SRC/pages/index/index. The JSX “components” control the TextArea defined inside make it, We do this using useState provided by React Hooks.

Open the SRC/pages/index/index. The JSX, make corresponding modifications to the content as follows:

import Taro, { useState } from "@tarojs/taro";
import { View, Button, Textarea } from "@tarojs/components";
import "./index.scss";

export default function Index() {
  const [post, setPost] = useState("");

  function handleChange(e) {
    setPost(e.target.value);
  }

  return (
    <View className="index">
      <Textarea
        placeholder="Write a good tutorial..."
        className="post-input"
        value={post}
        onInput={handleChange}
        autoHeight
      />
      <Button className="post-button">published</Button>
    </View>); } index. config = {navigationBarTitleText: "home"};Copy the code

As you can see, above we import the useState hook and call it to generate a POST and setPost. Then we define a handleChange function to handle the onInput event of the Textarea and accept user input to set the POST value. The “managed component” is achieved by setting the POST back to the value of the Textarea.

Component composition and handling OF UI feedback

When we had a lot of content, putting too much content in a component would cause logic to become unclear, so we tried to create a new component to extract some of its logic. Next we need to deal with the post logic and show the post effect, so we need to create an additional component to show the post logic.

The new component

In the SRC directory, first create the Components folder and then the PostCard folder. Then create an index. JSX file in the PostCard folder to place the component logic and UI. Here we write the following logic in the component:

import Taro from "@tarojs/taro";
import { View, Text, Image } from "@tarojs/components";

import "./styles.scss";

export default function PostCard(props) {
  const { post } = props;

  return (
    <View className="post">
      <Text className="post-name">{post}</Text>
    </View>
  );
}
Copy the code

You can see that we created a PostCard functional component, rendered the parameter POST passed by its parent, and imported a styles. SCSS file, which we will create in a moment.

Create a styles. SCSS under the SRC/Components /PostCard folder and write something like this:

.post {
  width: calc(80% + 60px);
  margin: 0 auto;
  padding: 32px 0;
  border-bottom: 1px solid #eee;
}

.post-name {
  font-size: 20px;
  font-weight: 600;
  width: 100%;
}
Copy the code

Handling UI feedback

When writing the rendering thread component, after we go back to the SRC/pages/index/index. The JSX components, components to import our written it, and at the same time processing posts published logic:

import Taro, { useState } from "@tarojs/taro";
import { View, Button, Textarea } from "@tarojs/components";

import PostCard from ".. /.. /components/PostCard";
import "./index.scss";

export default function Index() {
  const [post, setPost] = useState("");
  const [postList, setPostList] = useState([]);

  function handleChange(e) {
    setPost(e.target.value);
  }

  function handleSubmit() {
    console.log("hello world", post);
    if(! post) { Taro.showToast({title: "Content cannot be empty.".icon: "none"
      });
    } else {
      Taro.showToast({
        title: "Published successfully.".icon: "success"
      });

      setPost(""); setPostList(postList.concat(post)); }}return(<View className="index"> <Textarea placeholder=" className="post-input" value={post} onInput={handleChange} autoHeight /> <Button className="post-button" </Button> <View className="post-box"> {postlist. map(postItem => (<PostCard post={postItem}) /> ))} </View> </View> ); } index. config = {navigationBarTitleText: "home"};Copy the code

As you can see above, we created a new state postList using the useState hook. Then we defined an onClick handler on the Button, handleSubmit. In this function, we determine whether the input post is empty. If it is empty, the user can not post. If there is content, the user will be reminded that the new post has been published successfully, and the post will be added to the postList, and the post content will be empty and wait for the next input.

Note that we use the Taro. ShowToast API to prompt users. Taro also has many convenient apis, such as pop-up modal boxes, for reference in the documentation.

prompt

The additional console statements are ignored and are debug statements at development time.

Finally, we add some style to make our interface more professional, open the SRC/pages/index/index. The SCSS, modify the content is as follows:

.index {
  display: flex;
  flex-direction: column;
  align-items: center;
}

.post-input {
  margin-top: 24px;
  background: #fff;
  width: 80%;
  min-height: 80px;
  padding: 16px 30px;
  border: 1px solid #eee;
  font-size: 14px;
}

.post-button {
  margin-top: 24px;
  width: calc(80% + 60px);
  border-radius: 0;
  background-color: #00bc87;
  color: white;
}

.post-box {
  width: 100%;
  margin-top: 24px;
}
Copy the code

And you’re done! We can now publish a post and show the effect, this time to test your jingdong small program, you should see the following effect:

We successfully handled the composition of components and used Taro’s API to give user UI feedback when Posting.

Multi-page and route jump

Through the above steps, we can display the list of posts, but as we all know, the content of the post can be very long, so we need additional pages to display the details of the post, so we will create a new page and use the API provided by Taro to jump to multiple pages.

A new page

Create a post folder in SRC /pages, and create a post. JSX file inside it, and write the corresponding content as follows:

import Taro, { useRouter } from "@tarojs/taro";
import { View, Text } from "@tarojs/components";

import "./post.scss";

export default function Post() {
  const { params } = useRouter();
  const { post = "" } = params;

  return (
    <View className="post">
      <Text className="post-name">{post}</Text>
    </View>
  );
}

Post.config = {
  navigationBarTitleText: "Post page"
};
Copy the code

As you can see above, we created a Post function and added config to it. Then we changed the title to “Post page”. Then we used the useRouter hook provided by Taro to fetch the parameters from the route.

Pay attention to

Under normal circumstances, we pass postId through routing, and then initiate HTTP request in the details of the post to obtain the details of the post. Here, in order to demonstrate the ability of jingdong small program, the writing method is simplified.

The sign-up page

JSX: SRC /app.jsx: config.pages property of the corresponding app component and the path to the post details page is as follows:

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 {
  componentDidMount() {}

  componentDidShow() {}

  componentDidHide() {}

  componentDidCatchError() {}

  config = {
    pages: ["pages/index/index"."pages/post/post"].window: {
      backgroundTextStyle: "light".navigationBarBackgroundColor: "#fff".navigationBarTitleText: "WeChat".navigationBarTextStyle: "black"}};// 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

Handling route hops

Create and register the page, we can in the SRC/components/it/index JSX components inside handle routing jump: click on the post list of single post

import Taro from "@tarojs/taro";
import { View, Text } from "@tarojs/components";

import "./styles.scss";

export default function PostCard(props) {
  const { post } = props;

  function handleClick() {
    Taro.navigateTo({
      url: `/pages/post/post? post=${post}`
    });
  }

  return (
    <View className="post" onClick={handleClick}>
      <Text className="post-name">{post}</Text>
    </View>
  );
}
Copy the code

We’ve added handleClick to handle onClick events and navigateTo apis provided by Taro to navigate between pages. See the documentation for more page navigation apis.

Now you can click on an individual post after adding a post, and you’ll see that the page jumps to the post details page, which shows the content of the post:

Add the TabBar

Handle the jump of multiple pages, a small program also has some TarBar requirements, that is, there are several buttons at the bottom of the page to jump to a variety of types, we also explore how to add TabBar in jingdong small program.

Write a new TabBar page

Create a mine.jsx file in the SRC /pages directory, and write the corresponding contents as follows:

import Taro, { useRouter } from "@tarojs/taro";
import { View, Text, Image } from "@tarojs/components";

import "./mine.scss";
import avatar from ".. /.. /images/avatar.png";

export default function Mine() {
  return (
    <View className="mine">
      <Image src={avatar} className="mine-avatar" />
      <View className="slogan">
        <Text className="slogan-name">Tuq community: to force content creation, speed up the spread of technology</Text>
      </View>
    </View>); } mine.config = {navigationBarTitleText: "my"};Copy the code

You can see the familiar functional component, and config we set the title “mine”, and also render a picture and slogan in the component, the image can be obtained in the project. 1) Github 2) Gitee

SRC /pages/mine/ to create the corresponding mine.scss file and write the following:

.mine {
  padding-top: 40px;
  display: flex;
  flex-direction: column;
  align-items: center;
}

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

.slogan {
  margin-top: 24px;
}

.slogan-name {
  font-size: 32px;
}
Copy the code

Configuration TabBar

After the second TabBar page is ready, we configure the TabBar in 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 {
  componentDidMount() {}

  componentDidShow() {}

  componentDidHide() {}

  componentDidCatchError() {}

  config = {
    pages: ["pages/index/index"."pages/post/post"."pages/mine/mine"].window: {
      backgroundTextStyle: "light".navigationBarBackgroundColor: "#fff".navigationBarTitleText: "WeChat".navigationBarTextStyle: "black"
    },
    tabBar: {
      list: [{pagePath: "pages/index/index".text: "Home page".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

JSX = pages/mine/mine. JSX = pages/mine/mine. JSX = pages/mine/mine. I then added the configuration information for the two TabBar pages:

  • pagePathRepresents the path of the page rendered by the currently selected TabBar
  • textTabBar’s presentation title
  • iconPathThe icon displayed when TabBar is not selected
  • selectedIconPathTabBar Displays the icon when selected

More TabBar configuration information can be found in the documentation. The icon files are available in the project: 1) Github 2) Gitee.

When the configuration of the above content, we should be able to see the following effect in the JINGdong small program developer interface:

Making a Network request

All of the above is to understand some of the content of the small program written locally, most applications also need network requests to obtain remote data to display, of course, our jingdong small program taste can not miss this point.

We open the SRC/pages/index/index JSX files, make corresponding modifications to the content as follows:

import Taro, { useState, useEffect } from "@tarojs/taro";
import { View, Button, Textarea } from "@tarojs/components";

import PostCard from ".. /.. /components/PostCard";
import "./index.scss";

export default function Index() {
  const [post, setPost] = useState("");
  const [postList, setPostList] = useState([]);

  function handleChange(e) {
    setPost(e.target.value);
  }

  function handleSubmit() {
    console.log("hello world", post);
    if(! post) { Taro.showToast({title: "Content cannot be empty.".icon: "none"
      });
    } else {
      Taro.showToast({
        title: "Published successfully.".icon: "success"
      });

      setPost("");
      setPostList(postList.concat(post));
    }
  }

  useEffect((a)= > {
    async function getPosts() {
      try {
        const res = await Taro.request({
          url:
            "https://9ff4272f-ce60-4be6-9376-f9f462482edc.mock.pstmn.io/articles"
        });

        const postList = res.data.map(item= > item.name);
        setPostList(postList);
      } catch (err) {
        console.log("err", err); } } getPosts(); } []);return(<View className="index"> <Textarea placeholder=" className="post-input" value={post} onInput={handleChange} autoHeight /> <Button className="post-button" </Button> <View className="post-box"> {postlist. map(postItem => (<PostCard post={postItem}) /> ))} </View> </View> ); } index. config = {navigationBarTitleText: "home"};Copy the code

As you can see, we imported the useEffect hook and defined an asynchronous getPosts function to get the initial list of posts. We then used the Taro request API Taro. Request in this function to initiate a web request. The requested data will be processed and updated to postList. Please refer to the Taro documentation for more API requests.

After adding the above, we can get the following effect:

conclusion

Through this tutorial, we can find that thanks to Taro’s excellent cross-application features, even the newly launched PROGRAMS can easily develop the functions we need. This reminds me of the original intention and mission of the Taro team at the launch of Taro Next: “Lower development costs, improve development experience and efficiency”, stay true to our original mission, this is the Taro team’s way to embrace change!

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