移动端web快速开发
一、前端UI对比
阿里蚂蚁:https://ant.design/index-cn
阿里蚂蚁:https://mobile.ant.design/zh
阿里饿了么:https://element-plus.org/zh-CN/#/zh-CN
阿里饿了么:http://mint-ui.github.io/#!/zh-cn
腾讯TDesign:https://tdesign.tencent.com
腾讯WeUI:https://weui.io
有赞Vant:http://vant-contrib.gitee.io/vant/#/zh-CN
DCloud:https://uniapp.dcloud.net.cn二、预备资料
React :https://react.docschina.org
Ant Design Mobile 是什么
Ant Design
React 前端美化的两种思路:原生html控件+css,自定义控件(也可再追加css)t
三、一些关键内容介绍
`JavaScript`:ES6的一个实现,相当于oracle实现Java的JDK
`TypeScript`:微软基于JavaScript扩展的https://www.typescriptlang.org
`Node`:http://nodejs.cn 类似JDK中的 jre
`npm`:https://www.npmjs.com/package/npm
`NPM` 的全称是 Node Package Manager,是随同 NodeJS 一起安装的包管理和分发工具,它很方便让 JavaScript 开发者下载、安装、上传以及管理已经安装的包。
`npm` 之于 Node.js ,就像 pip 之于 Python, maven之于Java。
`npm` 是 Node.js 官方提供的包管理工具,他已经成了 Node.js 包的标准发布平台,用于 Node.js 包的发布、传播、依赖控制。
`npm` 提供了命令行工具,使你可以方便地下载、安装、升级、删除包,也可以让你作为开发者发布并维护包。
`package.json`:跟踪依赖关系和元数据。它包含名称、描述和版本之类的信息,以及运行、开发以及有选择地将项目发布到NPM所需的信息。类似maven种的POM.xml文件
`ES6`:`ECMAScript6`(简称ES6)是于2015年6月正式发布的JavaScript语言的标准,正式名为ECMAScript2015(ES2015)。它的目标是使得JavaScript语言可以用来编写复杂的大型应用程序,成为企业级开发语言 。另外,一些情况下ES6也泛指ES2015及之后的新增特性,虽然之后的版本应当称为ES7、ES8等。
新增关键字:let 、const与var对比箭头函数:
// 普通函数
let sum = function (x, y) {
return x + y;
}
// 箭头函数
let sum = (x, y) => {
return x + y;
}四、模块化
由于历史原因,直接引入的多个JS文件之间可能会产生互相污染(变量、函数等),为了解决这个问题,从ES5开始,在ES标准中引入了模块化的概念。 ES6中使用新的方法进行模块化: 使用 export 和 import 关键字
4.1、导出
方法1.声明时直接导出
// AAA文件中
export var a1 = '1';
export function f1() {
}
export const f2 = () => {
/ /
箭头函数导出
}方法2.统一在最后导出
// AAA文件中
var a1 = '1';
function f1() {
}
const f2 = () => {
/ /
箭头函数导出
}
export {a1, f1, f2,}方法3.导出时特殊操作:起别名
// AAA文件中
var a1 = '1';
function f1() {
}
const f2 = () => {
/ /
箭头函数导出
}
// as 后跟的名字是导出的别名
export {
a1 as A1,
f1 as F1,
f2 as F2,
}方法4.导出时特殊操作:直接导出导入内容
// 意思是导出 从XXX中导入的a1,f1,f2, 常写在一个文件中用于导出全部js,类似于库的头文件去给别人导入
export {a1, f1, f2} from './XXX.js'方法5.导出时特殊操作:使用default默认导出
export default function () {
}这种导出方式在导入时即可自己定义名称且不需要加{},和其他导出方式共存,但是一个js文件只能有一个default
方法6.导出时特殊操作:导出类
ES6中类的本就是函数,使用时需要创建一个实例,也可以直接导出一个实例(类似于导出变量) // AAA文件中
export class Dog {
eat() {
console.log('吃饭')
}
}// BBB 文件中
import {Dog} from './XXX'
const dog = new Dog();
dog.eat();5.注意export
export 是关键字 ,后面跟的并不是对象,而已一个导出列表,这里的a1,f1,f2的写法并不是ES6中属性的增强写法。 4.2、导入 方法1:直接导入 a1,f1,f2 是导出的时候的名称,不能更改,如果导出时有别名则这里导入的就是别名。
import {a1, f1, f2} from './XXX.js'方法2:导入时起别名
import {a1 as A1, f1 as F1, f2 as F2} from './XXX.js'方法3:导入时使用*
import * as aaa from './XXX.js'
// aaa 此时是一个对象
aaa.a1;
aaa.f1;
aaa.f2;方法4:导入使用default方式导出的模块 // aaa 此时即是导出的内容 import aaa from './XXX.js'
6.注意import
import 是关键字 ,后面跟的并不是对象. from 后面必须有.js 。如果是在框架中(比如Vue),则可以不写,框架会处理自动添加上。
7.JSX、TSX
https://react.docschina.org/docs/introducing-jsx.html
五、面向对象 class,面向过程Hooks
1、hooks 是什么
Hook 是从React 16.8 的新增特性。它可以让你在不编写 class 的情况下使用 state 以及其他的 React 特性。 Hook 是一些可以让你在函数组件里“钩入” React state 及生命周期等特性的函数。Hook 不能在 class 组件中使用 —— 这使得你不使用 class 也能使用 React。
2、为什么要使用 hooks
难以理解的 class 、组件中必须去理解 javascript 与 this 的工作方式、需要绑定事件处理器、纯函数组件与 class 组件的差异存在分歧、甚至需要区分两种组件的使用场景;Hook 可以使你在非 class 的情况下可以使用更多的 React 特性。 在组件之间复用状态逻辑很难、大型组件很难拆分和重构,也很难测试。Hook 使你在无需修改组件结构的情况下复用状态逻辑。 复杂组件变得难以理解、业务逻辑分散在组件的各个方法之中,导致重复逻辑或关联逻辑。Hook 将组件中相互关联的部分拆分成更小的函数(比如设置订阅或请求数据)
3、react 中我们常用的 hook
下面我们挑几种介绍一下(useState、userContext、useEffect ) useState 状态钩子
import React, {useState} from 'react';
function Example() {
// 声明一个叫 "count" 的 state 变量
const [count, setCount] = useState(0);
return (
<div>
<p>You
clicked
{
count
}
times < /p>
< button
onClick = {()
=>
setCount(count + 1)
}>
Click
me < /button>
< /div>
)
;
}等价的 class 示例
class Example extends React.Component {
constructor(props) {
super(props);
this.state = {
count: 0,
};
}
render() {
return (
<div>
<p>You
clicked
{
this.state.count
}
times < /p>
< button
onClick = {()
=>
this.setState({count: this.state.count + 1})
}>
Click
me < /button>
< /div>
)
;
}
}六、SPA及路由
前端跳转,不经过后台 React Router 是一个基于 React 之上的强大路由库,它可以让你向应用中快速地添加视图和数据流,同时保持页面与 URL 间的同步。
核心思想 监听history库url变化事件(Router) 通过react context传播机制,将变化传给(route)做匹配渲染 route将最新match(含路径参数,不含query参数)和location通过context传给child Router 位于应用的顶层,通过对history监听,将新location信息传给route做匹配渲染,新版本已经封装了BrowserRouter,HasRouter。
七、参数传递
react组件传值,大概有下面几种方法: propscontextreduxreact-router 路由切换时通过url传值(少量非机密数据,其实也是props传)。
一、父组件传给子组件
父组件通过props传递给子组件;
//父组件中
<Child data = {[1, 2, 3
]
}
/>
//子组件中
console.log(this.props.data);二、子组件传给父组件
父组件通过props向子组件传入一个方法,子组件在通过调用该方法,将数据以参数的形式传给父组件,父组件可以在该方法中对传入的数据进行处理;
//父组件
import Child from './Child.js'
export default class Parent
extend
compenent
{
getData = (data) => {
console.log(data);
}
render()
{
return (
<div>
父组件
< Child
getData = {this.getData}
/>
< /div>
)
}
}//子组件
export default class Child
extend
compenent
{
state = {
data: [1, 2, 3]
}
render()
{
const {data} = this.state;
return (
<div>
子组件
< button
onClick = {()
=>
{
this.props.getData(data)
}
}>
<button>
</div>
)
}
}三,路由传值。
1.props.params(推荐)
//设置路由
<Router history = {hashHistory} >
<Route path = '/user/:name'
component = {UserPage} > </Route>
< /Router>
import {Router, Route, Link, hashHistory} from 'react-router';
class App extends React.Component {
render() {
return (
<Link to = "/user/sam" > 用户 < /Link>
// 或者
hashHistory.push("/user/sam");
)
}
}当页面跳转到UserPage页面之后,取出传过来的值:
export default class UserPage extends React.Component {
constructor(props) {
super(props);
}
render() {
return (<div>this.props.match.params.name < /div>)
}
}上面的方法可以传递一个或多个值,但是每个值的类型都是字符串,没法传递一个对象,如果传递的话可以将json对象转换为字符串,然后传递过去,传递过去之后再将json字符串转换为对象将数据取出来
//定义路由
<Route path = '/user/:data'
component = {UserPage} > </Route>
//设置参数
var data = {id: 3, name: sam, age: 36};
data = JSON.stringify(data);
var path = `/user/${data}`;
//传值
<Link to = {path} > 用户 < /Link>
//或
hashHistory.push(path);
//获取参数
var data = JSON.parse(this.props.params.data);
var {id, name, age} = data;2.query(不推荐:刷新页面参数丢失)
query方式使用很简单,类似于表单中的get方法,传递参数为明文
//定义路由
<Route path = '/user'
component = {UserPage} > </Route>
//设置参数
var data = {id: 3, name: sam, age: 36};
var path = {
pathname: '/user',
query: data,
}
//传值
< Link
to = {path} > 用户 < /Link>
//或
hashHistory.push(path);
//获取参数
var data = this.props.location.query;
var {id, name, age} = data;3.state(不推荐,刷新页面参数丢失)
state方式类似于post方式,使用方式和query类似
//设置路由
<Route path = '/user' component = {UserPage} > </Route>
//设置参数
var data = {id: 3, name: sam, age: 36};
var path = {
pathname: '/user',
state: data,
}
//传值
< Link to = {path} > 用户 < /Link>
//或
hashHistory.push(path);
//获取参数
var data = this.props.location.state;
var {id, name, age} = data;特别提示: 1,获取参数时要用this.props.match.params.name 2,如果在子组件里打印要记得传this.props,如下:
class Todolist extends Component {
render() {
return (
<DocumentTitle title = "todolist" >
<div id = "home-container" >
<section>
<TodolistList {...this.props}
/> /
/不传的话this.props为空对象
< /section>
< /div>
< /DocumentTitle>
)
;
}
}
export default Todolist;四,非父子组件且嵌套关系复杂的组件之间数据的传递。
通过redux来传值的实现 1,我们先写一个createAction的函数
export function setAnalysisParams(params) {
return {
type: SET_ANALYSIS_PARAMS,
result: params
}
}2,在reducer里面:
export default function reducer(state = initialState, action = {}) {
switch (action.type) {
case SET_ANALYSIS_PARAMS:
return {
...state,
params: action.result
};
default:
return state;
}当action触发reducer时,会把action的result传给reducer的params。写好这里,我们就可以在组件中传给adction params了。
@connect(
() => ({}),
{
setAnalysisParams
})先把actionCreator拿出来。 在组件的某个需要的地方,可以直接向它传我们要放进redux里的数据:
this.props.setAnalysisParams({
someModels
});这时,我们就可以在另外一个组件中取到刚刚放进去的数据。 另外一个组件:
@connect(
state => ({
example: state.clinic.params
}),
{}
)把redux中的params数据映射到example上。 下面,就可以用了:
const {someNames, ...} = this.props.example; //取出数据名八、运行
start.js
const DEFAULT_PORT = parseInt(process.env.PORT, 10) || 28113;
const HOST = process.env.HOST || '0.0.0.0';