directory

A Promise,

Second, the swiper

Third, $event

Transition animation

5. Toast components

6. Deconstruction does not make deep copies of objects

7. Modify the default scaffold package management tool

Eight, redux

React component props type check and default values

Use WebPack to build react development environment

Making the source code:


 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

A Promise,

Async will return a Promise and the promise object’s state is Resolved

    //Promise basic usage
    let pro = new Promise(resolve= > {
      setTimeout(() = > {
        resolve('hello world')},500)
    })

    pro.then(res= > {
      console.log(res) // hello world
    })

    Async returns a Promise and the state of the Promise object is resolved
    const fun = async() = > {let result
      await new Promise((resolve, reject) = > {
        setTimeout(() = > {
          resolve({
            code: 200.data: { name: 'zhangsan' },
            message: 'name'})},1000)
      }).then(res= > {
        result = res
      })

      return result
    }

    Promiseandasync awaitFun ().then(res= > {
      console.log(res)
    })

    const fun2 = async() = > {return await new Promise((resolve, reject) = > {
        setTimeout(() = > {
          resolve({
            code: 200.data: 'lishi'.message: 'message'})},1500)
      })
    }

    fun2().then(res= > {
      console.log(res)
    })
Copy the code

 

Second, the swiper

swiper.js:

<template>
  <div>
    <div>
      <swiper v-if="bannerList.length > 0" :options="options">
        <swiper-slide v-for="(item,index) in bannerList" :key="index">
          <img :src="item" class="m-banner-img"/>
        </swiper-slide>
        <div class="swiper-pagination" slot="pagination"></div>
        <div class="swiper-button-prev" slot="button-prev"></div>
        <div class="swiper-button-next" slot="button-next"></div>
      </swiper>
    </div>
  </div>
</template>

<script>
import Api from ".. /api";

export default {
  data() {
    return {
      bannerList: [].options: {
        loop: true.effect: 'cube'.//slide, fade,cube, coverflow, flip
        speed: 1000.autoplay: {
          delay: 2000
        },
        pagination: {
          el: '.swiper-pagination'.clickable: true
        },
        navigation: {
          nextEl: '.swiper-button-next'.prevEl: '.swiper-button-prev'}}}; },mounted() {
    Api.getBanner().then(res= > {
      if (res.code === 200) {
        this.bannerList = res.data; }}); }};</script>

<style>
</style>
Copy the code

main.js:

import Vue from 'vue'
import lazyload from 'vue-lazyload'
import App from './App.vue'
import router from './router'
import store from './store'
import VueAwesomeSwiper from 'vue-awesome-swiper'
import 'swiper/dist/css/swiper.css'
import './font/iconfont.css'
import './index.css'
import img from './images/loading.png'


Vue.config.productionTip = false

Vue.use(lazyload, {
  loading: img
})

Vue.use(VueAwesomeSwiper)

new Vue({
  router,
  store,
  render: h= > h(App)
}).$mount('#app')
Copy the code

Third, $event

Sometimes you also need to access the raw DOM event in the associative sentence processor. You can pass it to the method with the special variable $event.

Cn.vuejs.org/v2/guide/ev…

Transition animation

<template>
  <div>
    <div>
      <router-link to="/index/home" class="m-nav-item">Home page</router-link>
      <router-link to="/index/my_book" class="m-nav-item">School bag</router-link>
      <router-link to="/index/exam1" class="m-nav-item">Zhou Kao 1</router-link>
    </div>
    <transition name="slide">
      <router-view class="m-router"></router-view>
    </transition>
  </div>
</template>

<script>
export default{}</script>

<style>
.m-router{position: absolute;width:100%}
.slide-enter-active{transition: all 1slinear; }.slide-enter{transform: translateX(100%)}

/* .slide-leave-active{transition: all 1s linear; } .slide-leave-to{transform: translateX(-100%)} */

.slide-leave-active{animation: slide 1slinear; }@keyframes slide {
  0% {transform: translateX(0)}
  100% { transform: translateX(-100%)}}</style>
Copy the code

5. Toast components

Toast.vue:

<template>
  <div class="m-toast-mask" :id="id" >
    <div class="m-toast">{{message}}</div>
  </div>
</template>

<script>
export default {
  data() {
    return {
      duration: 3000.message: ' '.id: Date.now()
    }
  },
  mounted() {
    setTimeout(() = > {
      document.getElementById(this.id).remove()
    }, this.duration)
  }
}
</script>

<style>

</style>
Copy the code

index.js:

import Vue from 'vue'
import Toast from './Toast'

const ToastConstructor = Vue.extend(Toast)

const toast = (options) = > {
  let instance = new ToastConstructor({data: options}).$mount()
  document.body.appendChild(instance.$el)
}

