您现在的位置是:主页 > news > 物联网技术应用是学什么的/西安做seo的公司
物联网技术应用是学什么的/西安做seo的公司
admin2025/5/8 16:10:10【news】
简介物联网技术应用是学什么的,西安做seo的公司,自适应网站建设需要注意什么,活码二维码生成器目录 一、Promise 二、swiper 三、$event 四、transition 过渡动画 五、toast组件 六、解构并不能实现对象的深拷贝 七、修改脚手架默认包管理工具 八、redux 九、react组件props类型检查和默认值 十、使用webpack搭建react开发环境 github源码: 一、Pro…
目录
一、Promise
二、swiper
三、$event
四、transition 过渡动画
五、toast组件
六、解构并不能实现对象的深拷贝
七、修改脚手架默认包管理工具
八、redux
九、react组件props类型检查和默认值
十、使用webpack搭建react开发环境
github源码:
一、Promise
async函数会返回一个promise,并且Promise对象的状态值是resolved(成功的)
//Promise基础用法let pro = new Promise(resolve => {setTimeout(() => {resolve('hello world')}, 500)})pro.then(res => {console.log(res) // hello world})//Promise和async await相结合,async函数会返回一个promise,并且Promise对象的状态值是resolved(成功的)const fun = async () => {let resultawait new Promise((resolve, reject) => {setTimeout(() => {resolve({code: 200,data: { name: 'zhangsan' },message: '姓名'})}, 1000)}).then(res => {result = res})return result}Promise和async await相结合二fun().then(res => {console.log(res)})const fun2 = async () => {return await new Promise((resolve, reject) => {setTimeout(() => {resolve({code: 200,data: 'lishi',message: '消息'})}, 1500)})}fun2().then(res => {console.log(res)})
二、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, flipspeed: 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>
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 = falseVue.use(lazyload, {loading: img
})Vue.use(VueAwesomeSwiper)new Vue({router,store,render: h => h(App)
}).$mount('#app')
三、$event
有时也需要在内联语句处理器中访问原始的 DOM 事件。可以用特殊变量 $event
把它传入方法。
https://cn.vuejs.org/v2/guide/events.html#%E5%86%85%E8%81%94%E5%A4%84%E7%90%86%E5%99%A8%E4%B8%AD%E7%9A%84%E6%96%B9%E6%B3%95
四、transition 过渡动画
<template><div><div><router-link to="/index/home" class="m-nav-item">首页</router-link><router-link to="/index/my_book" class="m-nav-item">书包</router-link><router-link to="/index/exam1" class="m-nav-item">周考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 1s linear;}
.slide-enter{transform: translateX(100%)}/* .slide-leave-active{transition: all 1s linear;}
.slide-leave-to{transform: translateX(-100%)} */.slide-leave-active{animation: slide 1s linear;}@keyframes slide {0% {transform: translateX(0)}100% { transform: translateX(-100%)}
}
</style>
五、toast组件
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>
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
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;}
使用:
<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)">删除</button></div></div><div v-if="myBook.length > 0"><div><label><input type="checkbox" :checked="total.checkedAll" @click="handleCheckAll">全选</label><button @click="handleShowDialog">删除</button></div><div>总价:¥{{total.totalPrice}},总数:{{total.totalCount}}</div></div><div v-else>书包空空如也~~~</div><Dialog :visible="visible" title="删除"><template v-slot:content><div class="m-delete-info"><Icon type="shanchu" classname="m-delete-icon"></Icon><div class="m-delete-text">你确定要删除选中的商品吗?</div></div></template><template v-slot:footer><button class="m-btn" @click="handleHideDialog">取消</button><button class="m-btn" @click="handleDeleteChecked">确定</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.checkedthis.$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('请选择要删除的商品~')toast({message: '请选择要删除的商品~', 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>
注册到全局:
import toast from './components/Toast'Vue.prototype.$toast = toast
使用:
this.$toast({message: 'test'})
appendChild() 方法在指定元素节点的最后一个子节点之后添加节点。
https://www.w3school.com.cn/xmldom/met_element_appendchild.asp
六、解构并不能实现对象的深拷贝
let obj = {a: 1,b: {c: '1'},fun() {console.log(1)},time: new Date(),d: undefined}let newObj = { ...obj }newObj.b.c = '2'console.log(obj)console.log(newObj)console.log(obj.b.c) // 2
七、修改脚手架默认包管理工具
八、redux
reducer 一定要保持纯净,只要传入参数相同,返回计算得到的下一个 state 就一定相同。没有特殊情况、没有副作用,没有 API 请求、没有变量修改,单纯执行计算。
时刻谨记永远不要在克隆 state
前修改它。
在redux-devtools中,我们可以查看到redux下所有通过reducer更新state的记录,每一个记录都对应着内存中某一个具体的state,让用户可以追溯到每一次历史操作产生与执行时,当时的具体状态,这也是使用redux管理状态的重要优势之一.
若不创建副本,redux的所有操作都将指向内存中的同一个state,我们将无从获取每一次操作前后,state的具体状态与改变,若没有副本,redux-devtools列表里所有的state都将被最后一次操作的结果所取代.我们将无法追溯state变更的历史记录.
创建副本也是为了保证向下传入的this.props与nextProps能得到正确的值,以便我们能够利用前后props的改变情况以决定如何render组件。
直接修改state(错误的):
const defaultState = {count: 0}//直接修改改state,所有的state都将被最后一次操作的结果所取代.我们将无法追溯state变更的历史记录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 }
深拷贝(性能很差):
const defaultState = {count: 0}//深拷贝可以解决这个问题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 }
解构:
const defaultState = {count: 0}//解构可以解决这个问题const reducer = (state = defaultState ) => {let newState = {...state}newState.count++return newState}let previousState = { count: 0 }let newState = reducer(previousState)console.log(previousState) //{ count: 0 }console.log(newState) //{ count: 1 }
解构属于浅拷贝,解决不了嵌套的场景:
const defaultState = {obj: {count: 0}}//解构属于浅拷贝,解决不了嵌套问题const reducer = (state = defaultState ) => {let newState = {...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 } }
非要用解构,也行:
const defaultState = {obj: {count: 0}}//解构属于浅拷贝,解决不了嵌套问题,不过可以这样解决,只是比较难理解const reducer = (state = defaultState ) => {let newObj = {...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 } }
immutable.js:
<!DOCTYPE html>
<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,由Facebook工程师耗时三年完成!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>
把业务代码提出来:
<!DOCTYPE html>
<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,有Facebook工程师耗时三年完成!可以把业务代码提出来,reducer变成动态的key和动态的valueconst 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>
九、react组件props类型检查和默认值
不需要安装prop-types包,脚手架已经默认安装
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.propsreturn (<span className={`icon iconfont icon-${type} ${className ? className : ''}`} onClick={this.props.onClick}></span>)}
}Icon.propTypes = {type: PropTypes.string,className: PropTypes.string
}Icon.defaultProps = {type: 'shubao'
}
参考链接:
https://zh-hans.reactjs.org/docs/typechecking-with-proptypes.html#___gatsby
https://www.npmjs.com/package/prop-types
十、使用webpack搭建react开发环境
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'})]
}
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"}
}
github:
https://github.com/baweireact/m-apps/tree/master/m-app-1708E/react/01%E4%BD%BF%E7%94%A8webpack%E6%90%AD%E5%BB%BAreact%E5%BC%80%E5%8F%91%E7%8E%AF%E5%A2%83
十一、webpack搭建react项目时在二级路由页面刷新报404的解决办法
react-router 使用webpack-dev-server做服务器时 单级刷新报错 Cannot GET /xx。多级刷新报错404
output: {path: __dirname + '/dist',filename: 'bundle-[hash].js',publicPath: '/' //第二处要添加的},devServer: {inline: true,hot: true,port: 9000,contentBase: __dirname + '/dist',open: true,historyApiFallback: true //第一处要添加的},
参考链接:
https://blog.csdn.net/limonsea/article/details/96865906
十二、webpack图解
webpack+webpack-dev-server:
https://segmentfault.com/q/1010000005767033/a-1020000005767079
通过node启动webpack-dev-server:
https://webpack.docschina.org/guides/hot-module-replacement/#%E9%80%9A%E8%BF%87-node-js-api
devServer.overlay:
这个配置属性用来在编译出错的时候,在浏览器页面上显示错误,默认是false,可设置为true
devServer: {overlay: true
}
十三、import对象解构失败问题
用惯了es6语法中的解构赋值,在对于import引入的对象进行解构赋值时发现对象变成了undefined
。
解决办法:
// main.js
import { foo, bar } from "./static"// static.js
let foo = "foo"
let bar = "bar"
export { foo, bar }
参考链接:
https://blog.csdn.net/momDIY/article/details/88375677
十四、FileZilla连接ftp服务器失败,提示"AUTH TLS"解决方法
https://www.cnblogs.com/mytt/p/6684199.html
github源码:
https://github.com/baweireact/m-apps/tree/master/m-app-1708E