关于js和vue以及项目搭建的相关问题

前端跨域

//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)
                    }
                })

一,ES6新增

1,语法变化
1. let   const  定义一个变量
	// 两个都没有变量提升
	// let具有块级作用域{}, 也就是局部使用才有效
	// const 是一个常量, 无法被修改
2,解构赋值
, 解构对象赋值
    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
3,字符串扩展
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=`<div>${
      
      str}</div>`
4,数组的扩展
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 } })   //得到这个对象
5,对象的扩展
. 对象的简写
	语法: var obj={
    
     name,age:18 }      //键和值相等,只需要写一个,对象的拷贝( 浅拷贝↓  深拷贝:JSON转字符串再转对象 )
	obj.assign()  //对象的浅拷贝和合并( 只拷贝第一层的内容,第二层,第三层的内容两个对象共享 )
		语法: obj1 = obj.assign({
    
    }, obj)    //把obj拷贝给空元素,赋于给obj1
6,函数的扩展
, 设置默认参数
	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,默认指向外面一层
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{
    
                //通过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

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项目生成器
	//创建跟目录文件夹
	//文件夹初始 npm init   然后安装express包
	//安装: npm install express-generator -g
	//创建项目 express 名字  然后安装依赖包和运行项目

2. 安装express框架 
     第一步:  npm init -y     //初始化一个环境
     第二步:  在项目目录下安装   cnpm i express --save-dev
1,fs模块
简介: 主要用来文件的读取,写入,修改,追加,重命名,新建
引入: 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('拷贝成功')
})

2,path路径
path 模块提供用于处理文件路径和目录路径的实用工具。
引入: const path=require("path")     //系统自带模块

//路径的拼接
path.join(__dirname,'./res','/123.txt')      //__dirname是获取该目录下的文件

//获取文件扩展名
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切换淘宝镜像
	//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
		
1,自定义模块
安装: npm init -y   //初始化文件夹
设置: 文件夹内默认访问的主文件路径 package.json
暴露: module.exports={
    
    }
//自定义模块也就是自己写一个函数,进行封装,然后暴露出去,让外部可以引用
2,querystring模块
解析: 查询字符串模块,一般是对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)       转化后 '字符串'
3.mysql
安装: 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返回一个数组
})
4.sql语句
//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
5.bodyParser
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:'名字'}
6.服务渲染SSR
两种殷勤模板  
//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
7.路由router
路由就是一个管理工具,,用来管理某个路径
//引入: 引入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 //这样在服务端页面就直接引入,就可以使用了
8.Express项目生成
网址: 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
9.apidoc接口文档
//1.安装: npm install apidoc -g     全局安装
//2.访问页面: http://apidocjs.com/#install     查看详细使用
//3.在项目根目录新建 apidoc.json
//4.在需要生成接口文档的接口上面注释   也就是打开网址最开头的一段/* */
//5.运行命名生成文档  apidoc -i ./routes -o ./apidoc -t mytemplate
		-i 以哪个文件夹生成     -o 生成到哪个文件
10.跨域解决
当前端端口为8080,后端的为8888的时候,就产生了跨域
//解决办法1: JSONP  但只支持get请求
//解决办法2: cors
安装: cnpm i cors -save-dev( -D )
引入: const cors=require("cors")
设置: app.use(cors())       //就解决跨域问题了