export default toast
Copy the code

css:

.m-toast-mask{display: flex; position: fixed;top: 0;left: 0;right: 0;bottom: 0; }.m-toast{margin: auto;padding: 0 10px; min-width: 100px;line-height: 40px;border-radius: 3px;background: rgba(0.0.0.0.5);text-align: center;color: #ffffff; }Copy the code

Use:

<template>
  <div>
    <div v-for="(item, index) in myBook" :key="item.id" class="m-my-book-item">
      <div class="m-my-book-info">
        <label>
          <input type="checkbox" :checked="item.checked" @change="handleCheck(index, $event)" />
          {{item.title}}
        </label>${{item. Price}}</div>
      <div class="m-my-book-action">
        <button @click="handleSub(index)">-</button>
        {{item.count}}
        <button @click="handleAdd(index)">+</button>
        <button @click="handleDelete(index)">delete</button>
      </div>
    </div>
    <div v-if="myBook.length > 0">
      <div>
        <label>
          <input type="checkbox" :checked="total.checkedAll" @click="handleCheckAll">select all</label>
        <button @click="handleShowDialog">delete</button>
      </div>
      <div>Total price: ¥{{total.totalprice}}, total price: {{total.totalcount}}</div>
    </div>
    <div v-else>The bag is empty</div>
    <Dialog :visible="visible" title="Delete">
      <template v-slot:content>
        <div class="m-delete-info">
          <Icon type="shanchu" classname="m-delete-icon"></Icon>
          <div class="m-delete-text">Are you sure you want to delete the selected item?</div>
        </div>
      </template>
      <template v-slot:footer>
        <button class="m-btn" @click="handleHideDialog">cancel</button>
        <button class="m-btn" @click="handleDeleteChecked">determine</button>
      </template>
    </Dialog>
  </div>
</template>

<script>
import Api from ".. /api";
import Dialog from '.. /components/Dialog'
import Icon from '.. /components/Icon'
import toast from '.. /components/Toast'

export default {
  data() {
    return {
      visible: false}},computed: {
    myBook() {
      return this.$store.state.myBook;
    },
    total() {
      let myBook = this.myBook;
      let totalCount = myBook.filter(item= > item.checked).reduce((total, item) = > {
        return total + item.count;
      }, 0);
      let totalPrice = myBook.filter(item= > item.checked).reduce((total, item) = > {
        return total + item.count * item.price;
      }, 0);
      return {
        totalCount,
        totalPrice,
        checkedAll: myBook.every(item= >item.checked) }; }},components:{
    Dialog,
    Icon
  },
  methods: {
    handleSub(index) {
      let myBook = this.myBook;
      if (myBook[index].count > 1) {
        myBook[index].count--;
        this.$store.commit({ type: "setState".key: "myBook".value: myBook }); }},handleAdd(index) {
      let myBook = this.myBook;
      myBook[index].count++;
      this.$store.commit({ type: "setState".key: "myBook".value: myBook });
    },
    handleDelete(index) {
      let myBook = this.myBook;
      myBook.splice(index, 1)
      this.$store.commit({ type: "setState".key: "myBook".value: myBook });
    },
    handleCheck(index, e) {
      let myBook = this.myBook;
      myBook[index].checked = e.target.checked
      this.$store.commit({ type: "setState".key: "myBook".value: myBook });
    },
    handleCheckAll(e) {
      let myBook = this.myBook;
      myBook.forEach(item= > {
        item.checked = e.target.checked
      })
      this.$store.commit({ type: "setState".key: "myBook".value: myBook });
    },
    handleDeleteChecked() {
      let myBook = this.myBook;
      myBook = myBook.filter(item= >! item.checked)this.$store.commit({ type: "setState".key: "myBook".value: myBook });
      this.handleHideDialog()
    },
    handleShowDialog() {
      if (this.myBook.filter(item= > item.checked).length === 0) {
        //alert(' Please select the item to delete ~')
        toast({message: 'Please select the item to delete ~'.duration: 1000})
        return
      }
      this.visible = true
    },
    handleHideDialog() {
      this.visible = false}},updated() {
    Api.update({ myBookNew: this.myBook }).then(res= > {});
  },
  mounted() {
    this.$store.dispatch({ type: "getMyBook"}); }};</script>

<style>
</style>
Copy the code

Register to global:

import toast from './components/Toast'

Vue.prototype.$toast = toast
Copy the code

Use:

this.$toast({message: 'test'})
Copy the code

The appendChild() method adds the node after specifying the last child of the element node.

www.w3school.com.cn/xmldom/met_…

 

6. Deconstruction does not make deep copies of objects

      let obj = {
        a: 1.b: {
          c: '1'
        },
        fun() {
          console.log(1)},time: new Date(),
        d: undefined
      }
      letnewObj = { ... obj } newObj.b.c ='2'
      console.log(obj)
      console.log(newObj)
      console.log(obj.b.c) / / 2
Copy the code

7. Modify the default scaffold package management tool

Eight, redux

 

Reducer must be pure, as long as the parameters passed in are the same, the next state returned must be the same. No special cases, no side effects, no API requests, no variable changes, just perform calculations.

Always remember to never modify state before cloning it.

In Redux-DevTools, we can view all records updated state by reducer under Redux. Each record corresponds to a specific state in the memory, so that users can trace the specific state when each historical operation was generated and executed, which is also managed state using Redux One of the important advantages of.

Without a copy, all redux operations would point to the same state in memory, and we would have no way of capturing the state before and after each operation. Without a copy, all states in the Redux-DevTools list would be replaced by the result of the last operation. We will not be able to trace the history of state changes.

The copy is also created to make sure that the values passed down to this. Props and nextProps are correct so that we can use changes to the props before and after to determine how to render the component.

Modify state directly (wrong) :

      const defaultState = {
        count: 0
      }

      // Modify state directly, all state will be replaced by the result of the last operation. We will not be able to trace the history of state changes
      const reducer = (state = defaultState ) = > {
        state.count++
        return state
      }

      let previousState = { count: 0 }
      let newState = reducer(previousState)
      console.log(previousState)  //{ count: 1 }
      console.log(newState)       //{ count: 1 }
Copy the code

Deep copy (poor performance) :

      const defaultState = {
        count: 0
      }

      // Deep copy can solve this problem
      const reducer = (state = defaultState ) = > {
        state = JSON.parse(JSON.stringify(state))
        state.count++
        return state
      }

      let previousState = { count: 0 }
      let newState = reducer(previousState)
      console.log(previousState)  //{ count: 0 }
      console.log(newState)       //{ count: 1 }
Copy the code

Deconstruction:

      const defaultState = {
        count: 0
      }

      // Deconstruction can solve this problem
      const reducer = (state = defaultState ) = > {
        letnewState = {... state} newState.count++return newState
      }

      let previousState = { count: 0 }
      let newState = reducer(previousState)
      console.log(previousState)  //{ count: 0 }
      console.log(newState)       //{ count: 1 }
Copy the code

Deconstruction is shallow copy and does not solve nested scenarios:

      const defaultState = {
        obj: {
          count: 0}}// Destruct is a shallow copy and does not solve the nesting problem
      const reducer = (state = defaultState ) = > {
        letnewState = {... state} newState.obj.count++return newState
      }

      let previousState = {
        obj: {
          count: 0}}let newState = reducer(previousState)
      console.log(previousState)  //{ obj: { count: 1 } }
      console.log(newState)       //{ obj: { count: 1 } }
Copy the code

If you have to use deconstruction, you can:

      const defaultState = {
        obj: {
          count: 0}}// Destruct is a shallow copy and does not solve the nesting problem, but it can be solved in this way, but it is more difficult to understand
      const reducer = (state = defaultState ) = > {
        letnewObj = {... state.obj} newObj.count++return{... state,obj: newObj}
      }

      let previousState = {
        obj: {
          count: 0}}let newState = reducer(previousState)
      console.log(previousState)  //{ obj: { count: 0 } }
      console.log(newState)       //{ obj: { count: 1 } }
Copy the code

immutable.js:

<! DOCTYPEhtml>
<html>

<head>
</head>

<body>
  <div>
    <script src="https://cdn.bootcss.com/immutable/4.0.0-rc.12/immutable.js"></script>
    <script>

      const defaultState = Immutable.fromJS({
        obj: {
          count: 0}})// Immutable. Js is recommended. It took Facebook engineers three years to make!
      const reducer = (state = defaultState ) = > {
        return state.setIn(['obj'.'count'], Immutable.fromJS(state.getIn(['obj'.'count']) + 1))}let previousState = Immutable.fromJS({
        obj: {
          count: 0}})let newState = reducer(previousState)
      console.log(previousState.getIn(['obj']).toJS())  //{ count: 0 }
      console.log(newState.getIn(['obj']).toJS())       //{ count: 1 }

    </script>
  </div>


</body>

</html>
Copy the code

Bring out the business code:

<! DOCTYPEhtml>
<html>

<head>
</head>

<body>
  <div>
    <script src="https://cdn.bootcss.com/immutable/4.0.0-rc.12/immutable.js"></script>
    <script>

      const defaultState = Immutable.fromJS({
        obj: {
          count: 0}})// Immutable. Js is recommended, which took Facebook engineers three years to make! Business code can be presented and reducer becomes dynamic keys and dynamic values
      const reducer = (state = defaultState, action ) = > {
        return state.setIn(action.key, Immutable.fromJS(action.value))
      }

      let previousState = Immutable.fromJS({
        obj: {
          count: 0}})let action = { key: ['obj'].value: { count : 1}}let newState = reducer(previousState, action)
      console.log(previousState.getIn(['obj']).toJS())  //{ count: 0 }
      console.log(newState.getIn(['obj']).toJS())       //{ count: 1 }

    </script>
  </div>


</body>

</html>
Copy the code

React component props type check and default values

There is no need to install the prop-types package, scaffolding is already installed by default

import React, { Component } from 'react'
import PropTypes from 'prop-types'

export default class Icon extends Component {
  // static defaultProps = {
  // type: 'xingxing'
  // }
  render() {
    let { type, className } = this.props
    return (
      <span className={`icon iconfont icon-The ${type} ${className ? className :"'} `}onClick={this.props.onClick}></span>
    )
  }
}

Icon.propTypes = {
  type: PropTypes.string,
  className: PropTypes.string
}

Icon.defaultProps = {
  type: 'shubao'
}
Copy the code

Reference links:

Zh-hans.reactjs.org/docs/typech…

www.npmjs.com/package/pro…

 

Use WebPack to build react development environment

webpack.config.js:

const MiniCssExtractPlugin = require('mini-css-extract-plugin')
const HtmeWebpackPlugin = require('html-webpack-plugin')

module.exports = {
  mode: 'development'.devtool: 'source-map'.entry: __dirname + '/index.js'.output: {
    path: __dirname + '/dist'.filename: 'bundle-[hash].js'
  },
  devServer: {
    inline: true.hot: true.port: 9000.contentBase: __dirname + '/dist'.open: true
  },
  module: {
    rules: [{test: /\.(js|jsx)$/,
        use: {
          loader: 'babel-loader'.options: {
            presets: ["@babel/preset-react"."@babel/preset-env"]}},exclude: /node_modules/
      }, {
        test: /\.css$/,
        use: [{
          loader: MiniCssExtractPlugin.loader
        }, {
          loader: 'css-loader'}}}]],plugins: [
    new HtmeWebpackPlugin({
      template: __dirname + '/public/index.html'
    }),
    new MiniCssExtractPlugin({
      filename: '[name]-[hash].css'}})]Copy the code

package.json:

{
  "name": "toast"."version": "1.0.0"."description": ""."main": "/toast/index.js"."scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"."build": "webpack"."start": "webpack-dev-server"
  },
  "author": ""."license": "ISC"."devDependencies": {
    "@babel/core": "^ 7.7.7"."@babel/preset-env": "^ 7.7.7"."@babel/preset-react": "^ 7.7.4"."babel-loader": "^ 8.0.6"."css-loader": "^ 3.4.2." "."html-webpack-plugin": "^ 3.2.0"."mini-css-extract-plugin": "^ 0.9.0"."react": "^ 16.12.0"."react-dom": "^ 16.12.0"."style-loader": "^ 1.1.2." "."webpack": "^ 4.41.5"."webpack-cli": "^ 3.3.10"."webpack-dev-server": "^ 3.10.1"}}Copy the code

