前端跨域
1. 浏览器默认的一种'同源策略'
2. 协议- 域名- 端口不统一造成的跨域
1. 后端安装 : yarn add cors - S
2. 引入 : const cors = require ( 'cors' )
3. 直接挂载 : App. use ( cors ( ) )
header ( "Access-Control-Allow-Origin: * " )
1. 原理 : 利用一些带有src属性的标签 ( script) 能够不受限制并切合callback回调函数, 得到结果
2. 直接在script的src标签上加入访问端口地址, 然后执行一个fn函数打印形参
< script src= '端口' > < script>
function fn ( obj ) {
console. log ( obj) }
3. 封装一个JSONP , 跟ajax差不多原理
function JSONP ( setting = {
} ) {
var fnName = 'Show' + parseInt ( Math. random ( ) * 100 )
window[ fnName] = setting. success
var oScript = document. createElement ( 'script' )
let url= setting. url+ '?' + Params ( setting. data) + setting. Callback+ '=' + fnName
oScript. setAttribute ( 'src' , url)
document. body. appendChild ( oScript)
oScript. onload = function ( ) {
this . remove ( )
}
}
提示 : setting就是ajax, 里面要填的一些请求值
封装好了后, 就可以用类似ajax的方式调用访问端口拿到数据
JSONP ( {
url : '访问的端口' ,
data : {
wd : '你好'
} ,
Callback : 'cb' ,
success : function ( data ) {
console. log ( data)
}
} )
一,ES6新增
1,语法变化
1. let const 定义一个变量
2,解构赋值
一, 解构对象赋值
var obj= {
name : "fly" ,
age : 18
}
var {
name, age} = obj
二, 解构数组赋值
var arr= [ 1 , 2 , 3 , 4 ]
var [ a, b, c, d] = arr
var [ , , c, d] = arr
var [ , ... Arr] = arr
console. log ( Arr)
console. log ( ... Arr)
3,字符串扩展
str. includes ( "a" )
str. startsWith ( "a" )
str. endsWith ( "z" )
'x' . padStart ( 5 , 'ab' )
'x' . padEnd ( 5 , 'ab' )
var str= "fly"
var str1= ` <div> ${
str} </div> `
4,数组的扩展
arr. indexOf ( )
arr. forEach ( )
语法 : arr. forEach ( ( el, index, arr ) => {
执行} )
el : 数组里面的每一个数值
index : 数值里面每一个数值的下标
arr : 数组本身
arr. map ( )
语法 : 跟forEach ( ) 语法一样
for . . of
语法 : for ( var el of arr. keys ( arr) ) {
console. log ( el) }
keys : el得到下标 values: el得到值 entries: el得到实例 ( 下标和值 )
arr. filter ( )
语法 : Arr= arr. filter ( el ) {
return el> 3 }
arr. some ( )
语法 : arr. some ( ( el ) => {
if ( el== 20 ) {
return el } } )
obj. findIndex ( )
语法 : obj. findIndex ( ( el ) => {
if ( el. id == 0 ) {
return true } } )
obj. find ( )
语法 : obj. find ( ( el ) => {
if ( el. id == 0 ) {
return true } } )
5,对象的扩展
一. 对象的简写
语法 : var obj= {
name, age : 18 }
二, 对象的拷贝 ( 浅拷贝↓ 深拷贝: 用JSON 转字符串再转对象 )
obj. assign ( )
语法 : obj1 = obj. assign ( {
} , obj)
6,函数的扩展
一, 设置默认参数
function show ( str= "fly" ) {
}
二, 默认参数解构赋值
function show ( {
x, y= 2 } ) {
} show ( {
x : 1 } )
三, reset和扩展运算符
function show ( ... rest) {
}
... 扩展运算符
四, 箭头函数
( ) => {
}
7,class类
继承 : 子类拥有父类的属性和方法, 子类可以重写父类的方法, 子类可以新增自己的属性和方法
class Person {
constructor ( name, age ) {
this . name= name
this . age= age
}
say ( ) {
console. log ( this . name)
}
}
var P = new Person ( '大佬' , '18' )
class Abc extends Person {
construstonr ( name, age, upw ) {
super ( name, age)
this . upw= upw
}
mysay ( ) {
console. log ( this . upw)
}
}
var A = new Abc ( '小炮' , '19' , '258' )
二,NodeJs
Nodejs是一个基于 Chrome V8 引擎的 JavaScript 运行环境, Ndoejs使用了一个事件驱动, 非阻塞式I / O 的模型, 使其轻量又高效, Nodejs的包管理器 npm , 是全球最大的开源库生态环境
下载地址 : http: / / nodejs.cn /
卸载 : 删除C : \Program Files\nodejs C : \users\用户名\appData\Roaming\npm 然后重装
0,express
1. express项目生成器
2. 安装express框架
第一步 : npm init - y
第二步 : 在项目目录下安装 cnpm i express -- save- dev
1,fs模块
简介 : 主要用来文件的读取, 写入, 修改, 追加, 重命名, 新建
引入 : const fs= require ( "fs" )
fs. radFile ( "./node.txt" , 'utf8' , ( err, data ) => {
if ( err) return console. log ( err. message)
console. log ( data)
} )
fs. writeFile ( './node.txt' , '你们好' , ( err ) => {
if ( err) return console. log ( ree. message)
console. log ( "写入成功" )
} )
fs. appendFile ( './node.txt' , '你们好' , ( err ) => {
if ( err) return console. log ( ree. message)
console. log ( "写入成功" )
} )
fs. copyFile ( './node.txt' , 'npm.txt' , ( err ) => {
if ( err) return console. log ( err. message)
console. log ( '拷贝成功' )
} )
2,path路径
path 模块提供用于处理文件路径和目录路径的实用工具。
引入 : const path= require ( "path" )
path. join ( __dirname, './res' , '/123.txt' )
3,http静态服务器
引入 : const http= require ( "http" )
const server= http. createServer ( )
server. on ( 'request' , ( req, res ) => {
} )
server. listen ( 3000 , ( ) => {
console. log ( "服务器启动中" ) } )
三,npm模块
一, 中间件的特性
1. 中间件就是一个普通函数, 有三个参数, req, res, next
2. 中间件需要用use执行, 先安装, 后执行, 后续执行一定要加next ( )
二, npm切换淘宝镜像
npm config set registry https: / / registry. npm. taobao. org
npm config get registry
npm install yarn - g
npm install - g cnpm -- registry= https: / / registry. npm. taobao. org
三, npm/ cnpm/ yarn一些常用命令
npm init - y
npm install
npm i 包名 ( express) - save- dev
- g
-- save
-- save- dev
npm uninstall 包名 ( express) - save- dev
操作跟npm一摸一样, 只是npm变成了cnpm
操作跟npm一摸一样, 只是npm变成了yarn
1,自定义模块
安装 : npm init - y
设置 : 文件夹内默认访问的主文件路径 package . json
暴露 : module. exports= {
}
2,querystring模块
解析 : 查询字符串模块, 一般是对http请求所带的数据进行解析, 对应四个方法
引入 : const querystring= require ( "querystring" )
语法 : querystring. parse ( name= ygy& age= 18 ) 转化后 {
name : 'ygy' , age : 18 }
语法 : querystring. stringify ( {
name : 'ygy' , age : 18 } ) 转化后 name= ygy& age= 18
语法 : querystring. escape ( str) 转化后 % E5 % AD % 97 % E7 % AC % A6 % E4 % B8 % B2
语法 : querystring. unescape ( % E5 % AD % 97 ) 转化后 '字符串'
3.mysql
安装 : cnpm i mysql -- save- dev ( 可以缩写成 - D )
引入 : const mysql= require ( "mysql" )
var connection= mysql. createConnection ( {
host : "localhost" ,
user : "root" ,
password : "root" ,
database : "users"
} )
connection. connect ( )
var sql= "SELECT * FROM users"
connection. query ( sql, '查询的内容' , ( err, result ) => {
if ( err) throw err. message
console. log ( '查询到的数据是' + result)
} )
4.sql语句
insert into ` users ` ( u_name, u_pwd) values ( 'abc123' , '123' )
delete from ` users ` where u_id= 1
select ` u_id ` , ` u_name ` from users where u_name= 'abc123' and u_pwd= '123'
update users set u_sex= '女' where u_id= 1
SELECT * FROM users
5.bodyParser
bodyparser 用来解析post请求的传过来的数据, 不使用该中间件, 解析的内容是一个空对象
安装 : cnpm i body- parser -- save- dev ( 或者- D )
引入 : const bodyParser= require ( "body-parser" )
app. use ( bodyparser. urlencoded ( {
extended : false , limit : "500mb" } ) )
app. use ( bodyParser. json ( ) )
6.服务渲染SSR
两种殷勤模板
1. 把数据和页面结合
2. 使用res. end ( ) 返回处理的内容给 客户端
1. 设置引擎模板的类型和模板的位置
2. 使用res. render ( ) 返回数据
安装 : cnpm i art- template ejs -- save- dev ( 或者- D )
引入 : const tem= require ( "art-template" )
引入 : const ejs= require ( "ejs" )
页面引入 : {
{
name} }
后台语法 : var ret = tem. render ( 地址, 对象)
语法 : const html= tem ( path. join ( __dirname, './index.html' ) , {
} )
res. end ( html)
页面引入 : < %= name% >
app. set ( 'engine view' , 'ejs' )
app. set ( 'views' , 地址)
res. render ( '地址' , 对象)
7.路由router
路由就是一个管理工具, , 用来管理某个路径
const router = express. Router ( )
{
caseSensitive : false , strict : true }
router. get ( "/index.html" , ( req, res, next ) => {
console. log ( request. params. id)
response. end ( "恭喜" )
} )
module. exports= router
8.Express项目生成
网址 : http: / / www.expressjs.com.cn /
安装 : npm install express- generator - g
9.apidoc接口文档
- i 以哪个文件夹生成 - o 生成到哪个文件
10.跨域解决
当前端端口为8080 , 后端的为8888 的时候, 就产生了跨域
安装 : cnpm i cors - save- dev ( - D )
引入 : const cors= require ( "cors" )
设置 : app. use ( cors ( ) )
11.bootstrap渲染
介绍 : 简洁、直观、强悍的前端开发框架,让web开发更迅速、简单。
安装 : cnpm add bootstrap@3.3 .7 - D
引入 : 用css的link引入 路径: . / node_modules/ bootstrap/ dist/ css/ bootstrap. min. css
使用 : 跟普通的class 差不多, 引用库是class 名字, 实现指定的效果
四,Vue
Vue是一款前端框架, 构建用户界面的框架, 为了提高开发效率, 语法类似SSR 服务渲染
基础语法 : const vm= new Vue ( {
el : "#app" ,
data : {
msg : "这是第一段数据" ,
msg1 : "这是第二段数据" ,
msg2 : "<i>这是第三段数据</i>" ,
arr : [ 1 , 2 , 3 , 4 ] ,
arrObj : [ {
id : 0 } , {
id : 1 } , {
id : 2 } ] ,
obj : {
id : 0 , id : 1 , id : 2 , id : 3 } ,
} ,
created ( ) {
} ,
beforeMount ( ) {
}
mounted ( ) {
}
beforeUpdate ( ) {
}
methods : {
show ( ) {
console. log ( '这是第一个函数' )
} ,
}
updated ( ) {
}
destroyed ( ) {
}
} )
< div id= 'app' >
{
{
msg} }
< p v- text= 'msg1' > 第1 段< p>
< p v- html= 'msg2' > 第2 段< p>
< p v- bind: title= "msg" > 第3 段< p>
: title= "{msg:true}"
< button v- on: click= "show" > 点击< button>
@click= "show()"
< input v- model= "msg" type= "text" >
< p : key= 'el.id' >
< p v- for = "(el,index) in arr" > < p>
< p v- for = "(el,index) in arrObj" > < p>
< p v- for = "(el,index,key) in obj" > < p>
< div v- if = "score>=90" > 优秀< div>
< div v- else - if = "score>=80" > 合格< div>
< div v- else > 你个垃圾< div>
< p v- show>= "90" > 显示/ 隐藏< p>
< / div>
< p : class = "{ 'aa':true, 'bb':false }" > < p>
< p : class = "classObject" > < p> classObject: {
box : true }
< p : class = "[ aa, bb ]" > < p> aa: 'active'
< p : style= "{ color:aa, font-size:bb+'px' }" > < p>
< p : class = "class" > < p> class : {
color : 'red' , fontSize : '20px' }
< p : class = "[aa,bb]" > < p> aa: {
color : 'red' } , bb : {
fontSize : '20px' }
1.vue的ajax
Vue的ajax请求
axios. get ( 'http://127.0.0.1:5000/api/getprodlist' ) . then ( ( res ) => {
console. log ( res) } )
2.vue的动画
v- enter
v- enter- active
v- enter- to
v- leave
v- leave- active
v- leave- to
提示 : 可以改变v, 设置一个动画前缀 比如: x- enter 来绑定指定动画标签
提示 : 给绑定添加标签, 可以在变化时, 执行指定的动画, 不写默认为v
提示 : transition默认是span标签, 可以通过 tag= "p" 改为指定的标签
. v- enter, . v- leave- to{
transform : translateX ( 150px) ;
}
. v- enter- active, . v- leave- active{
transition : all . 3s ease;
}
< button @click= "flag=!flag" > 点击< button>
< transition name= "x" >
< div v- show= "flag" > 显示/ 隐藏< div>
< transition>
new Vue ( {
el : '#app' , data : {
flag : true } } )
3.animated动画
引入 : < link rel= "stylesheet" href= "./lib/animate.min.css" >
< button @click= "flag=!flag" > 点击< button>
< transition enter- active- class = "fadeInRight" leave- active- class = "fadeOutRight" >
< div v- show= "flag" class = "animated" > 显示/ 隐藏< div>
< transition>
v- on: before- enter= "beforeEnter"
v- on: enter= "enter"
v- on: after- enter= "afterEnter"
v- on: enter- cancelled= "enterCancelled"
beforeEnter ( el ) {
el. style. transform= "translate(0,0)"
} ,
enter ( el, done ) {
el. offsetLeft
el. style. transform= "translate(300px,300px)"
el. style. transition= "all 1s ease"
done ( )
} ,
afterEnter ( ) {
this . flag= ! this . flag
}
4.过滤器
符号 : | 管道符号, {
{
msg | datafmt} }
Vue. filter ( 'datafmt' , ( data ) => {
return data. replace ( '好' , '坏' )
} )
{
{
msg | datafmt ( 'arr' ) } }
Vue. filter ( 'datafmt' , ( data, arr ) => {
return data. replace ( '好' , '坏' )
} )
在Vue里面, 挂载标签后, 里面增加 filters ( ) {
过滤器名字 ( data, arr ) {
return } }
5.列表动画
< transition- group appear tag= "div" >
< p v- for = "el in arr" : key= "el.id" > 显示/ 隐藏< p>
< transition- group>
6.自定义指令
自定义指令, 也就是定义一块区域, 绑定一个标签, 来更改这个标签的一些CSS 和JS 效果
创建 : Vue. directive ( '名字' , {
bind ( el, binding ) {
el. style. color= 'red'
} ,
inserted ( el ) {
} ,
updated ( ) {
}
} )
绑定 : < p v- foucs= "100" > < p>
调用 : 在Vue渲染范围里面的任意标签 增加 v- 名字 比如 v- foucs
在Vue渲染区域里面增加 directives{
focus : {
bind ( ) {
} } }
size ( el, binding ) {
el. style. coloe= 'red' }
7.自定义组件
自定义组件, 也就是自己设置一个自定义的html标签, 把内容填在这个标签里面
自定义组件的data, 是一个函数 data ( ) {
} 或者 data : ( ) => {
{
写内容} }
const Login= Vue. extend ( {
template : ` <div>这是一个自定义组件</div> `
} )
Vue. component ( 'my-login' , Login)
< my- login> < my- login>
const Login= {
template : ` <div>这是一个自定义组件</div> ` }
const Login= {
template : '#template' }
< template id= "template" >
< div> 这是一个自定义组件< div>
< template>
Vue渲染模块里面增加 components: {
'my-login' : Login }
组件的 data属性是私有的
const login= {
template : '#template' ,
data : {
msg : '这是自定义私有' ,
count : 1
}
}
< template id= "template" >
< div>
< p> {
{
msg} } -- - {
{
count} } < p>
< div>
< template>
8.组件传值
一, 父传子 data的传值, 默认是不共享
1. 在渲染的子组件上使用 v- bind 绑定要传递的父组件的data数据
2. 在子组件中使用 props 接收传递过来的数据
const login= {
props : [ 'msgs' ] ,
props : {
msg : {
type : String } }
template : ` <p>子组件</p> `
}
< login v- binf: msgs= 'msg' > < login>
msgs 是自定义的属性拿过来使用 msg 是父组件里面的data数据
二, 子传父 data的传值, 默认是不共享 也就是调用父组件的函数, 然后把子组件的值传过去
1. 在渲染的子组件上使用 v- on 绑定要传递的父组件的methods, 也就是启用事件函数
2. 在子组件中使用 this , $emit ( ) 调用传递过来的函数, 调用的同时传递子组件的数据
< Login @getdatas= "getdata" > < Login>
提示 : 右边是父组件的函数明, 左边自定义, 与下面调用同名
created ( ) {
this . $emit ( 'getdatas' , '传过去的值' ) }
methods : {
getdata ( data ) {
} }
三, 子组件之间传值 把两个子组件, 挂载在同一个Vue对象上面 两个子组件依旧是父组件的私有组件
1. 实例化一个新的 vue 对象
2. 定义2 个兄弟组件
const bus= new Vue ( )
const Com1= {
template : ` <p @click='show'>第一个子组件</p> ` ,
methods : {
show ( ) {
bus. $emit ( 'getdata' , '传过去的值' )
}
}
}
const Com1= {
template : ` <p>第二个子组件</p> ` ,
created ( ) {
bus. $on ( 'getdata' , ( data ) => {
} )
}
}
9.组件动画
也就是通过组件来控制一个元素的出现和消失, 来进行Vue动画, 其中给transition 标签添加 mode= 'out-in' , 代表这次动画执行完了, 才进行后续的
用三个按钮, 来改变父组件里面data的值
10.组件插槽
插槽就是 : 在子组件自定义标签里面, 如果没有内容, 就传一个默认内容, , 有内容, 就会用插槽的内容
一, 匿名插槽, 插槽没有名字, 就对应一个
const Com1= {
template : ` <div><slot>默认内容</slot></div> `
}
new Vue ( {
components : {
Com1 } } )
< Com1> < Com1>
二, 具明插槽, 插槽存在名字, 一个插槽对应被替换的标签
const Com1= {
template : ` <div>
<slot name='header'>默认内容</slot> //给两个插槽都添加名字
<slot name='footer'>默认内容</slot>
</div> `
}
< Com1>
< div slot= 'header' > 这是头< div>
< div slot= 'footer' > 这是尾< div>
< Com1>
1. 插槽添加, 标签不添加, 会显示插槽的内容, 且排成一行
2. 插槽不添加, 标签添加, 会显示插槽的内容, 且排成一行
3. 两个都不添加, 插槽会视为一个整体, 子组件里面标签有几个, 就出现几次, 多次重复, 内容为标签里的
4. 标签添加一个插槽都不添加 , 同上, 没有添加名字的标签, 会根据插槽重复多次
总结 : 如果出现多行标签, 就需要都添加名字, 不然会重复错乱
三, 作用域插槽, 让插槽和标签的数据都是动态的,也就是写入的内容是动态的
const Com1= {
data : {
msg : '这是子组件' } ,
template : ` <div><slot :msg='msg'>默认内容</slot></div> `
}
< Com1> < mark slot- scope= "scope" > {
{
scope. msg} } < mark> < Com1>
提示 : / / 这里scope是一个对象 {
msg : '子组件的数据' } 所以需要scope. msg才能拿到内容
扩展 : 优化标签 < template> < template> 在Vue里可以优化标签里面没有显示多余的内容, 减少代码量
11.Vue路由
需要元素 :
` <script src="./lib/vue-router.js"></script> `
` <script src="./lib/vue.js"></script> `
使用的标签
` <router-link> ` 是一个组件, 用于设置导航链接, to= '' 为目标地址 该标签默认渲染为a标签
const Login= {
template : ` <div>第一个组件</div> ` }
const Register= {
template : ` <div>第二个组件</div> ` }
const router= new VueRouter ( {
router : [
{
path : '/' , redirect : '/Login' } ,
{
path : 'Login' , component : Login} ,
{
path : 'Register' , component : Register} ,
linkActiveClass : 'active'
]
} )
new Vue ( {
el : 'app' , router : router } )
< router- link to= '/Login' tag= 'span' > Login< router- link>
< router- link to= '/Register' tag= 'span' > Register< router- link>
< router- view> < router- view>
第一种, query方式
to= '/Login?name=aa&age=123'
在Login组件里面, 通过data ( ) {
return {
name : this . $router. query. name } } 获取url的参数
然后可直接写入在 template: ` <div>{
{name}}第一个组件</div> `
第二种, params方式
to= '/Register/bbb/456'
需要在'实例化路由' 里面把 path: '/Register/:name/:age'
在Register组件里面, 通过data ( ) {
return {
name : this . $router. params. name } } 获取url的参数
然后可直接写入在 template: ` <div>{
{name}}第二个组件</div> `
二, 编程式导航路由
通过点击按钮, 启用一个函数, 函数里面写好了路由的url路径, 根据路径来判断访问的组件, 获取内容
goLogin ( ) {
this . $router. push ( '/login?name=aaa&age=123' ) }
template : ` <div>{
{$route.query.name}}---{
{$route.params.name}}</div> `
三, 命名视图
类似具名组件, 给` <router-link> ` 标签设置名字, 然后渲染对应的组件
'<router-view name=' main'></router-view>'
routers : [ {
path : '/' ,
components : {
default : Header,
main : Main
}
} ]
12Vue中的三个属性
methods : {
}
watch : {
}
例子 : show ( newVal, oldVal ) {
} newVal是最新的数据 oldVal是更新之前的数据
computed : {
}
13.Vue-UI
查看有没有安装/ 版本号: vue- V
初始化项目 : vue init webpack 名字
npm install vue- cli - g
npm install @vue/ cli- init
初始化项目 : vue create 名字
npm install @vue/ cli - g
npm install - g @vue/ cli- service- global
` 注意: 用 vue ui打开,选择所需组件,router等,目录 `
eslint
vetur
设置里面添加自动格式化代码
"eslint.autoFixOnSave" : true ,
"eslint.validate" : [
"javascript" ,
"javascriptreact" ,
{
"language" : "vue" ,
"autoFix" : true
}
] ,
安装 : npm i vant - S
操作步骤 : https: / / youzan. github. io/ vant/ ? source= vuejsorg#/ zh- CN / quickstart
` 提示: 有两种方式,一直是全局引入,一直是按需求引入指定的 `
把引入文件复制到main. js里面, 然后就能直接使用了
import Vant from 'vant'
import 'vant/lib/index.css'
Vue. use ( Vant)
安装 : npm i babel- plugin- import - D
` 对于使用 babel7 的用户,可以在 babel.config.js 中配置 `
module. exports = {
plugins : [
[ 'import' , {
libraryName : 'vant' ,
libraryDirectory : 'es' ,
style : true
} , 'vant' ]
]
} ;
把所需要的文件, 在main. js里面直接引入就能使用了
import {
NavBar, Tabbar, TabbarItem } from 'vant'
Vue. use ( NavBar) . use ( Tabbar) . use ( TabbarItem)
14.Vuex
Vuex 是一个专为 Vue. js 应用程序开发的状态管理模式。它采用集中式存储管理应用的所有组件的状态
Vuex 是一个全局存储的工具, 里面的属性和方法都是公有的, 可以在项目任何地方调用和设置
Vue Components ( 用户) > Actions ( 请求) > Mutations ( 执行请求并返回) > State ( 存储结果数据)
4. 实例化vuex const store= new vuex. Store ( {
state : {
} ,
mutations : {
SupCount ( stale, obj ) {
}
} ,
actions : {
SupCount ( {
commit} , obj) {
commit ( 'SupCount' , obj)
}
} ,
getters : {
getCount ( state ) {
return '$' + state. count
}
} ,
module : {
}
} )
调用vuex里面数据的方式
{
{
$store. state. count } }
{
{
$store. getters. getCount} }
$store. dispatch ( 'SupCount' , '嘿嘿' )
$store. commit ( 'SupCount' , '哄哄' )
可以通过执行vue的函数, 然后在里面执行vuex的函数, 前面需要加this
辅助函数的调用方式
import {
mapState } from 'vuex'
export default {
computed : {
... mapState ( [ 'count' , 'name' ] )
}
}
import {
mapActions } from 'vuex'
... mapActions ( [ 'SupCount' ] )
五,项目优化
一, 项目添加nprogress加载进度条, 也就是页面跳转, 顶部的进度条
import NProgress from 'nprogress'
import 'nprogress/nprogress.css'
axios. interceptors. request. use ( function ( config ) {
NProgress. start ( )
return config
} )
axios. interceptors. response. use ( function ( response ) {
NProgress. done ( )
return response
} )
一, 自动移除console. log ( ) 打印代码
或者cnpm i babel- plugin- transform- remove- console - D
const prodPlugins = [ ]
if ( process. env. NODE_ENV === 'production' ) {
prodPlugins. push ( 'transform-remove-console' )
}
module. exports = {
'presets' : [
'@vue/app'
] ,
plugins : [
[
'import' ,
{
'libraryName' : 'vant' ,
'libraryDirectory' : 'es' ,
'style' : true
} ,
'vant'
] ,
... prodPlugins
]
}
一, 为开发模式与发布模式设置不同的打包入口
module. exports = {
chainWebpack : config => {
config. when ( process. env. NODE_ENV === 'production' , config => {
config
. entry ( 'app' )
. clear ( )
. add ( './src/main-prod.js' )
} )
config. when ( process. env. NODE_ENV === 'development' , config => {
config
. entry ( 'app' )
. clear ( )
. add ( './src/main-dev.js' )
} )
}
}
一, 通过 externals 加载外部 CDN 资源, 让压缩后的文件更小
config
. set ( 'externals' , {
vue : 'Vue' ,
'vue-router' : 'VueRouter' ,
axios : 'axios' ,
nprogress : 'NProgress'
} )
` <title><%= htmlWebpackPlugin.options.isProd ? '' : 'dev - ' %>mall-vue</title>
<% if(htmlWebpackPlugin.options.isProd){ %>
<title>vue-ssr</title>
<!-- nprogress 的样式表文件 -->
<link rel="stylesheet" href="https://cdn.staticfile.org/nprogress/0.2.0/nprogress.min.css" />
<!-- vant 的样式表文件 -->
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/[email protected] /lib/index.css">
<script src="https://cdn.staticfile.org/vue/2.5.22/vue.min.js"></script>
<script src="https://cdn.staticfile.org/vue-router/3.0.1/vue-router.min.js"></script>
<script src="https://cdn.staticfile.org/axios/0.18.0/axios.min.js"></script>
<!-- nprogress 的 js 文件 -->
<script src="https://cdn.staticfile.org/nprogress/0.2.0/nprogress.min.js"></script>
<!-- moment 的 js 文件 -->
<script src="https://cdn.staticfile.org/moment.js/2.24.0/moment.min.js"></script>
<!-- vant 的 js 文件 -->
<script src="https://cdn.jsdelivr.net/npm/[email protected] /lib/vant.min.js"></script>
<%}%> `
一, 首页内容定制, 也是解决上面CDN 出现的BUG , 也就是重复出现路由调用的问题, 这里来根据情况使用或者不使用
发布模式加入
config. plugin ( 'html' ) . tap ( args => {
args[ 0 ] . isProd = true
return args
} )
开发模式加入
config. plugin ( 'html' ) . tap ( args => {
args[ 0 ] . isProd = false
return args
} )
` <title><%= htmlWebpackPlugin.options.isProd ? '' : 'dev - ' %>mall-vue</title>
<% if(htmlWebpackPlugin.options.isProd){ %>
<title>vue-ssr</title>
<!-- nprogress 的样式表文件 -->
<link rel="stylesheet" href="https://cdn.staticfile.org/nprogress/0.2.0/nprogress.min.css" />
<!-- vant 的样式表文件 -->
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/[email protected] /lib/index.css">
<script src="https://cdn.staticfile.org/vue/2.5.22/vue.min.js"></script>
<script src="https://cdn.staticfile.org/vue-router/3.0.1/vue-router.min.js"></script>
<script src="https://cdn.staticfile.org/axios/0.18.0/axios.min.js"></script>
<!-- nprogress 的 js 文件 -->
<script src="https://cdn.staticfile.org/nprogress/0.2.0/nprogress.min.js"></script>
<!-- moment 的 js 文件 -->
<script src="https://cdn.staticfile.org/moment.js/2.24.0/moment.min.js"></script>
<!-- vant 的 js 文件 -->
<script src="https://cdn.jsdelivr.net/npm/[email protected] /lib/vant.min.js"></script>
<%}%> `
一, 实现路由懒加载, 也就是避免重复的加载, 加载的时候设置缓存
` <transition>
<keep-alive>
<router-view></router-view>
</keep-alive>
</transition> `
提示, 要删除原有的router- view标签, 不然可能会出现两次
二, 按需求引入组件, 也就是页面被访问的时候, 指定的组件才会加载, 不会一次性全加载
plugins : [
'@babel/plugin-syntax-dynamic-import'
]
const Home = ( ) => import ( '../views/Home' )
六,项目流程
git clone https: / / gitee. com/ fj2321605193/ vue- app. git
git checkout - b 分支名 git branch
git checkout '分支名' git merge 分支名
git add . git status
git commit - m '这次操作的注释'
git push - u origin 分支名
七,微信小程序
小程序文件简介
pages -- - 存放所有的页面
utils -- - 存放所有的工具类
app. js -- - 小程序的入口文件
app. json -- - 小程序的配置文件
app. wxss -- - 公共的css样式
project. config. json -- - 存放一些信息
sitemap. json -- - 文档说明文件
一, pages 小程序的组成部分
` onLoad/类似vue的created onReady/类似vue的mounted `
` onShow/当前页面是否激活 onHide/当前页面是否隐藏 `
` onUnload/卸载完页面 `
二, utils
三, app. json 小程序配置文件
window全局样式根据小程序的框架- 全局配置- window来进行配置, 也可以根据全局配置, 来增加一些内容
tabbar设置下面导航栏, 需要配合一些小图片
app. js 小程序应用的的生命周期
onLaunch : function ( ) {
}
onShow : function ( ) {
}
onHide : function ( ) {
}
与vue语法不一样的地方, 除了下面的, 其他的跟vue一样
wx : for = "{
{arr}}" {
{
item} } -- - {
{
index} }
wx : for - item= "value"
wx : key= "index"
bindtab= "" 点击事件 bindinput= "aaa" 输入框内容变化事件
提示 : 事件跟vue不一样, 这个可以直接写在data的外面, 函数有一个默认的e参数
show ( e ) {
}
value= "{
{msg}}"
this . data. msg
this . setData ( {
msg : 'ssr' } )
wx : if = "{
{true}}" wx : else
hidden= "true"
参考小程序框架- 模板 进行设置和使用 数据的定义也根据模板来
< view> {
{
foo. getData ( 'ygy' ) } } < view>
< wxs module= "foo" >
module. exports= {
getData : function ( aa ) {
return aa;
}
}
< wxs>
八,小程序项目
使用工具 mpvue. com
1. 先安装node. js
2. 全局安装vue- cli
3. 创建一个基于mpvue- quickstart 模板的新项目
4 . mpvue中配置 vant- weapp 下载资源
5. 把下载的资源dist目录下的所有文件复制到你项目的/ static / vant/ 目录下
6. 打开 微信开发者工具中的 想起- 本地设置- ES6 转ES5 功能
7. 运行 : npm run dev
8. 导入项目, 用微信开发工具根据路径导入
直接复制一个页面, 比如home, 整个复制, 然后修改文件名, 在app. json里面的pages添加上路径, 然后重新编译
1. 下载
2. 把下载的资源dist目录下的所有文件复制到你项目的/ static / vant/ 目录下
3. 打开 微信开发者工具中的 想起- 本地设置- ES6 转ES5 功能
4. 在指定要用的页面, 新建一个main. json文件, 里面添加
{
"usingComponents" : {
"van-button" : "/static/vant/button/index" ,
}
}
5. 在页面中正常使用vant组件内容 < van- button> 测试< / van- button>
1. 安装 yarn add flyio - S npm i flyio - S
2. 在main. js引入, 然后挂载到Vue的原型上, 就可以在任何地方用this . $http调用了
3. 或者使用原生的, 放在自执行 created里面
wx. request ( {
url : 'http://127.0.0.1:5000/api/getlunbo' ,
method : 'GET' ,
success : res => {
console. log ( res)
}
} )
1. 一个完整的项目
1. 全局安装vue- cli后, 创建一个mpvue项目 vue init mpvue/ mpvue- quickstart + 项目名
2. cnpm i安装全部的node包, 包括额外安装less
3. 修改app. json文件, 新文件路径和tabBar的路径信息
4. 访问小程序组件, 使用根据介绍使用对应的组件
5. 单位尽量采用 rpx, 一屏正常是750rpx, 做不出效果就用%
6. 新建文件 src/ api/ fly. js , 把传值的代码都复制进去, 也就跟安装flyio差不多, 用来ajax请求端口
7. 在main. js上, 把fly挂载到Vue的原型上面
8. 把fly. js的host请求路径更改为 locally. uieee. com, 并打开, 根据内容拿数据
9. 微信开发工具- 详情- 本地设置, 把不效验合法域名打开, 然后正常请求数据
10. 通过上拉或者下拉等其他生命周期函数来触发事件
11. 其他 : onLoad ( options ) {
}
wx. setNavigationBarTitle ( {
title : res. name} )
12. 上下拉菜单思路 : 设定好页面id, 页数, 展示个数, 一个布尔值, 根据布尔值判断是否继续展示更多, 每上拉一次, 就访问新的数据, 进行一次数组合并, 下拉就重置所有数据, 且快速关闭刷新事件
await this . getShops ( )
await wx. stopPullDownRefresh ( )
import Fly from 'flyio/dist/npm/wx'
const fly = new Fly ( )
const host = 'http://127.0.0.1:5000/'
fly. interceptors. request. use (
( request ) => {
wx. showLoading ( {
title : '加载中' ,
mask : true
} )
console. log ( request)
request. headers = {
'X-Tag' : 'flyio' ,
'content-type' : 'application/json'
}
let authParams = {
'categoryType' : 'SaleGoodsType@sim' ,
'streamNo' : 'wxapp153570682909641893' ,
'reqSource' : 'MALL_H5' ,
'appid' : 'string' ,
'timestamp' : new Date ( ) . getTime ( ) ,
'sign' : 'string'
}
request. body && Object. keys ( request. body) . forEach ( ( val ) => {
if ( request. body[ val] === '' ) {
delete request. body[ val]
} ;
} )
request. body = {
... request. body,
... authParams
}
return request
} )
fly. interceptors. response. use ( ( response ) => {
wx. hideLoading ( )
return response. data
} ,
( err ) => {
console. log ( err)
wx. hideLoading ( )
if ( err) {
return '请求失败'
} ;
}
)
fly. config. baseURL = host
export default fly
九,create-react-app
create- teact- app是一个构建React单页面的脚手架工具,跟vue- cli差不多, 创建的项目样式跟结构是分离的
生命周期函数
constructor ( props ) {
super ( ) this . state= {
} }
state= {
}
componentWillMout
rander
componentDidMount
shouldComponentUpdate
componentWillReceiveProps ( nextprops ) {
}
ReactDOM. render (
DIV ,
< App / > ,
document. getElementById ( 'root' )
) ;
提示:引入的模块加入是 < App / > 直接使用加入是 DIV
const App = ( ) => {
return ( < h3> 这是一个无状态组件< / h3> )
}
class App extends React. Component {
render ( ) {
return ( < h3> 这是一个有状态组件< / h3> )
}
}
import rfc from './components'
< rfc title= 'rfc' > < / rfc> 标签里面直接出现组件return 的内容, 且传一个值给无状态组件
提示 : 在app. js的组件标签里面, 定义一个title值传过去给组件, {
this . state. rfc} 的写法是变量
export default function Rfc ( props ) {
return ( < div> 这是模块的无状态组件 {
props. title} < / div> )
}
提示 : props. title 接收传的值 props. children 只接收组件的内容, 不接收传的值
` 传值时设置默认内容,设置默认内容后,就不需要接收app.js那边传过来的值了 `
Rfc. defaultProps= {
title : 'rfc' }
export default class Rcc extends Component {
` 传值设置默认内容,设置默认内容后,就不需要接收app.js那边传过来的值了 `
static defaultProps= {
title : 'rcc' }
render ( ) {
return ( < div> 这是有状态组件-- - 传值{
this . props. title} < / div> )
}
}
提示 : this . props. title 接收传的值 this . props. children 只接收组件的内容, 不接收传的值
提示 : 如果传的值时变量, 需要再app. js里面加入一个state = ( ) => {
定义变量}
安装 : npm i prop- types - D
引入 : import PropTypes from 'prop-types'
设置 : 就直接写在无状态组件模块里面
Rfc. propTypes= {
title : PropTypes. string
}
提示 : 传值方式发生改变 < Rfc title= {
1 } > 无状态组件传值< / Rfc>
export default class Rcc extends Component {
static propTypes= {
tiele : PropTypes. string }
render ( ) {
return ( < div> 这是有状态组件-- - 传值{
this . props. title} < / div> )
}
}
提示 : 传值方式发生改变 < Rcc title= {
1 } > 无状态组件传值< / Rcc>
1. 正常新建一个rcc有状态组件
2. APP . js里面引入
3. div里面再加一个Input的框, 里面要有value和onChange事件
< input type= 'text' value= {
this . state. value} onChange= {
this . handleChangeValue . bind ( this ) } / >
4. 同级写上函数
handleChangeValue ( e ) {
console. log ( e. target. value)
this . setState ( {
value : e. target. value
} )
console. log ( this . state. value)
}
state= {
value : 1
}
1. 正常新建一个rcc有状态组件
2. APP . js里面引入
3. div里面加入 < input type= "text" ref= 'inputRef' onChange= {
this . handChangeRef} / >
4. 通过onChange来触发事件
handChangeRef = ( e ) => {
console. log ( this . refs. inputRef. value)
}
1. app. js引入app. css文件
2. div里面的标签上正常加内联样式, app. css里面直接写css样式内容, ( 但是会报错)
3. 不报错安装 : npm i classnames - S 且在app. js引入 import calssNames from 'classnames'
4. 样式名有class 变成className
5. className= {
classNames ( {
title : true } )
1.页面渲染模式
只会渲染发生改变了的部分, 不会重新渲染全部
原理 : 会先生成一个虚拟的DOM , 去跟页面的DOM 对比, 用diff算法把发生了改变的进行替换
一, 创建虚拟DOM ( 在index. js里面 )
const App= React. createElement ( 'div' , 'null' , 'ssr' )
提示 : 标签内容也可以是一个标签或者变量, 变量也是标签
const App= < div> < span> 第二种写法< / span> < / div>
二, 组件布局-- - 传值
新建js文件, 生成无状态组件 ( rfc)
三, 组件遍历-- - 类似vue的v- for , 根据数组的来遍历出多少个标签
1. 在app. js的state里面定义一个变量数组
2. 把该数组传到某个组件
3. 组件接收, 使用map遍历, 然后return 一个标签出来, 遍历的标签上也要写key定义唯一值
< div>
{
this . props. todes. map ( el => {
return < li key= {
el. id} > {
el. title} < li> } ) }
< div>
四, 组件传值, 子传父
1. 子级设置一个受控组件 ( 双向绑定) , 一个点击触发事件按钮
2. state的写法需要 constructor ( props ) {
super ( ) this . state= {
value : 'ssr' } }
提示 : 固定写法, props能接收父组件 ( app. js) 的传值
3. 父组件自定义一个函数 addbtn = ( todo ) => {
this . setState ( title) }
提示 : 在子组件标签上, 把这个函数传过去, 子组件用props接收 ( 如上)
提示 : todo是子级传过来的值, setState对页面重新渲染
4. 子组件通过this . props. addbtn ( ) 拿到传过来的函数, 且传值过去
5. 父组件获取, 然后设置到数组里面, 用this . setState ( ) 重新渲染
6. 子组件通过在标签上加ref= {
this . inputref} , 可以拿到input框 ( 非受控组件 )
7. this . inputRef= createRef ( )
提示 : import react, {
createRef} from 'react'
8. 对input框设置事件,
提示 : 传过去的值注意类型
五, 请求端口, axios
1. 安装 : yarn add axios - S
2. 在app. js里面引入, 或者在index. js里面挂载到全局上面
3. axios. defaults. baseURL= '端口开始部分' React. Component . prototype. $http= axios
4. 使用 : this . $http. get ( ) . then ( res => {
} )
六, 路由的使用router
1. 官网看文档 : react- router
2. 安装 : yarn add react- router- dom - S 也可以装react- router
3. 引入 : import {
HashRouter as Router, Route, Link} from 'react-router-dom'
4. 在app. js里面, 把div改成Router标签
5. 设置跳转链接 < Link to= '/login' > < Link>
6. 配置路由规则 < Route path= '/login' component= {
Login} > < Route>
7. 传参 < Link to= '/login?name=abc&age=18' > < Link>
8. 接收 componentDidMount声明周期函数里面执行
const params= new URLSearchParams ( this . props. location. search)
params. get ( 'name' )
提示 : 得到? 号后面的内容, 然后进行解析, 下面直接获取
9. 第二种传参 < Link to= '/ login/ abc/ 18 > < Link> 直接传数据, 但是需要站位
占位 : < Route path= '/login/:name/:age' component= {
Login} > < / Route>
10. 第二种接收 this . props. match. params. name
七, 嵌套路由
就是在子组件里面再设置一个路由跳转
八, URL 没有#号
把引入改成 import {
BrowseRouter as Router, Route, Link} from 'react-router-dom'
2. redux
1. 介绍 : 如同vue的vuex, 一种可预测的状态容器
2. 安装 : yarn add redux - S
3. 新建 : 新建路径 src/ store/ index. js 引入 import {
createStore} from 'redux' , 且暴露
暴露 : export default createStore ( reducer) , 引入的下面的文件暴露
4. 新建 : 新建路径 src/ store/ reduecer. js
暴露 : export default ( state= defaultState, action ) => {
return state }
提示 : defaultState类似vuex的state, 存数据的地方, 通过上面return 出去给外面引用
5. App. js引入store/ index, 在constructor ( ) {
} 加入 this . state= store. getState ( )
提示 : 这里直接就拿到了另一个文件return 出来的数据
6. 发送更改请求, App. js定义一个点击按钮触发事件, 定义一个对象, 通过stort. dispatch ( ) 传过去
提示 : stort是引入的一个组件, 要传到哪个组件去, dispatch是发生改变启动的函数
7. 接收更改请求, 在 ( 第4 条暴露) 通过action接收到传过来的内容, 然后判断类型, 进行修改
8. 监听更改的请求, 在app. js加入函数 listenStore = ( ) => {
} , 然后在constructor里面自执行
提示 : 自执行 store. subscribe ( this . listenStore)
9. 页面渲染 在监听函数加入 this . setState ( store. getState ( ) )
一, react- redux
1. 安装 : yarn add react- redux - S
2. 引入 : improt {
Provider} from 'react-redux'
3. 使用, 在index. js里面, 把APP 标签包起来 < Provider> < App/ > < Provider>
4. 引入 store import store from 'store'
3. antd和Layout
improt {
Button} from 'antd'
4.百度地图
http : / / lbsyun. baidu. com/ index. php? title= jspopular3. 0 / guide/ helloworld
注意, 设置放地图的元素的宽和高
1. 可以打开示例DEMO 来设置一些功能, 逆解析是来解析定位经纬度
5.mock后台模拟
router. get ( '/api/data' , ( req, res ) => {
res. send ( ) } )
注意 : 在设置新的内容的时候, 需要先从mock里面拿到, 比如 var Random= Mock. Random
6.Layout组件