//提示: 后端设置的端口为8080,但是前端ajax访问的端口为8888,设置了后就能访问了
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服务渲染
//1.引入Vue库,下载Vue,然后通过<script src="./lib/vue.js"></script>  2.5版本
基础语法: const vm=new Vue({
    
                  //Vue的基础语法操作,里面来存储数据
    		el:"#app",                  //指定我们的存放标签区域,,这里是id
    		data:{
    
                          //定义model普通数据的存放( 属性 )
                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(){
    
    }     //在页面渲染之前执行,虚拟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'}  //一次使用两个样式对象
1.vue的ajax
Vue的ajax请求
	// axios	Promise 语法的 ajax请求库  任何框架都能使用
	// vue-resouce 	Promise vue配套的ajax请求  在vue的基础上才可以使用 ( 2.0之后不更新了 )
//1. 引入axios文件  <script src="./axios.min.js"></script> 
//2. 安装axios包 yarn add axios -S

//获取端口请求   res为返回的结果
	axios.get('http://127.0.0.1:5000/api/getprodlist').then((res)=>{
    
     console.log(res) })
2.vue的动画
//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 来绑定指定动画标签

//元素绑定:   <transition name='x'> <transition>   该标签绑定一个动画前缀
	提示: 给绑定添加标签,可以在变化时,执行指定的动画,不写默认为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}})
3.animated动画
引入:  <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
       }
4.过滤器
符号: | 管道符号,  {
    
    {
    
    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 } }
5.列表动画
// 也就是通过遍历出现的内容,采用动画的形式  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,然后为设置的数组添加新的内容
6.自定义指令
自定义指令,也就是定义一块区域,绑定一个标签,来更改这个标签的一些CSSJS效果

创建: 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' }

7.自定义组件
自定义组件,也就是自己设置一个自定义的html标签,把内容填在这个标签里面
自定义组件的data,是一个函数 data(){
    
    } 或者 data:()=>{
    
    {
    
    写内容}}

//定义组件  只能创建一个div根标签,里面可以放任意其他标签
const Login=Vue.extend({
    
    
    template:`<div>这是一个自定义组件</div>`        //通过字符串的方式创建一个div根标签
})

//注册组件-全局和私有     Vue.component('组件名',定义组件的返回值)
Vue.component('my-login', Login)        //my-login是一个自定义的html标签名

//渲染组件    以组件名作为html标签使用, 放在Vue渲染范围内,在自定义组件标签里面

//html使用方法,放在Vue渲染的内容里面
<my-login><my-login>         //这个标签里面会默认加上上面定义的div
    
    
//自定义组件的简写
const Login={
    
     template:`<div>这是一个自定义组件</div>` }    //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>
8.组件传值
, 父传子 data的传值,默认是不共享
	1. 在渲染的子组件上使用 v-bind 绑定要传递的父组件的data数据
    2. 在子组件中使用 props 接收传递过来的数据
    
//步骤一: 定义Vue根组件,里面的 components:{ 自定义组件名 }   自定义组件也就是子组件,变成私有
    
//创建子组件
    const login={
    
    
        props:['msgs'],          //用props来接收父组件的值,这里只取了msg,且改了名字
        props:{
    
     msg:{
    
     type:String } }   //接收值的另一种写法,可以看到传过来的类型
        template:`<p>子组件</p>`
    }
    
//子组件标签需要加上 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:`<p @click='show'>第一个子组件</p>`,   //点击执行自己的函数
        methods:{
    
    
            show(){
    
    
                bus.$emit('getdata','传过去的值')      //调用第二个子组件的函数,把值传过去
            }
        }
    }
    
//第二个子组件
    const Com1={
    
    
        template:`<p>第二个子组件</p>`,
        created(){
    
              //通过$on 定义一个函数,让第一个子组件可以调用
            bus.$on('getdata',(data)=>{
    
    })    //这里的data是第一个子组件传过来的值
        }
    }
9.组件动画
也就是通过组件来控制一个元素的出现和消失,来进行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' 使上一次切换完了,才开始切换下一个
10.组件插槽
插槽就是: 在子组件自定义标签里面,如果没有内容,就传一个默认内容,,有内容,就会用插槽的内容

一, 匿名插槽,插槽没有名字,就对应一个

//1. 创建子组件
const Com1={
    
    
    template:`<div><slot>默认内容</slot></div>`      //slot标签就是默认内容标签
}