Making:

Github.com/baweireact/…

 

Update 404 on the secondary routing page when Webpack builds react project

When the react-router uses webpack-dev-server as the server, an error Cannot GET /xx is reported. Procedure Error 404 was reported when multi-level refresh was performed

 

  output: {
    path: __dirname + '/dist'.filename: 'bundle-[hash].js'.publicPath: '/'   // The second thing to add
  },
  devServer: {
    inline: true.hot: true.port: 9000.contentBase: __dirname + '/dist'.open: true.historyApiFallback: true  // The first one to be added
  },
Copy the code

Reference links:

Blog.csdn.net/limonsea/ar…

12. Webpack diagram

webpack+webpack-dev-server:

Segmentfault.com/q/101000000…

 

Start webpack-dev-server from Node:

Webpack.docschina.org/guides/hot-…

 

devServer.overlay:

This configuration property is used to display errors on the browser page when compilation errors occur. The default is false and can be set to true

devServer: {
    overlay: true
}
Copy the code

Import object deconstruction failure

I used to destruct assignment in ES6 syntax, and found that the object changed to undefined when destruct assignment was performed on the object introduced by import.

Solutions:

// main.js
import { foo, bar } from "./static"

// static.js
let foo =  "foo"
let bar = "bar"
export { foo, bar }
Copy the code

Reference links:

Blog.csdn.net/momDIY/arti…

Fourteen,FileZilla failed to connect to the FTP server, and the AUTH TLS solution is displayed

www.cnblogs.com/mytt/p/6684…

 

 

 

 

 

 

 

 

 

 

 

 

Making the source code:

Github.com/baweireact/…