//0. 为什么出现跨域
1. 浏览器默认的一种'同源策略'
2. 协议-域名-端口不统一造成的跨域
//1. 跨域资源共享,在后端设置cors (nodejs的express服务下)
1. 后端安装: yarn add cors -S
2. 引入: const cors = require('cors')
3. 直接挂载: App.use(cors())
//2. 后台处理CORS,加入一句话 (加载设置响应头部分)
header("Access-Control-Allow-Origin: * ") //* 代表所有网站,可设置指定网站,逗号隔开
//3. JSONP,一种非官方的跨域解决方案,只能是get请求(因为只能是src)
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 //全局动态生成一个函数, 在window上
var oScript = document.createElement('script') //创建一个script
//设置标签的src
let url= setting.url+'?'+Params(setting.data)+setting.Callback+'='+fnName
oScript.setAttribute('src',url)
document.body.appendChild(oScript)
//标签加载完成了,获取到数据了,就删除掉
oScript.onload = function(){ //每个带有src的标签都带有一个onload事件
this.remove()
}
}
提示: setting就是ajax,里面要填的一些请求值
封装好了后,就可以用类似ajax的方式调用访问端口拿到数据
JSONP({
url:'访问的端口',
data:{ //要传的值,query
wd:'你好'
},
Callback:'cb', //回调的函数
success:function(data){
console.log(data)
}
})
1. let const 定义一个变量
// 两个都没有变量提升
// let具有块级作用域{}, 也就是局部使用才有效
// const 是一个常量, 无法被修改
一, 解构对象赋值
var obj={
name:"fly",
age:18
}
//解构语法: var {}=obj //把obj对象赋值给另外一个对象
var {name,age}=obj //对象里面的值互相对应
二, 解构数组赋值
var arr=[1,2,3,4]
//解构语法: var []=arr //把arr数组赋值给另外一个数组
var [a,b,c,d]=arr //数组里面的值互相对应
var [,,c,d]=arr //留空代表不赋值,但是一定要有位置
var [,...Arr]=arr //把后面三个值赋值给Arr
console.log(Arr) //[2,3,4]
console.log(...Arr) //2,3,4
str.includes("a") //查找一个字符串里面是否有该值,找到返回true
str.startsWith("a") //查找一个字符串是否已该值开头,返回true或者false
str.endsWith("z") //查找一个字符串是否已该值结尾,返回true或者false
//上面三个方法都可以添加第二个参数,为从第几个开始
//字符串的补全( 第一个参数:最低长度 第二个参数:补全的内容 )
'x'.padStart(5, 'ab') //x只有一个,所以会利用ab在开头补全至 ababx
'x'.padEnd(5, 'ab') //x只有一个,所以会利用ab在结尾补全至 xabab
//字符串模板 `${}`
var str="fly"
var str1=`${str}`
arr.indexOf() //在一个数组/字符串里面查找一个内容的下标,如果没找到下标就是-1
arr.forEach() //遍历数组,里面需要加函数来执行,没有返回值,对原数组没影响
语法: arr.forEach((el,index,arr)=>{执行})
el: 数组里面的每一个数值
index: 数值里面每一个数值的下标
arr: 数组本身
arr.map() //遍历数组,里面需要加函数来执行,没有返回值,对原数组没影响
语法: 跟forEach()语法一样
for..of //es6提供的一种新的遍历方式
语法: for(var el of arr.keys(arr)){ console.log(el) }
keys: el得到下标 values: el得到值 entries: el得到实例( 下标和值 )
arr.filter() //获取数组中你想要的元素,不改变原数组,需要return来接收
语法: Arr=arr.filter(el){ return el>3 }
arr.some() //查找数组中的内容,找到了,就返回true,后面的不找了,需要return来接收
语法: arr.some((el)=>{ if( el==20 ){ return el } })
obj.findIndex() //查找一个对象,符合就返回该内容
语法: obj.findIndex((el)=>{ if(el.id == 0){ return true } }) //得到这个对象id的值
obj.find() //查找一个对象,符合就返回该内容
语法: obj.find((el)=>{ if(el.id == 0){ return true } }) //得到这个对象
一. 对象的简写
语法: var obj={ name,age:18 } //键和值相等,只需要写一个
二,对象的拷贝( 浅拷贝↓ 深拷贝:用JSON转字符串再转对象 )
obj.assign() //对象的浅拷贝和合并( 只拷贝第一层的内容,第二层,第三层的内容两个对象共享 )
语法: obj1 = obj.assign({}, obj) //把obj拷贝给空元素,赋于给obj1
一, 设置默认参数
function show(str="fly"){} //如果str没有传值进来,则默认为fly
二, 默认参数解构赋值
function show({x,y=2}){} show({x:1}) //y默认为2 x没传参数为undefined
三, reset和扩展运算符
function show(...rest){} //在函数调用的时候使用的 ...obj 叫做如est参数
... 扩展运算符 //...arr 可以把一个数组转成纯数字 1,2,3,4
四, 箭头函数
()=>{} //只执行一行的时候,不需要return和(){} 里面的this,默认指向外面一层
继承: 子类拥有父类的属性和方法,子类可以重写父类的方法,子类可以新增自己的属性和方法
//父类
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{ //通过extends让Abc继承Person
construstonr(name,age,upw){ //接收参数
super(name,age) //继承父类的属性
this.upw=upw //获取自身新增的值
}
mysay(){ //除了继承父类的,还便携自己新增的
console.log(this.upw)
}
}
var A=new Abc('小炮','19','258')
Nodejs是一个基于 Chrome V8 引擎的 JavaScript 运行环境,Ndoejs使用了一个事件驱动,非阻塞式I/O的模型,使其轻量又高效,Nodejs的包管理器 npm ,是全球最大的开源库生态环境
下载地址: http://nodejs.cn/
卸载: 删除C:\Program Files\nodejs C:\users\用户名\appData\Roaming\npm 然后重装
1. express项目生成器
//创建跟目录文件夹
//文件夹初始 npm init 然后安装express包
//安装: npm install express-generator -g
//创建项目 express 名字 然后安装依赖包和运行项目
2. 安装express框架
第一步: npm init -y //初始化一个环境
第二步: 在项目目录下安装 cnpm i express --save-dev
简介: 主要用来文件的读取,写入,修改,追加,重命名,新建
引入: const fs=require("fs") //该模块系统自带
//读取一个文件的内容
fs.radFile("./node.txt",'utf8',(err,data)=>{ //err错误先行,data读取的内容 utf8解析二进制
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('拷贝成功')
})
path 模块提供用于处理文件路径和目录路径的实用工具。
引入: const path=require("path") //系统自带模块
//路径的拼接
path.join(__dirname,'./res','/123.txt') //__dirname是获取该目录下的文件
//获取文件扩展名
引入: const http=require("http") //系统自带模块
//创建服务
const server=http.createServer()
server.on('request',(req,res)=>{})
//监听窗口
server.listen(3000,()=>{ console.log("服务器启动中") })
一,中间件的特性
1.中间件就是一个普通函数,有三个参数,req,res,next
2.中间件需要用use执行,先安装,后执行,后续执行一定要加next()
二,npm切换淘宝镜像
//1.直接设置淘宝镜像
npm config set registry https://registry.npm.taobao.org
npm config get registry
//2.安装yarn 是最快的
npm install yarn -g //设置淘宝镜像,跟上面一样,把npm改成yarn
//3.cnpm 中国版的npm,镜像包只有淘宝有
npm install -g cnpm --registry=https://registry.npm.taobao.org
三,npm/cnpm/yarn一些常用命令
//1.npm
npm init -y //初始化 package.json
npm install //根据 package.json文件下载所有包
npm i 包名(express) -save-dev
-g //全局包
--save //生产需要 可缩写成 -S
--save-dev //开发需要 可缩写成 -D
npm uninstall 包名(express) -save-dev //卸载一个包
//2.cnpm
操作跟npm一摸一样,只是npm变成了cnpm
//3.yarn
操作跟npm一摸一样,只是npm变成了yarn
安装: npm init -y //初始化文件夹
设置: 文件夹内默认访问的主文件路径 package.json
暴露: module.exports={}
//自定义模块也就是自己写一个函数,进行封装,然后暴露出去,让外部可以引用
解析: 查询字符串模块,一般是对http请求所带的数据进行解析,对应四个方法
引入: const querystring=require("querystring") //系统自带模块
//1.方法一 querystring.parse() 将一个字符串反序列化转为一个对象 键不带引号
语法: querystring.parse(name=ygy&age=18) 转化后 {name:'ygy',age:18}
//2.方法二 querystring.stringify() 将一个对象序列化转为一个字符串
语法: querystring.stringify({name:'ygy',age:18}) 转化后 name=ygy&age=18
//3.方法三 querystring.escape() 对字符串进行编码
语法: querystring.escape(str) 转化后 %E5%AD%97%E7%AC%A6%E4%B8%B2
//4.方法四 querystring.unescape() 对编码进行解析
语法: querystring.unescape(%E5%AD%97) 转化后 '字符串'
安装: cnpm i mysql --save-dev( 可以缩写成 -D )
引入: const mysql=require("mysql")
//1.创建连接对象
var connection=mysql.createConnection({
host:"localhost", //sql主机名
user:"root", //用户名
password:"root", //密码(一般不设置就填空)
database:"users" //数据库的名字
})
//2.开启/关闭连接数据库
connection.connect() //开启链接 connection.end() //关闭连接
//3.执行数据库sql语句
var sql="SELECT * FROM users" //查询一个表
connection.query(sql,'查询的内容',(err,result)=>{
if(err) throw err.message //跟return不同,这里报错了还会继续执行
console.log('查询到的数据是'+result) //result返回一个数组
})
//1.增加一条信息 insert into 表名称 (字段)values('值')
insert into `users` (u_name,u_pwd)values('abc123','123')
//2.删除一条信息 根据id删除一些数据
delete from `users` where u_id=1
//3.查询一条信息 前面设置展现哪些内容,后面是根据什么查询
select `u_id`,`u_name` from users where u_name='abc123' and u_pwd='123'
//4.修改一条信息 根据id修改某个信息 表名-修改的信息-根据什么修改
update users set u_sex='女' where u_id=1
//5.查询一个表数据 *代表所有
SELECT*FROM users
//6.特殊修改法: 修改状态status=0 查询的时候查询状态 1
bodyparser 用来解析post请求的传过来的数据,不使用该中间件,解析的内容是一个空对象
//1.处理不同类型的请求体:text、json、urlencoded、raw,对应的报文主体的格式不同。
//2.处理不同的编码:比如utf8、gbk等。
//3.处理不同的压缩类型:比如gzip、deflare等。
//4.其他边界、异常的处理
//5.主要用来解析http请求传过来的字符串,用JSON.parser转对象 或者JSON.stringify转字符串
安装: cnpm i body-parser --save-dev (或者-D)
引入: const bodyParser=require("body-parser")
//设置模块 两个需要一起使用
app.use(bodyparser.urlencoded({ extended:false,limit:"500mb" }))
app.use(bodyParser.json()) //主要是可以支持JSON格式
//limit为post请求传输的文件大小限制
//extended为false时,解析的对象格式为: str[name]:'名字' 为true解析为: str:{name:'名字'}
两种殷勤模板
//art-template 安装和引入 art-template
1.把数据和页面结合
2.使用res.end() 返回处理的内容给 客户端
//ejs 安装ejs
1.设置引擎模板的类型和模板的位置
2.使用res.render() 返回数据
安装: cnpm i art-template ejs --save-dev (或者-D)
引入: const tem=require("art-template")
引入: const ejs=require("ejs")
//把后台数据输出到html页面 html 语法 ( 后台数据要是一个对象 )
页面引入: {{name}} //出现在任何地方,会直接拿到后台对象内的内容
后台语法: var ret = tem.render(地址,对象) //地址就是html页面的内容 对象就是一个对象
//步骤一: 通过fs.readFile()读取html页面, 然后 toString() 转字符串,再输出到页面
//步骤二: get请求放问一个端口,tem(读取的地址,对象) 再res.end()返回到页面 //需要path模块
语法: const html=tem(path.join(__dirname,'./index.html'),{})
res.end(html)
//把后台输出输出到html页面 ejs 语法 ( 后台数据要是一个对象 )
页面引入: <%=name%> //可以为变量或者表达式 a+b
//后台语法:ejs.renderFile('./index.ejs',{},(err,data)=>{ res.end(data) })
app.set('engine view','ejs') //设置引擎模板类型 engine view固定写法
app.set('views',地址) //设置引擎模板的路径 到文件夹就行,或者index.ejs
res.render('地址',对象) //地址是设置的路径,index.ejs
路由就是一个管理工具,,用来管理某个路径
//引入: 引入express模块
//创建一个路由对象
const router = express.Router() //里面加对象可添加审核要求
{caseSensitive:false,strict:true} //开启严格模式并严格区分大小写
//挂载在路由上
router.get("/index.html",(req,res,next)=>{
console.log(request.params.id) //params跟query差不多, params可以获取纯数字
response.end("恭喜")
})
//暴露路由
module.exports=router //这样在服务端页面就直接引入,就可以使用了
网址: http://www.expressjs.com.cn/
安装: npm install express-generator -g //这是全局安装,只需要安装一次就够了
//1.安装好生成器
//2.在目录下生成项目文件夹 express 项目名
//3.cnpm i 根据package.json配置文件,安装所需要的包
//4.实现自动刷新,把package.json里面的start的node改为nodemon 要安装nodemon
//1.安装: npm install apidoc -g 全局安装
//2.访问页面: http://apidocjs.com/#install 查看详细使用
//3.在项目根目录新建 apidoc.json
//4.在需要生成接口文档的接口上面注释 也就是打开网址最开头的一段/* */
//5.运行命名生成文档 apidoc -i ./routes -o ./apidoc -t mytemplate
-i 以哪个文件夹生成 -o 生成到哪个文件
当前端端口为8080,后端的为8888的时候,就产生了跨域
//解决办法1: JSONP 但只支持get请求
//解决办法2: cors
安装: cnpm i cors -save-dev( -D )
引入: const cors=require("cors")
设置: app.use(cors()) //就解决跨域问题了
//提示: 后端设置的端口为8080,但是前端ajax访问的端口为8888,设置了后就能访问了
介绍: 简洁、直观、强悍的前端开发框架,让web开发更迅速、简单。
安装: cnpm add bootstrap@3.3.7 -D
引入: 用css的link引入 路径: ./node_modules/bootstrap/dist/css/bootstrap.min.css
使用:跟普通的class差不多,引用库是class名字,实现指定的效果
Vue是一款前端框架,构建用户界面的框架,为了提高开发效率,语法类似SSR服务渲染
//1.引入Vue库,下载Vue,然后通过 2.5版本
基础语法: const vm=new Vue({ //Vue的基础语法操作,里面来存储数据
el:"#app", //指定我们的存放标签区域,,这里是id
data:{ //定义model普通数据的存放( 属性 )
msg:"这是第一段数据", //普通数据
msg1:"这是第二段数据", //普通数据
msg2:"这是第三段数据", //普通数据
arr: [1, 2, 3, 4], //数组
arrObj: [{ id: 0}, { id: 1}, { id: 2}], //数组里放对象
obj: { id: 0, id: 1, id: 2, id: 3 }, //对象
},
created(){ }, //自执行内容区,组件实例化完毕,但页面还未显示
beforeMount(){} //在页面渲染之前执行,虚拟DOM已经生产
mounted(){} //在页面渲染完毕之前执行,执行完,页面显示
beforeUpdate(){} //组件更新前,页面仍未更新,虚拟DOM已经完成
methods:{ //定义事件数据的存放,也就是触发的函数,只针对事件
show(){
console.log('这是第一个函数')
},
}
updated(){} //组件更新,此方法执行后,页面显示
destroyed(){} //组件销毁
})
//html页面引用Vue功能
<div id='app'> //设置id,来获取指定的Vue数据存放库
{{msg}} //正常获取普通数据的存放语法,可以出现在任何标签地方
<p v-text='msg1'>第1段<p> //获取某个普通数据,纯文本获取,不会解析html
<p v-html='msg2'>第2段<p> //获取某个普通数据,会解析html
<p v-bind:title="msg">第3段<p> //设置一个标签里面的属性和值,获取指定Vue里面的内容
:title="{msg:true}" //设置属性内容的简写 还可判断是否使用
<button v-on:click="show">点击<button> //设置一个按钮,点击后触发Vue里面的函数
@click="show()" //事件绑定的简写,可以传参数
<input v-model="msg" type="text"> //只针对表单,改变里的内容,Vue里面指定的msg也会改变
<p :key='el.id'> //key可以是唯一的字符串或者数字,绑定固定不变元素,id
//循环遍历
<p v-for="(el,index) in arr"><p> //遍历数组 el对应值,index对应下标,arr对应Vue里面的数组
<p v-for="(el,index) in arrObj"><p> //遍历数组的对象,同上,可以用el.id拿到内容
<p v-for="(el,index,key) in obj"><p> //遍历对象,el为值,index为下标,key为键
//显示和隐藏
<div v-if="score>=90">优秀<div> //判断Vue里面的score的数来显示标签,不合格会隐藏标签
<div v-else-if="score>=80">合格<div> //跟if判断一样,这里是else后再-if判断
<div v-else>你个垃圾<div> //最后剩下的另一个结果
<p v-show>="90">显示/隐藏<p> //根据判断条件来决定显示和隐藏
//if和show的区别 if是隐藏是完全删除数据 show是不显示( 频繁操作的时候使用show更好 )
</div>
//1.给一个标签设置多个class名
<p :class="{ 'aa':true, 'bb':false }"><p> //用对象设置aa和bb两个class名是否使用
//2. 控制是否启动某个样式名 后面是Vue里面的data里的值
<p :class="classObject"><p> classObject:{ box: true } //true为使用这个样式名
//3. 数组语法控制多个class名字 后面是Vue里面的data里的值
<p :class="[ aa, bb ]"><p> aa: 'active' //直接控制aa或bb等于某个样式名
//4. 内联样式用对象设置多个属性 后面是Vue里面的data里的值
<p :style="{ color:aa, font-size:bb+'px' }"><p> //aa:red bb:20 //直接控制值
//5. 内联样式直接绑定对象 后面是Vue里面的data里的值
<p :class="class"><p> class:{ color:'red',fontSize:'20px' } //直接下面取值
//6. 内联样式,用数组绑定多个对象 后面是Vue里面的data里的值
<p :class="[aa,bb]"><p> aa:{color:'red'},bb:{fontSize:'20px'} //一次使用两个样式对象
Vue的ajax请求
// axios Promise 语法的 ajax请求库 任何框架都能使用
// vue-resouce Promise vue配套的ajax请求 在vue的基础上才可以使用 ( 2.0之后不更新了 )
//1. 引入axios文件
//2. 安装axios包 yarn add axios -S
//获取端口请求 res为返回的结果
axios.get('http://127.0.0.1:5000/api/getprodlist').then((res)=>{ console.log(res) })
//vue的动画就是一个元素的开始,动画中,动画结束,利用css的过渡属性 transition结合使用
//Vue 在插入、更新或者移除 DOM 时,提供多种不同方式的应用过渡效果。
//需要有一个可切换的元素
//动画分,去的三个步骤,回来的三个步骤 去的开始和回来的结束为同一个属性
//进入: false-true 无-有
v-enter //进入过渡的开始状态
v-enter-active //进入过渡生效时的状态,包含元素,时间,动画过程( ease从慢到快 )
v-enter-to //进入过渡的结束状态( 也就是默认状态 )
//离开: true-false 有-无
v-leave //离开过渡的开始状态( 也就是默认状态 )
v-leave-active //离开过渡生效时的状态,包含元素,时间,动画过程( ease从慢到快 )
v-leave-to //离开过渡的结束状态
提示: 可以改变v,设置一个动画前缀 比如: x-enter 来绑定指定动画标签
//元素绑定: 该标签绑定一个动画前缀
提示: 给绑定添加标签,可以在变化时,执行指定的动画,不写默认为v
提示: transition默认是span标签,可以通过 tag="p"改为指定的标签
//完整语法
//动画开始位置和最后回来的结束位置 CSS样式
.v-enter,.v-leave-to{ //根据默认状态来执行,
transform: translateX(150px); //移动元素的距离 X是左右
}
.v-enter-active,.v-leave-active{ //元素变化的过程, 所有属性,0.3s 从慢到快
transition: all .3s ease;
}
//html部分
<button @click="flag=!flag">点击<button> //按钮控制显示还是隐藏
<transition name="x"> //执行动画的元素和动画名字
<div v-show="flag">显示/隐藏<div>
<transition>
//js部分
new Vue({el:'#app',data:{flag:true}})
引入: <link rel="stylesheet" href="./lib/animate.min.css"> //动画库,配合Vue
//animated是所有animated.css的基础类样式 ( 刻意不用写css )
//需要有一个可切换的元素
//百度animated.css,会提供动画命令库 这里用的fadeInRight 和 fadeOutRight
//完整语法
<button @click="flag=!flag">点击<button> //用vue控制显示和隐藏
<transition enter-active-class="fadeInRight" leave-active-class="fadeOutRight">
<div v-show="flag" class="animated">显示/隐藏<div>
<transition>
//这里的动画是 从最右边进来或者到最右边去
//半场动画 钩子函数 也就是控制一个动画的完整过程
//放在 transition标签里面 函数名可自定义,但是见名思义
v-on:before-enter="beforeEnter" //进入之前 也就是初始化位置
v-on:enter="enter" //已经进去,执行中
v-on:after-enter="afterEnter" //执行完毕
v-on:enter-cancelled="enterCancelled" //离开
//Vue里面的methods放置的函数
beforeEnter(el){ //el是动画里面的元素 div
el.style.transform="translate(0,0)" //设置初始化的位置 el就是所包含的元素
},
enter(el,done){ //进去了,根据el设置样式属性 done是为了跟执行完毕同时执行
el.offsetLeft //强制刷新,没有这个动画不执行
el.style.transform="translate(300px,300px)"
el.style.transition="all 1s ease"
done() //是执行完毕的回调函数,就是为了能跟执行中同时执行
},
afterEnter(){ //执行完毕,元素就隐藏了
this.flag=!this.flag
}
符号: | 管道符号, {{msg | datafmt}} //左边是内容,右边是过滤器名字
//创建过滤器
Vue.filter('datafmt',(data)=>{ //data就是管道符左边的内容
return data.replace('好','坏') //这里获取文字后,把msg的好进行了替换成坏
})
//管道符传参数
{{msg | datafmt('arr')}} //参数由过滤器的第二个参数接收,第一个默认是msg
//全局过滤器
Vue.filter('datafmt',(data,arr)=>{ //data就是管道符左边的内容
return data.replace('好','坏') //这里获取文字后,进行了替换
})
//私有过滤器
在Vue里面,挂载标签后,里面增加 filters(){ 过滤器名字(data,arr){ return } }
// 也就是通过遍历出现的内容,采用动画的形式 input输入框可以为arr数组添加内容
//appear默认就有动画
<transition-group appear tag="div"> //通过 tag="div"改为指定的标签
<p v-for="el in arr" :key="el.id">显示/隐藏<p>
<transition-group>
//需配合原生vue动画,在css里面写 enter,leave-to,然后为设置的数组添加新的内容
自定义指令,也就是定义一块区域,绑定一个标签,来更改这个标签的一些CSS和JS效果
创建: Vue.directive('名字',{ //自定义一个名字,比如foucs
bind(el,binding){ //el是标签本体 ,binding是一个对象,比如传过来的参数
el.style.color='red' //在bind里面适用更改css样式
},
inserted(el){}, //el就是标签本体 适用js的DOM操作
updated(){}
})
绑定: <p v-foucs="100"><p> //这里的100可以传到binding, binding.value可以查找到
调用: 在Vue渲染范围里面的任意标签 增加 v-名字 比如 v-foucs
//私有自定义指令
在Vue渲染区域里面增加 directives{ focus:{ bind(){} } } //只是开头不一样,作用域在渲染范围内
//指令的简写,默认是bind和updated方法,可直接简写,适用修改css样式
size(el,binding){ el.style.coloe='red' }
自定义组件,也就是自己设置一个自定义的html标签,把内容填在这个标签里面
自定义组件的data,是一个函数 data(){} 或者 data:()=>{{写内容}}
//定义组件 只能创建一个div根标签,里面可以放任意其他标签
const Login=Vue.extend({
template:`这是一个自定义组件` //通过字符串的方式创建一个div根标签
})
//注册组件-全局和私有 Vue.component('组件名',定义组件的返回值)
Vue.component('my-login', Login) //my-login是一个自定义的html标签名
//渲染组件 以组件名作为html标签使用, 放在Vue渲染范围内,在自定义组件标签里面
//html使用方法,放在Vue渲染的内容里面
<my-login><my-login> //这个标签里面会默认加上上面定义的div
//自定义组件的简写
const Login={ template:`这是一个自定义组件` } //1.直接定义内容,但是标签得是Login
const Login={ template: '#template' } //2.在body里面再加一个template标签,然后id绑定
<template id="template"> //id跟定义组件对应上
<div>这是一个自定义组件<div>
<template>
//私有自定义组件 也就是在外面定义, 然后再Vue区域里面注册
Vue渲染模块里面增加 components:{ 'my-login':Login }
组件的 data属性是私有的
//定义一个组件
const login={
template:'#template',
data:{
msg:'这是自定义私有',
count:1
}
}
//自定义组件的data的值跟Vue根组件不冲突
<template id="template"> //绑定id,绑定某个自定义组件
<div> //组件模板中,需要且有一个根元素div,也只能有一个
<p>{{msg}}---{{count}}<p> //这里提取的是自定义组件里面的dat的值
<div>
<template>
一, 父传子 data的传值,默认是不共享
1. 在渲染的子组件上使用 v-bind 绑定要传递的父组件的data数据
2. 在子组件中使用 props 接收传递过来的数据
//步骤一: 定义Vue根组件,里面的 components:{ 自定义组件名 } 自定义组件也就是子组件,变成私有
//创建子组件
const login={
props:['msgs'], //用props来接收父组件的值,这里只取了msg,且改了名字
props:{ msg:{ type:String } } //接收值的另一种写法,可以看到传过来的类型
template:`子组件
`
}
//子组件标签需要加上 v-bind来接收父组件传递的data数据
<login v-binf:msgs='msg'><login>
msgs 是自定义的属性拿过来使用 msg 是父组件里面的data数据
二, 子传父 data的传值,默认是不共享 也就是调用父组件的函数,然后把子组件的值传过去
1. 在渲染的子组件上使用 v-on 绑定要传递的父组件的methods,也就是启用事件函数
2. 在子组件中使用 this,$emit() 调用传递过来的函数,调用的同时传递子组件的数据
//子组件标签上加上 v-on事件绑定
<Login @getdatas="getdata"><Login> //父组件的函数要同名
提示: 右边是父组件的函数明,左边自定义,与下面调用同名
//子组件函数的调用
created(){ this.$emit('getdatas','传过去的值') } //通过调用父组件函数,把值传过去
//父组件里面定义函数,然后接收子组件传过来的值
methods:{ getdata(data){} } //data就是子组件调用传过来的值
三, 子组件之间传值 把两个子组件,挂载在同一个Vue对象上面 两个子组件依旧是父组件的私有组件
1.实例化一个新的 vue 对象
2.定义2个兄弟组件
//实例化新的Vue对象
const bus=new Vue()
//第一个子组件
const Com1={
template:`第一个子组件
`, //点击执行自己的函数
methods:{
show(){
bus.$emit('getdata','传过去的值') //调用第二个子组件的函数,把值传过去
}
}
}
//第二个子组件
const Com1={
template:`第二个子组件
`,
created(){ //通过$on 定义一个函数,让第一个子组件可以调用
bus.$on('getdata',(data)=>{}) //这里的data是第一个子组件传过来的值
}
}
也就是通过组件来控制一个元素的出现和消失,来进行Vue动画,其中给transition 标签添加 mode='out-in',代表这次动画执行完了,才进行后续的
//组件渲染
// 以组件名称作为 html元素渲染
// 使用component 渲染, 通过 is属性渲染指定的组件,当涉及到
用三个按钮,来改变父组件里面data的值
//1. 定义几个子组件,template:`` 对应不同的内容
//2. 父组件的components:{} 添加这几个子组件为私有
//3. 父组件里面的data定义一个属性 isComName='子组件名'
//4. Vue渲染标签里面增加几个按钮,分别点击事件 @click="isComNmae='子组件名'"
//5. 设置Vue动画标签 transition 里面添加component 用 :is='isComNmae' 来决定显示哪个子组件的内容
//6. transition添加 mod='out-in' 使上一次切换完了,才开始切换下一个
插槽就是: 在子组件自定义标签里面,如果没有内容,就传一个默认内容,,有内容,就会用插槽的内容
一, 匿名插槽,插槽没有名字,就对应一个
//1. 创建子组件
const Com1={
template:`默认内容 ` //slot标签就是默认内容标签
}
//2. 父组件把子组件变成私有
new Vue({ components:{ Com1 } })
//3. 子组件标签如果没有内容,就显示slot标签默认内容,有内容,就显示自己的
<Com1><Com1> //没内容 666 //有内容
二, 具明插槽,插槽存在名字,一个插槽对应被替换的标签
//1. 创建子组件,并给插槽添加名字
const Com1={
template:`
默认内容 //给两个插槽都添加名字
默认内容
`
}
//2. 子组件标签里面写内容,也同样要写名字,不然会继续显示插槽内容
<Com1>
<div slot='header'>这是头<div> //一个标签对应一个插槽标签
<div slot='footer'>这是尾<div>
<Com1>
//3. 如果不添加名字出现的特殊情况
1.插槽添加,标签不添加, 会显示插槽的内容,且排成一行
2.插槽不添加,标签添加, 会显示插槽的内容,且排成一行
3.两个都不添加, 插槽会视为一个整体, 子组件里面标签有几个,就出现几次,多次重复,内容为标签里的
4.标签添加一个插槽都不添加 ,同上,没有添加名字的标签,会根据插槽重复多次
总结: 如果出现多行标签,就需要都添加名字,不然会重复错乱
三, 作用域插槽,让插槽和标签的数据都是动态的,也就是写入的内容是动态的
//1. 创建子组件 在slot上用 v-bind的方式绑定子组件的数据
const Com1={
data:{ msg:'这是子组件' },
template:`默认内容 `
}
//2. 子组件变成私有,写在父组件里面, slot-scope接收得到的是一个对象,也就是子组件的data
<Com1><mark slot-scope="scope">{{scope.msg}}<mark><Com1>
提示://这里scope是一个对象 { msg:'子组件的数据' } 所以需要scope.msg才能拿到内容
扩展: 优化标签 <template><template> 在Vue里可以优化标签里面没有显示多余的内容,减少代码量
需要元素:
`` //Vue路由库
`` //Vue库
使用的标签
` ` 是一个组件,用于设置导航链接,to='' 为目标地址 该标签默认渲染为a标签
//1.定义组件
const Login={ template:`第一个组件` }
const Register={ template:`第二个组件` }
//2.实例化路由对象
const router=new VueRouter({
router:[
{path:'/',redirect:'/Login'}, //让页面默认渲染这个组件内容,可不写
{path:'Login',component:Login}, //链接打开的为/Login,就渲染指定的组件
{path:'Register',component:Register},
linkActiveClass:'active' //router-link标签默认带一个class名,这个可以改掉
]
})
//3.挂载在根组件
new Vue({ el:'app',router:router }) //把路由挂载在Vue里面
//Vue渲染区域部分 //使用 router-link 组件来导航 `to` 属性指定链接,
<router-link to='/Login' tag='span'>Login<router-link>
<router-link to='/Register' tag='span'>Register<router-link>
<router-view><router-view> //路由出口,路由匹配到的组件将渲染在这里
//路由在router-link标签,to路径模拟传参数
第一种,query方式
to='/Login?name=aa&age=123' //普通的get请求传参数
在Login组件里面,通过data(){ return{ name:this.$router.query.name } } 获取url的参数
然后可直接写入在 template:`{{name}}第一个组件`
第二种,params方式
to='/Register/bbb/456' //只需要写入值,名字在下面已经定义好了
需要在'实例化路由'里面把 path:'/Register/:name/:age' //每个名字对应传的值
在Register组件里面,通过data(){ return{ name:this.$router.params.name } } 获取url的参数
然后可直接写入在 template:`{{name}}第二个组件`
二, 编程式导航路由
通过点击按钮,启用一个函数,函数里面写好了路由的url路径,根据路径来判断访问的组件,获取内容
//在Vue的methods设置函数
goLogin(){ this.$router.push('/login?name=aaa&age=123') } //也可以写成params的方式
//子组件template里面直接获取内容,根据设置的函数方式来显示某一个( 这里route不需要r )
template:`{{$route.query.name}}---{{$route.params.name}}`
三,命名视图
类似具名组件,给` `标签设置名字,然后渲染对应的组件
//绑定名字
' ' //绑定一个name名字为main
//实例化路由对象里面设置名字
routers:[{
path:'/',
components:{
default:Header, //默认展示的组件名,没有设置的情况下渲染这个
main:Main //左边是绑定的name,右边是组件名,标签内只渲染这个组件
}
}]
methods:{} //里面就是普通的函数,直接调用,return返回结果
watch:{} //直接以data里面的属性作为函数名, 两个形参,一个是最新的数据,一个是上一次的数据
例子: show( newVal, oldVal ){} newVal是最新的数据 oldVal是更新之前的数据
computed:{} //直接以data的属性作为函数名,data里面可以不用写,return返回
查看有没有安装/版本号: vue-V
//安装 2.x 版本----需要 cnpm i 下载依赖包
初始化项目: vue init webpack 名字
npm install vue-cli -g
npm install @vue/cli-init
//安装 3.x版本(建议使用)
初始化项目: vue create 名字 //vue ui命令启动项目
npm install @vue/cli -g
npm install -g @vue/cli-service-global
`注意: 用 vue ui打开,选择所需组件,router等,目录`
//VScode插件
eslint //严格语法标准化
vetur //实现代码高亮
设置里面添加自动格式化代码
// #每次保存的时候将代码按eslint格式进行修复
"eslint.autoFixOnSave": true,
// 添加 vue 支持
"eslint.validate": [
"javascript",
"javascriptreact",
{
"language": "vue",
"autoFix": true
}
],
//设置vant,使用其样式
安装: 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) //可以链式多个使用
Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式。它采用集中式存储管理应用的所有组件的状态
Vuex 是一个全局存储的工具,里面的属性和方法都是公有的,可以在项目任何地方调用和设置
//逻辑步骤
Vue Components(用户) > Actions(请求) > Mutations(执行请求并返回) > State(存储结果数据)
//1.安装: 先安装vue,且创建好项目,然后安装 npm install vuex -S 或者 yarn add vuex
//2.创建vuex文件夹 store/index.js //跟路由router差不多
//3.index.js里面引入vue和vuex,且vue.use(vuex)注册
4.实例化vuex const store=new vuex.Store({
state:{}, //类似vue的data,用来存放数据
mutations:{ //类似vue的mothods,用来放执行函数,但不会直接执行,同步
SupCount(stale,obj){} //stale就是上面的,obj是下面传的参数
},
actions:{ //通知上面的函数进行执行,异步,可加入ajax
SupCount({commit},obj){ //被调用时,接收一个参数
commit('SupCount',obj) //让上面执行某个函数,且传一个参数
}
},
getters:{ //类似Vue的computed和filter的组合
getCount(state){ //同样被某个地方调用执行
return '$'+state.count //把state里面的属性进行修饰,然后返回
}
},
module:{} //管理多个state
})
//5.暴露vuex export default store
调用vuex里面数据的方式
{{ $store.state.count }} //获取state里面的某个值
{{$store.getters.getCount}} //执行getters里面的某个函数,并得到返回值
$store.dispatch('SupCount', '嘿嘿') //操作actions里面的函数,且传一个参数
$store.commit('SupCount', '哄哄') //操作mutations里面的函数,且传一个参数
可以通过执行vue的函数,然后在里面执行vuex的函数,前面需要加this
辅助函数的调用方式 //主要是简化代码
//调用属性 直接使用{{count}}
import { mapState } from 'vuex'
export default {
computed: {
...mapState(['count','name'])
}
}
//调用函数 直接使用 @click='SupCount'
import { mapActions } from 'vuex'
...mapActions(['SupCount']) //卸载vue的methods函数里面
//1.bulid进行项目打包,减少体积 npm run bulid
一, 项目添加nprogress加载进度条,也就是页面跳转,顶部的进度条
//1.安装依赖包 yarn add nprogress -S npm i nprogress -S
//2.在main.js中导入依赖包和样式
import NProgress from 'nprogress'
import 'nprogress/nprogress.css'
//3.在axios请求拦截器和响应拦截器中配置启动和结束
// axios 请求拦截
axios.interceptors.request.use(function (config) {
NProgress.start()
return config
})
// axios 响应拦截
axios.interceptors.response.use(function (response) {
NProgress.done()
return response
})
一, 自动移除console.log()打印代码
//1.安装依赖包 yarn add babel-plugin-transform-remove-console -D
或者cnpm i babel-plugin-transform-remove-console -D
//2.在.babelrc | babel.config.js 文件中配置 plugins 插件
// 生产环境移除console
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
]
}
一, 为开发模式与发布模式设置不同的打包入口
//1. 新建文件 配置开发入口文件 src/main-dev.js 和发布模式入口文件 src/main-prod.js
//2. 删除原有的main.js文件 且上面的两个文件跟里面的内容一样
//3. 新建 vue.config.js 在src项目目录下,重新设置,里面加入
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 资源,让压缩后的文件更小
//1.直接在vue.config.js发布模式 .add后面那行后面加入
config
.set('externals', {
vue: 'Vue',
'vue-router': 'VueRouter',
axios: 'axios',
nprogress: 'NProgress'
})
//2. 引入CDN的服务依赖资源 http://www.staticfile.org/,复制到public/index.html
`<%= htmlWebpackPlugin.options.isProd ? '' : 'dev - ' %>mall-vue
<% if(htmlWebpackPlugin.options.isProd){ %>
vue-ssr
<%}%>`
//3. 可能没有moment,需要额外加入,在vue.config.js的config下面加入 moment: 'moment'
//4. 在发布模式 main-prod.js 把vant禁用,不然文件还是很大
一, 首页内容定制,也是解决上面CDN出现的BUG,也就是重复出现路由调用的问题,这里来根据情况使用或者不使用
//1.在vue.config.js加入
发布模式加入
// 配置首页定制
config.plugin('html').tap(args => {
args[0].isProd = true
return args
})
开发模式加入
// 配置首页定制
config.plugin('html').tap(args => {
args[0].isProd = false
return args
})
//2.在public/index.html 替换之前的,包括tiile,这样可以避免路由报错,设置什么时候使用,什么时候不用
`<%= htmlWebpackPlugin.options.isProd ? '' : 'dev - ' %>mall-vue
<% if(htmlWebpackPlugin.options.isProd){ %>
vue-ssr
<%}%>`
一, 实现路由懒加载,也就是避免重复的加载,加载的时候设置缓存
//在APP.vue 标题的下面加入
`
`
提示,要删除原有的router-view标签,不然可能会出现两次
二, 按需求引入组件,也就是页面被访问的时候,指定的组件才会加载,不会一次性全加载
//1. 安装 yarn add @babel/plugin-syntax-dynamic-import -D
//2. 在babel.config.js 加入
plugins: [
'@babel/plugin-syntax-dynamic-import'
]
//3. 在router/index.js加入组件 路径设置为Home的路径,所有的引入都可以这么设置
const Home = () => import(/* webpackChunkName: "about" */ '../views/Home')
//1. 复制项目到桌面
git clone https://gitee.com/fj2321605193/vue-app.git
//2. 新建分支和查看分支
git checkout -b 分支名 git branch
//3. 切换分支/合并分支(最终写完了再操作)
git checkout '分支名' git merge 分支名
//4. 写入代码
//5. 提交到监听 和 查看监听状态
git add . git status
//6. 提交到本地仓库
git commit -m '这次操作的注释'
//7. 加入到码云,这步会要求填写码云的账号密码
git push -u origin 分支名
//8. 切换到主分支,合并自己的文件
//9. 拉取,同步其他人写的代码
小程序文件简介
pages --- 存放所有的页面
utils --- 存放所有的工具类
app.js --- 小程序的入口文件
app.json --- 小程序的配置文件
app.wxss --- 公共的css样式
project.config.json --- 存放一些信息
sitemap.json --- 文档说明文件
一, pages 小程序的组成部分
// page.js/必须存在,js文件 类似vue,可以用vue的写法
`onLoad/类似vue的created onReady/类似vue的mounted`
`onShow/当前页面是否激活 onHide/当前页面是否隐藏`
`onUnload/卸载完页面`
// page.wxml/必须存在,html文件 主要用组件的标签,view类似div text类似span
// page.wxss/可选,css文件
// page.json/可选/,配置window选项 也就是对应的页面,配置跟全局一样的内容属性
二, utils
三, app.json 小程序配置文件
// pages 文件路径列表,在小程序编辑器编辑,会自动生成文件
// window 默认窗口的全局样式,翻小程序文档有详细样式写法
// tabbar 小程序下面的导航栏
// networkTimeout 网络延迟
// debug 是否开启调试模式( 默认为false )
window全局样式根据小程序的框架-全局配置-window来进行配置,也可以根据全局配置,来增加一些内容
tabbar设置下面导航栏,需要配合一些小图片
app.js 小程序应用的的生命周期
onLaunch:function(){ } //小程序打开的时候就执行,只执行一次
onShow:function(){ } //前台运行,一直处于运行状态,也就是应用没被隐藏的时候
onHide:function(){ } //后台运行,切换到其他应用了,也在运行
与vue语法不一样的地方,除了下面的,其他的跟vue一样
//小程序的循环,v-for='el in arr' :key='el.id'
wx:for="{{arr}}" {{item}}---{{index}} //分别打印值和下标
wx:for-item="value" //把item或者index改成另外一个东西
wx:key="index" //绑定唯一的值
//小程序的事件绑定 bind+事件类型
bindtab="" 点击事件 bindinput="aaa" 输入框内容变化事件
提示: 事件跟vue不一样,这个可以直接写在data的外面,函数有一个默认的e参数
show(e){}
//属性绑定数据,类似vue的 v-bind
value="{{msg}}" //小程序里面不需要加前面的,直接进行设置,不是双向绑定
//获取和同步设置data的值
this.data.msg //获取值
this.setData({ msg:'ssr' }) //修改model的值且同步view的数据到页面上
//条件渲染语法
wx:if="{{true}}" wx:else //跟vue的v-if差不多
hidden="true" //跟vue的v-show差不多
//template模板 相当于定义代码片段,然后在不同的地方调用
参考小程序框架-模板 进行设置和使用 数据的定义也根据模板来
//wxs 类似script 只能使用commonjs规范, 可以来引入js文件
<view>{{foo.getData('ygy')}}<view> //调用方法,且传一个值
<wxs module="foo"> //暴露出一个函数
module.exports={
getData:function(aa){
return aa;
}
}
<wxs>
使用工具 mpvue.com
1.先安装node.js
2.全局安装vue-cli //npm install --global [email protected]
3.创建一个基于mpvue-quickstart 模板的新项目 //vue init mpvue/mpvue-quickstart +项目名
4.mpvue中配置 vant-weapp 下载资源 //git clone https://github.com/youzan/vant-weapp.git
5.把下载的资源dist目录下的所有文件复制到你项目的/static/vant/目录下 //vant要新建文件夹
6.打开 微信开发者工具中的 想起-本地设置-ES6转ES5功能
7.运行: npm run dev
8.导入项目,用微信开发工具根据路径导入
//组件新增文件 ( 微信工具默认读取的dist的文件,所以写完了需要编译 )
直接复制一个页面,比如home,整个复制,然后修改文件名,在app.json里面的pages添加上路径,然后重新编译
//在微信小程序组件页面使用 vue-vant组件
1.下载 //git clone https://github.com/youzan/vant-weapp.git
2.把下载的资源dist目录下的所有文件复制到你项目的/static/vant/目录下 //vant要新建文件夹
3.打开 微信开发者工具中的 想起-本地设置-ES6转ES5功能
4.在指定要用的页面,新建一个main.json文件,里面添加
{
"usingComponents": {
"van-button": "/static/vant/button/index",
}
}
5.在页面中正常使用vant组件内容 <van-button>测试</van-button>
//在微信小程序组件页面中使用 axios 使用方法跟vue的axios差不多
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. 全局安装vue-cli后,创建一个mpvue项目 vue init mpvue/mpvue-quickstart +项目名
2. cnpm i安装全部的node包,包括额外安装less //cnpm i less less-loader -S
3. 修改app.json文件,新文件路径和tabBar的路径信息 //tabBar写后无法进行 url跳转
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){} //VUE生命周期监听函数,options可以拿到url后面的ID
wx.setNavigationBarTitle({title: res.name}) //可以修改id页面的标题
12. 上下拉菜单思路: 设定好页面id,页数,展示个数,一个布尔值,根据布尔值判断是否继续展示更多,每上拉一次,就访问新的数据,进行一次数组合并,下拉就重置所有数据,且快速关闭刷新事件
await this.getShops() //重置数据后重新渲染
await wx.stopPullDownRefresh() //刷新了立马停止刷新,用await跟上面执行的函数绑定
// fly.js的传值代码,,,然后在main.js里面引入,再挂载到原型上
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";
// request.headers['content-type']= 'application/json';
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-teact-app是一个构建React单页面的脚手架工具,跟vue-cli差不多,创建的项目样式跟结构是分离的
//全局安装 npm install -g create-react-app
//创建项目 npx create-react-app 项目名 (需要node 10.13.0版本以上)
//运行 npm run start
//app.css和index.css分别是app的页面样式和全局的样式
//VScode安装插件,es7,会出现html提示
生命周期函数
constructor(props){super() this.state={}} //state放在里面,用props拿到标签的值
state={} //存储数据用的-----初始化流程
componentWillMout //即将渲染执行-----初始化流程
rander //渲染------------初始化流程
componentDidMount //真正的挂载渲染-----初始化流程
shouldComponentUpdate //监听state的变化------运行中
componentWillReceiveProps(nextprops){} //某个值变化时监听----运行中
//index.js的文件
// const DIV=66666 // 直接定义一个html内容,加在下面,页面会显示
ReactDOM.render(
DIV, //在上面定义一块HTML,然后这里加入
<App />, //直接显示指定的内容,但是只能存在一个,且是组件的形式引入的
document.getElementById('root')
);
提示:引入的模块加入是 <App /> 直接使用加入是 DIV
//定义组件---无状态 (直接以箭头函数定义的组件,return一个html标签出来)
const App=()=>{ //然后ReactDOM.render()里面直接使用,页面就会显示
return (<h3>这是一个无状态组件</h3>)
}
//定义组件---有状态 (以class的方式定义的组件,return一个html标签出来)
class App extends React.Component{
render(){ //然后ReactDOM.render()里面直接使用,页面就会显示
return(<h3>这是一个有状态组件</h3>)
}
}
//组件模块化,在一个新的js页面直接rcc,会自动生成一个有状态组件,然后在index.js里面引入使用
//组件模块里面再加组件模块, 一个新的页面,使用rfc生成无状态组件,然后这边组件直接用导入的命名标签使用
import rfc from './components'
<rfc title='rfc'></rfc> 标签里面直接出现组件return的内容,且传一个值给无状态组件
提示:在app.js的组件标签里面,定义一个title值传过去给组件,{this.state.rfc}的写法是变量
//有状态组件(app.js)里面再定义无状态组件----组件传值(需要接一个形参)
export default function Rfc(props) {
return (<div>这是模块的无状态组件 {props.title}</div>) //接收有状态组件传的值
}
提示: props.title 接收传的值 props.children 只接收组件的内容,不接收传的值
`传值时设置默认内容,设置默认内容后,就不需要接收app.js那边传过来的值了`
Rfc.defaultProps={title:'rfc'} //在里面设置好titile的值
//有状态组件(app.js)里面再定义有状态组件----组件传值
export default class Rcc extends Component {
`传值设置默认内容,设置默认内容后,就不需要接收app.js那边传过来的值了`
static defaultProps={title:'rcc'} //在里面设置好titile的值
render() {
return (<div>这是有状态组件---传值{this.props.title}</div>)
}
}
提示: this.props.title 接收传的值 this.props.children 只接收组件的内容,不接收传的值
提示: 如果传的值时变量,需要再app.js里面加入一个state=()=>{定义变量}
//react类型检查,无状态组件中配置prop-types第三方包进行类型检查,设置传的值必须是什么类型
安装:npm i prop-types -D
引入:import PropTypes from 'prop-types'
设置:就直接写在无状态组件模块里面
//1.无状态组件
Rfc.propTypes={
title:PropTypes.string //设置传过来的值,必须是string类型
}
提示:传值方式发生改变 <Rfc title={1}>无状态组件传值</Rfc> //变成了{}
//2.有状态组件
export default class Rcc extends Component {
static propTypes={ tiele:PropTypes.string } //跟定义传值一样
render() {
return (<div>这是有状态组件---传值{this.props.title}</div>)
}
}
提示:传值方式发生改变 <Rcc title={1}>无状态组件传值</Rcc> //变成了{}
//受控组件---就是input框的内容受state的控制
1. 正常新建一个rcc有状态组件
2. APP.js里面引入
3. div里面再加一个Input的框,里面要有value和onChange事件
<input type='text' value={this.state.value} onChange={this.handleChangeValue.bind(this)}/> //设置一个input框,加上事件绑定函数
4. 同级写上函数
handleChangeValue(e){
console.log(e.target.value) //e.target.value的一样可以拿到下面input框的值
this.setState({ //修改model的值,实现双向绑定,同步view的值,根据state变化
value:e.target.value
})
console.log(this.state.value) //这里拿到state的值,但是input需要加一个.bind(this) 主要是因为这里是普通函数,如果是箭头函数下面就不用加了
}
state={ //类似vue的data,定义一个值
value:1
}
//非受控组件---就是input框的内容不受state的控制,通过ref操作真是的DOM
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) //可以直接获取到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}) //判断是否使用这个class名字
只会渲染发生改变了的部分,不会重新渲染全部
原理: 会先生成一个虚拟的DOM,去跟页面的DOM对比,用diff算法把发生了改变的进行替换
一, 创建虚拟DOM( 在index.js里面 )
const App=React.createElement('div','null','ssr') //标签名-标签的属性-标签内容
提示:标签内容也可以是一个标签或者变量,变量也是标签
const App=<div><span>第二种写法</span></div> //jsx的写法,会被转成虚拟DOM
二, 组件布局---传值
新建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() //需要引入createRef,在顶上react,{createRef}
提示: import react,{createRef} from 'react' //这种写法同时引入里面的某个东西
8. 对input框设置事件, //this.inputRef.current.focus() 重新获得焦点
提示:传过去的值注意类型
五, 请求端口,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'
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 //使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'
// 安装: yarn add antd -S
// 在Index.js引入全局样式 import 'antd/dist/antd.css'
// 打开文档,在需要使用的组件中按需引入响应的antd组件
improt {Button} from 'antd'
//PC使用: https://ant.design/docs/react/introduce-cn
//无线使用: https://mobile.ant.design/docs/react/introduce-cn
//Layout组件 要先安装antd 这个组件会移动和PC自适应,需要把父级的宽高设为100%
//地址:https://ant.design/components/layout-cn/
//访问文档,按照步骤设置
http://lbsyun.baidu.com/index.php?title=jspopular3.0/guide/helloworld
注意,设置放地图的元素的宽和高
1. 可以打开示例DEMO来设置一些功能,逆解析是来解析定位经纬度
//安装:npm install mockjs -S
//创建一个express项目 ( 前面Nodejs有介绍 )
//引入 const mock=require('mockjs') 不能用Import
//在路由文件创建接口访问,就跟express项目的一样
router.get('/api/data',(req,res)=>{ res.send() })
注意: 在设置新的内容的时候,需要先从mock里面拿到,比如 var Random=Mock.Random