//2. 父组件把子组件变成私有
new Vue({
    
     components:{
    
     Com1 } })

//3. 子组件标签如果没有内容,就显示slot标签默认内容,有内容,就显示自己的
<Com1><Com1> //没内容    <Com1>666<Com1>  //有内容
    

, 具明插槽,插槽存在名字,一个插槽对应被替换的标签

//1. 创建子组件,并给插槽添加名字
const Com1={
    
    
    template:`<div>
		<slot name='header'>默认内容</slot>      //给两个插槽都添加名字
		<slot name='footer'>默认内容</slot>
	</div>`
}

//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:`<div><slot :msg='msg'>默认内容</slot></div>`
}

//2. 子组件变成私有,写在父组件里面, slot-scope接收得到的是一个对象,也就是子组件的data
<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>`      //Vue路由库
    `<script src="./lib/vue.js"></script>`             //Vue库
    
使用的标签
	`<router-link> `  是一个组件,用于设置导航链接,to='' 为目标地址  该标签默认渲染为a标签
//1.定义组件
	const Login={
    
     template:`<div>第一个组件</div>` }
    const Register={
    
     template:`<div>第二个组件</div>` }
    
//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:`<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路径,根据路径来判断访问的组件,获取内容

//在Vue的methods设置函数
	goLogin(){
    
     this.$router.push('/login?name=aaa&age=123') }   //也可以写成params的方式

//子组件template里面直接获取内容,根据设置的函数方式来显示某一个( 这里route不需要r )
	template:`<div>{
     
     {$route.query.name}}---{
     
     {$route.params.name}}</div>`
,命名视图

类似具名组件,`<router-link> `标签设置名字,然后渲染对应的组件

//绑定名字
	'<router-view name='main'></router-view>'      //绑定一个name名字为main

//实例化路由对象里面设置名字
	routers:[{
    
    
        path:'/',
        components:{
    
    
            default:Header,       //默认展示的组件名,没有设置的情况下渲染这个
            main:Main             //左边是绑定的name,右边是组件名,标签内只渲染这个组件
        }
    }]
12Vue中的三个属性
methods:{
    
    }      //里面就是普通的函数,直接调用,return返回结果
watch:{
    
    }    //直接以data里面的属性作为函数名, 两个形参,一个是最新的数据,一个是上一次的数据
		例子: show( newVal, oldVal ){
    
    }   newVal是最新的数据   oldVal是更新之前的数据
computed:{
    
    }  //直接以data的属性作为函数名,data里面可以不用写,return返回
13.Vue-UI
查看有没有安装/版本号:  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)		    //可以链式多个使用
14.Vuex
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
	 `<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>
  <%}%>`
	//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,这样可以避免路由报错,设置什么时候使用,什么时候不用
	  `<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>
  <%}%>`
, 实现路由懒加载,也就是避免重复的加载,加载的时候设置缓存
	//在APP.vue 标题的下面加入 
		    `<transition>
              <keep-alive>
                <router-view></router-view>
              </keep-alive>
            </transition>`
	提示,要删除原有的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.打开 微信开发者工具中的 想起-本地设置-ES6ES5功能 
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.打开 微信开发者工具中的 想起-本地设置-ES6ES5功能 
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. 一个完整的项目
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-react-app

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=<div>66666</div>  // 直接定义一个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名字
1.页面渲染模式
只会渲染发生改变了的部分,不会重新渲染全部
原理: 会先生成一个虚拟的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'

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  //使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
// 安装: 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/ 
4.百度地图
//访问文档,按照步骤设置
	http://lbsyun.baidu.com/index.php?title=jspopular3.0/guide/helloworld
	注意,设置放地图的元素的宽和高
1. 可以打开示例DEMO来设置一些功能,逆解析是来解析定位经纬度
5.mock后台模拟
//安装: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
6.Layout组件

猜你喜欢

转载自blog.csdn.net/weixin_43689726/article/details/126222799