前端:数据展示
后端:数据处理
npm管理
npm 的服务器是在国外的 国内下载很慢
淘宝镜像: npm i -g cnpm --registry=https://registry.npm.taobao.org
jquery :
1.cd 到你要下载的文件夹下
2.初始化 npm init -y
3.下载 npm install --save jquery
4.修改下载版本
4-1 在下载的时候直接指定版本 npm install --save jquery@版本号
4-2 可以在项目的package.json文件进行修改 在项目下使用 npm install 进行重新下载
与业务无关的代码块
业务:就是项目的功能
框架优缺点
简化了项目的复杂度 提高了项目的价值
缺点:你要学习一套新的语法
扩展html标签的功能
语法:
属性写在html的 开标签中 属性=“属性值 ” 多个属性用空格隔开
npm config set registry https://registry.npm.taobao.org
三大状态
等待 pending
成功 resolve-----------then()
失败 reject-------------catch()
如果我相同时执行100个异步操作怎么办?
使用promise.all()
promise是用来解决异步回调地狱问题的解决方案 他可以把难以阅读的异步代码 变成可读性更强的代码
promise.all() 把多个相同业务异步操作 包装成一个
Promise.all可以将多个Promise实例包装成一个新的Promise实例。同时,成功和失败的返回值是不同的,成功的时候返回的是一个结果数组,而失败的时候则返回最先被reject失败状态的值(不管是那个失败了一个成功都不会返回 只会返回第一个失败的内容)。
Document
接口测试工具
async 异步的意思 await就是async 与wait的简写 等待异步完成
await 必须在async中使用 不能单独使用
async包装一个函数那么这个函数就会返回换一个promise对象(async就是promise的语法糖----用简单的语法来简化之前复杂的内容)
async function fun(){ return "你好" } console.log(fun())
async包装的函数可以返回一个promise对象 所以我们可以使用then来得到结果
Document
await 就是等待异步 await就是等待一个表达式 这个表达式的结果就是promise的成功内容(awati拿到的东西就是async包装函数的promise成功返回值 await的作用就是替代.then)
function getlink(url){ return new Promise((resolve,reject)=>{ service.request({ url, method:"GET", }).then((ok)=>{ resolve(ok) }).catch((err)=>{ reject(err) }) }) } async function getlink(){ return await service.request({ url, method:"GET", }) }
async 与 await 可以理解为异步操作的终极解决方案 相比于promise来说 优势就是在处理then的时候 进行了大大的简化 可以更加清晰的来描述一段代码 因为then过多是一个很烦人的事件 并且还可以用精简的语法简化了异步回调地狱
js在设计的初期 是一个单线程的 但是在处理一些等待事件教程或者是突发情况的时候 使用异步这个操作机制
同步任务 正常的执行代码
异步任务 宏任务 (定时器) 微任务(优先级高 promise)
先执行同步代码 遇到异步操作就会把异步操作放到异步列队中 等同步执行完 在去异步列队中把所有的微任务取出来执行 最后执行宏任务
不同点:
1.模板与jsx react使用jsx来描述页面 而vue使用template模板来描述 在vue中就可以使用标签的属性(指令)来完成一些操作
2.状态管理与对象属性 状态是react中最核心的概念 state在程序中是不能直接修改的而是使用setState来更新 但是在vue中使用data属性来描述数据
3.react Native vue没有 react有一个分支叫Native这个是用react的语法来写原生app的 但是vue没有
相同点:
1.都是js框架 他们都是专注于数据层面的框架
2.都有虚拟dom
3.都是组件话
4.都有props概念
vue.js是现今最为主流的 前端 MVVM 框架 (更简单的来展示数据)
M Model 模型-----》数据
V View 视图-----》用户可以看见的界面
Vm ViewModel 视图模型-----》数据与展示相分离 视图于模型之间的桥梁 用来关联
数据驱动与组件化
1.下载vue依赖
npm install --save vue
2.编写代码
Document {{text}}
{{}} 模板语法/双大括号表达式/双大括号赋值法
{{ 表达式 }} 表达式 ---》 通过计算可以得到结果的公式
Document {{name}}
{{age+2}}
{{sex?"你好":"你坏"}}
{{arr[2]}}
{{love.userb}}
{{text}}
{{text.toUpperCase()}}
{{text.toUpperCase().substr(1,4)}}
vue 的核心就是可以使用简单简洁的模板语法来声明式的对数据进行展示。
原生js :命令式渲染 我们需要去命令我们的程序 你应该一步一步怎么走
vue框架 :声明式渲染 我们只需要告诉程序你要干什么 他就自己完成了
就是用v- 前缀的html特殊属性
在vue中 扩展html标签的功能
写在html的开标签中 并且 v-指令=“指令值” 多个指令用空格隔开
作用:控制元素的显示和隐藏
使用css的display来进行css的设置
true 显示 false 隐藏
Document v-show
看我的显示和隐藏
用于在表单元素上进行数据的双向绑定
Document v-model
{{text}}
双向绑定 是通过 数据劫持与发布者订阅者模式来实现的
双向绑定 是通过 数据劫持与发布者订阅者模式来实现的
数据劫持:数据拦截 数据阻断 就是vm层会时时刻刻的监听者模型和视图中的数据当其中一个改变了 vm层就会收到通知(vm怎么收到的通知 通过数据劫持 Object.defineProperty() 他可以拦截 所绑定的对象数据 然后通过其中是的getter和setter方法来实现 读取与修改)
发布者订阅者 就是一个一对多的关系
就是在vue中绑定事件的指令 (在vue中不能直接使用事件 必须使用v-on修饰才能使用)
Document v-on
便利data数据 并且进行页面数据展示
语法:
v-for=" (v,i) in 你要便利的数据 "
v 就是便利出来的值
i 就是便利出来的下标
Document v-for
- {{item}}------{{index}}
便利复杂数据
Document v-for
- {{item}}------{{index}}
{{v.name}} {{v.age}}
给html标签的属性绑定变量
Document
v-if 判断当前内容是否加载
指令值:true 加载 false不加载
Document v-if
看我是否显示v-show
看我是否显示v-if
相同点 : 从用户的角度都是对内容可以隐藏
不同点 :v-show 是通过css来对元素进行显示和隐藏 但是v-if 是对dom进行添加和删除
v-show 通常使用在对安全性不高的地方 它在初始化的时候对性能有影响 在频繁切换的时候对性能比较友好
v-if 用在对安全性较高的地方 对初始化的性能比较友好 在频繁切换的时候对性能比较差
v-else
必须配合v-if来使用 不能单独使用
当v-if不符合的时候 v-else的内容显示
Document v-else
请登录
欢迎您尊敬的vip
v-else-if
当其中一项成立的时候就加载那个元素显示
Document v-else-if
111111111
111111112
111111113
111111114
向网页中插入纯文本 {{}} 和v-text的作用基本相同
Document v-text
就是因为网速或者是用户的设备加载过慢 在vue还没有渲染内容的是时候页面就显示了 可能在用户的界面中出现很多{{}}然后突然间 加载出来了页面由变得正常了
解决方式
1.v-text
2.v-cloak 在vue关联处理完数据之后进行加载
Document v-text
{{text}}
把字符串标签 解析到页面中
Document v-html
{{demohtml}}
数据一次性绑定
Document v-once
{{text}}
{{text}}
{{text}}
{{text}}
{{text}}
{{text}}
watch就是用来监听data中的数据的 当监听的data数据改变了 那么watch就会自动触发
watch在初始化不会执行
语法:
写在与el data methods等同级的位置
watch:{
你要监听的数据(newval,oldval){
当监听的数据改变了你要操作的逻辑
}
}
引子
在没有计算属性的时候 如果我们需要对数据进行一些操作 那么我们可以把这些操作放到{{}}中进行处理
Document 正常展示:{{text}}
大写展示:{{text.toUpperCase()}}
大写加截取展示:{{text.toUpperCase().substr(1,4)}}
注意:
上面的写法没有问题 但是我们把大量的逻辑放到了{{}}中会导致后期代码可读性和可维护性非常低 而且{{}}中在实际开发中主要就是用来展示数据的 并不是用来处理数据的
其实我们可以把一条数据在不同位置展示不同形态 计算属性中来完成
计算(处理数据)属性(就是vue实例中的一个属性) vue实例中可以计算数据处理数据的一个属性 计算属性他是依赖data数据的 当依赖的数据改变了 计算属性会重新计算这个数据并且返回计算之后的新结果
语法:
写在与 el data methods watch等同级位置
computed:{
你计算之后返回结果的变量(){
必须有return 你处理数据的逻辑
}
}
Document 正常展示:{{text}}
大写展示:{{text.toUpperCase()}}
大写加截取展示:{{text.toUpperCase().substr(1,4)}}
计算属性来处理上面的业务
正常展示:{{text}}
大写展示:{{uppertext}}
大写加截取展示:{{upperstrtext}}
计算属性是基于依赖缓存的 也就是说 计算属性处理数据只会处理一次 如果你多次调用的话 那么她只会给你返回第一次处理之后存储在内存中的内容
方法 只要被调用那么就执行
计算属性依赖缓存相对于方法来说更加节省资源性能
计算属性:在computed中 他是把data的数据变成自己依赖的数据 当这个数据改变了计算属性会重新计算这个依赖的数据并且返回处理之后的结果
watch:在watch中 他是监听一个data的数据 当这个数据改变了 他会完成一些业务操作
谁触发了这个事件 事件对象就指向谁
$event 事件对象
Document
就是帮助我们可以更简单的在事件实现的过程中处理一些基本的操作
语法:
@事件.修饰符=“函数()”
可以对键盘事件进行简化
.up .down .ctrl .enter .space等等
Document
阻止事件默认行为 : .prevent
阻止冒泡: .stop
事件捕获: .captrue
事件只触发一次: .once
Document
钩子函数
在特定情况下被自定钩起的函数(自动调用的函数)
vue的生命周期
vue实例从创建到销毁的过程
生命周期的钩子函数
vue实例从创建到销毁的过程中被自动调用的函数
生命周期的钩子函数:
1.实例创建前后
实例创建之前: beforeCreate 数据观测和初始化并没有开始
实例创建之后: created 完成了数据的观测 属性方法等内容都开始初始化 但是这个时候视图层还没有开始渲染
2.模板渲染前后
模板渲染之前: beforeMount 模板开始准备被渲染 但是还没有渲染
模板渲染之后: mounted el已经被vue实例挂在并且页面的dom也进行了渲染
3.数据更新前后
数据更新之前: beforeUpdate 在数据更新之前被调用 这个时候是准备开始更新
数据更新之后: updated 数据更新之后调用并且页面重新渲染展示修改之后的内容
4.实例销毁前后
实例销毁之前:beforeDestroy
实例销毁之后:destoryed
vue首次加载的时候之前前两组4个钩子
在vue中过滤器使用 filter来表示
在不改变原始数据的情况下 格式化(按照我们的需要)展示内容
过滤器本应该分为自定义过滤器和内置过滤器 但是在vue2.x之后取消了内置过滤器 内置过滤器只停留在1.x之中
Document 全局和局部的改变
11111{{text}} 22222{{text}}
全局过滤器在任意位置都可以使用
语法:
定义在vue实例之前
Vue.filter("当前过滤器的名字",(你要过滤的数据)=>{
必须return 你过滤这个数据的逻辑
})
定义过滤器
Document 全局过滤器
{{num}}
{{num}}
使用过滤器
{{变量| 过滤器的名字 }}
{{num|xiaoming}}
{{num|xiaoming}}
只能在创建过滤器的这个实例中进行使用
语法:
写在指定实例的el methods watch 等同级位置 使用 filters来进行定义
filters:{
过滤器的名字(你要过滤器的数据){
必须return 你过滤的逻辑
}
}
Document 局部的过滤器
{{num}}{{num|xiaoming}}
在vue中 脚手架使用的是 vue-cli这个技术
脚手架 就是一个今后所写项目的一个基本的空框架 这个空框架中包含了 与项目业务无关的空框框
创建:
前期准备:电脑上必须药有node 建议页安装好淘宝镜像
1.全局安装 npm install -g @vue/cli
2.查看安装之后的脚手架版本 vue --version
3.把cmd cd到你要创建项目的路径下
4.创建项目 vue create 项目名
5 把路径cd到你创建的项目下
6.启动项目 npm run serve
在一个.vue文件中有三个部分
1.template html部分写在template中
2.script 就是用来写js相关的代码 data methods watch computed等等
3.style 就是用来编写组件的样式
1.点开src文件夹 找到components文件夹 删除其中的helloword.vue
2.在components文件夹中创建一个属于我们自己的.vue文件 在其中把template script style补齐
你好我是第一个vue文件1
你好我是第一个vue文件2
你好我是第一个vue文件3
你好我是第一个vue文件4
你好我是第一个vue文件5
3.到app.vue(所有组件的老大 不能删)中修改 原有的配置
4.在app.vue中删除图片与默认样式
1.在vue项目的根路径下根路径下根路径下根路径下根路径下根路径下根路径下 创建一个vue.config.js
2.在其中编写
module.exports={ devServer:{ open:true } }
3.重启项目
把页面中多次重现 或者是 可以复用的内容 封装起来 在复用的时候只需要重读调用 二部需要重写的一个技术叫做组件
组件就是用来提高代码的复用性 减少代码量 提高开发速度 降低后期维护难度
组件的本质是 自定义标签
可以在任何地方都是用
1.在main.js中引用调用
import Vue from 'vue' import App from './App.vue' // 1.引用组件 import Demo from "./components/demo.vue" // 2.调用 // Vue.component("组件名",引用的组件) Vue.component("Demo",Demo) Vue.config.productionTip = false new Vue({ render: h => h(App), }).$mount('#app')
2.在想使用的地方直接使用
我是测试全局组件的
注意 全局组件会污染项目 所以使用的时候请注意
只能在局部进行使用的组件
创建
1.需要在components文件家中创建一个.vue文件 并写入内容
2.使用组件
(1) 引用 import 首字母大写 from "引用文件的路径"
(2)调用 需要与data methods watch 等同级位置 使用components来进行表示
语法:
components:{
给引用的组件起个名字: 你要用的组件
}
(3)使用 把组件当做标签在template中进行使用
在vue的组件中 如果你要有多行标签那么必须把这多行标签 使用一个父组件包裹(就是在template中只能有一个根节点)
我是测试组件中有多个标签的例子我是测试组件中有多个标签的例子
scoped 当前样式仅对当前组件生效
key 是在vue使用v-for的时候添加的一个属性 它的作用就是给遍历出来的内容添加一个唯一标识 因为有了这个唯一的名字之后 vue在处理这些新遍历出来的数据 效率更高
测试本地模式学习的属性---{{text}}
- {{v}}
1.data属性 语法有区别
data(){ return { text:"我是字符串", num:18 } }
剩下的所有属性写法一模一样
2.methods属性
3.watch属性
4.computed属性
5.8个生命周期钩子
6.filters过滤器
7.components属性
组件与组件之间有嵌套关系
就是按照组件使用的语法在一个组件中调用另外一个组件
我在父组件中创建一个变量 在子组件中呢直接使用吗?
不能直接用
我在子组件中创建一个变量 在父组件中呢直接使用吗?
不能直接用
组件是一个完整的独立的个体 数据与数据之间不能直接相互使用 父子不行 子父不行 爷孙更不行
父组件把数据给子组件
使用props来实现正向传值 props 就是组件中的一个开口 可以让数据在父子之间正向传递
语法:
写在与data merhods watch 等同级位置
props:[ "接收数据的变量1",“接收数据的变量2”,.........n ]
使用:
子组件定义接收参数
ziziz
父组件开始传递
props验证
就是在正向传值的时候对父组件传递过来的数据进行数据类型 默认值等 数据的格式效验
props验证不会影响页面的显示(哪怕验证的是错误的都不会影响页面显示 )但是会在控制台给我们开发者一个警告的错误提示
props验证上线后需要移除
语法:
props:{
接收参数:数据类型,
//如果我想验证接收参数可以是多个类型怎么办?
接收参数:[数据类型1,数据类型2]
//默认值呢?
接收参数:{
default:"你的默认值"
}
}
props:{ text:String, // num:Number // num:[String,Number] num:{ default:"我是num的默认值", type:String//设置了默认值之后设置数据类型校验的写法 } }
子组件把数据给父组件
注意:在vue中默认情况下 逆向传值是不被允许的 如果想实现你想传值 那必须通过事件来触发
实现:
1.子组件通过事件来触发一个 vue中自定义事件($emit)的抛出
this.$emit("自定义事件的名字随便起",你要抛出的数据)
zizizizzizizizi
2.接收 在子组件被调用的位置 使用@xiaoming="父组件的函数但是不加()不加()" 加()就会自动调用所以不加
fuffufufufufufu
ref的方式
把ref绑定到组件之上就可以获取到子组件的数据
平级组件之间传递数据
中央事件总线 ---- eventBus
中央事件总线 其实就是凌驾在两个需要传递数据的兄弟组件之上的一个空的vue实例
1.创建eventBus文件夹 用来存放这个中央事件总线
import Vue from "vue" export default new Vue
2.在需要传递数据的组件中 抛出 中央事件总线.$emit() 抛出一个自定义事件
zia
3.在需要数据的页面 组件中 接收 中央事件总线.$on() 监听实例上的自定义事件
zib
爷孙组件 或者 更多层级之间的数据传递
vuex就是一个vue中进行数据状态管理的工具
主要就是把项目组件中的数据 集中的管理存储 方便项目中组件与组件之间的相互访问与使用
vue是单向数据流 数据只能值父子这种关系进行相互的流动 但是兄弟组件这种关系就没有办法了
使用:
state--数据源
就是用来在vuex中存储数据的位置
state: {//存储数据的 demoatext:"我是demoa的数据", ziatext:"我是zia的数据", zibtext:"我是zib的数据" },
state 组件获取数据
this.$store.state.xxx 获取数据
{{this.$store.state.demoatext}} {{this.$store.state.ziatext}} {{this.$store.state.zibtext}}
module 模块
就是把原来写在vuex文件中的内容分门别类的 进行拆解 用模块来进行管理 方便后期维护
1.创建modules文件夹用来runaway模块
2.把原有写在一起的数据 拆分到模块中
let zib={ // 是一个模块 state: {//存储数据的 zibtext:"我是zib的数据" }, } export default zib
3.在vuex文件中引用模块 并且注入到modules
import Vue from 'vue' import Vuex from 'vuex' import demoa from "./modules/demoa.js" import zia from "./modules/zia.js" import zib from "./modules/zib.js" Vue.use(Vuex) export default new Vuex.Store({ state: {//存储数据的 }, mutations: { }, actions: { }, modules: { //模块 demoa, zia, zib } })
页面取值
{{this.$store.state.demoa.demoatext}} {{this.$store.state.zia.ziatext}}
mutations 修改
mutations就是在vuex中进行数据的修改的 mutations中是很多个函数 每一个函数就是一个修改的任务
1.修改数据 在组件中使用commit() 来触发vuex的mutations修改动作 (commit触发mutations修改state)
fun(){ // 触发vuex的修改任务 // this.$store.commit("mutations的任务名") this.$store.commit("setdemoa") }
2.新建mutations
mutations中是一个个的函数 函数的名字就是任务名 注意使用mutations的时候名字不能重复
mutations:{//修改state的数据 // state 就是上面的state数据源 setdemoa(state){ state.demoatext="哈哈我变了!!!!" } }
payload 载荷
payload就是一个可以接收commit传递数据的一个形参
1.在使用commit的时候 除了第一个参数是调用的名字之外 可以传递第二个参数
// this.$store.commit("mutations的任务名",你传递给mutations的数据) this.$store.commit("setdemoa","哈哈")
2.在mutations中接收的时候 就可以使用payload这个形参来接收传递进来的数据
// 接收第二个形参 payload setdemoa(state,payload){ state.demoatext=payload }
vuex数据修改刷新丢失
在需要解决的组件中
使用事件监听器监听beforeunload页面关闭事件 在其中使用本地存储本store的数据转成字符串存起来
然后在页面重新加载之后判断本地存储中有没有之前存的那个数据 如果有 就把数据取出来替换store中的state数据源
created(){ window.addEventListener("beforeunload", () => { localStorage.setItem("stateInfo", JSON.stringify(this.$store.state)); }); if (localStorage.getItem("stateInfo")) { this.$store.replaceState( Object.assign( {}, this.$store.state, JSON.parse(localStorage.getItem("stateInfo")) ) ); } },
actions 异步操作
在vuex中如果想进行异步数据请求那么就在actions中进行发送
1.在指定模块中 编写actions 并且actions中是一个个的函数 每个函数就是一个异步操作
actions:{//进行异步操作的 demolink(){ // 把请求放在这里 getlink("http://api.artgoer.cn:8084/artgoer/api/v1/user/324380/v3/topic/topicHomeByLabel?pageIndex=1&token=b544cd63-6d42-46fe-a96c-3cf96bae3113&topicId=62187").then((ok)=>{ console.log(ok); }) } }
2.在组件中通过dispatch()来调用actions中异步操作
funb(){ // 调用actions // this.$store.dispatch("你要调用actions的名字") this.$store.dispatch("demolink") },
请求来的数据怎么赋值给state
1.在actions中 是一些异步操作 我们需要把异步请求过来的数据 交给muttaions 才能修改state
actions:{//进行异步操作的 demolink(context){ // 把请求放在这里 getlink("http://api.artgoer.cn:8084/artgoer/api/v1/user/324380/v3/topic/topicHomeByLabel?pageIndex=1&token=b544cd63-6d42-46fe-a96c-3cf96bae3113&topicId=62187").then((ok)=>{ console.log(ok.data.data.commentList); // 我们需要把请求过来的数据交给mutations // context.commit("mutations的名字",你要传递的数据) context.commit("setarr",ok.data.data.commentList) }) } }
2.新建mutations 并且新建对应的state数据
setarr(state,payload){ // 把actions传递过来的数据修改state state.arr=payload }
在组件中通过this.$store.dispatch(“你要调用的actions的名字”)触发actions进行异步操作 在actions中通过数据请求把数据请求过来 然后通过context.commit() 调用mutations 修改state的数据
getters
是vuex中5大属性的其中之一 gettes 就是vuex中的计算属性
getters与vue的计算属性的区别
相同点 都是对数据进行计算并且返回处理好的结果方便页面展示
不同点: 计算属性处理的数据只能在当前组件内部使用 vuex的getters 他处理好的数据由于在vuex中 所以可以在任何组件中使用
语法:
写在与 state mutations 等同级的位置 getters里面对应的是一个个的函数 每个函数就是一个处理数据的操作 但是必须return
getters:{//vuex的计算属性 upnum(state){ return state.num.toUpperCase() } }
在组件中 可以 直接使用getters处理好的数据 this.$store.getters.xxx
{{this.$store.getters.upnum}}
原生ajax与jquery的方式实现
vue-resource 是vue官方出品 vue2.0之后官方停止维护了
axios
axios是一个第三方的数据请求 可以在vuer中使用 也可以在原生js中使用 也可以在今后学习的react等知识点中使用
axios 就是基于XHR对象 使用promise进行异步封装的一个扩展 的写法(让他更符合当下的语法要求)
axios.get()
axios.post()
axios({ })
使用:
1.下载 npm install --save axios
2.引用
3.使用
mounted(){ axios({ url:"http://api.artgoer.cn:8084/artgoer/api/v1/user/324380/v3/topic/topicHomeByLabel?pageIndex=1&token=b544cd63-6d42-46fe-a96c-3cf96bae3113&topicId=62187", method:"get" }).then((ok)=>{ console.log(ok) }).catch((err)=>{ console.log(err); }) }
使用
1.下载axios
2.新建util文件夹 工具文件夹
3.新建api文件夹 用来封装数据请求的文件夹
4.在util中新建拦截器文件
import axios from "axios" // 创建axios 赋值给常量service const service = axios.create(); // 添加请求拦截器(Interceptors) service.interceptors.request.use(function (config) { // 发送请求之前做写什么 return config; }, function (error) { // 请求错误的时候做些什么 return Promise.reject(error); }); // 添加响应拦截器 service.interceptors.response.use(function (response) { // 对响应数据做点什么 return response; }, function (error) { // 对响应错误做点什么 return Promise.reject(error); }); export default service
5.封装数据请求
import service from "@/util/service.js" // 用来封装数据请求的文件 let getlink=(url)=>{ // 当我调用这个函数的时候需要让他返回一个promise对象(因为我们使用promise对象来封装我们的异步请求让他的可读性更高并且更符合当下语法主流) return new Promise((resolve,reject)=>{ // 来写你的异步操作 service.request({ url, method:"GET" }).then((ok)=>{ resolve(ok) }).catch((err)=>{ reject(err) }) }) } export default getlink
6 在需要使用的组件内 调用api的请求 进行数据请求
getlink("http://api.artgoer.cn:8084/artgoer/api/v1/user/324380/v3/topic/topicHomeByLabel?pageIndex=1&token=b544cd63-6d42-46fe-a96c-3cf96bae3113&topicId=62187").then((ok)=>{ console.log(ok) }).catch((err)=>{ console.log(err) })
因为浏览器的安全机制 同源策略引起的 同端口 同域名 同协议
如果数据请求出现如下错误 表示跨域了
localhost/:1 Access to XMLHttpRequest at 'http://www.weather.com.cn/data/cityinfo/101320101.html' from origin 'http://localhost:8080' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.
使用代理跨域即可解决
我们日常发送数据请求是通过浏览器进行发送的
代理跨域
1.在项目的根路径下 新建vue.config.js
2.编写如下内容
module.exports={ devServer:{ open:true, // 设置跨域 proxy:{ "/api":{ // target:"设置你要帮助跨域的地址" target:"http://www.weather.com.cn/", changeOrigin:true, ws:true, pathRewrite:{ "^/api":"" } } } } }
3.在组件的请求中 设置/api
getlink("/api/data/cityinfo/101320101.html").then((ok)=>{ console.log(ok) }).catch((err)=>{ console.log(err); })
1.下载 npm install --save mockjs 没有点
2.新建文件夹 mock 用来存放模拟数据相关代码 并且在其中新建data文件夹用来存放模拟数据的json文件 在新建index.js来编写代码
let Mock=require("mockjs") // Mock.mock("模拟请求地址","请求方式",require("json模拟数据地址")) Mock.mock("/mock/data/movielist","get",require("./data/moviedata.json"))
3.需要在全局配置文件中添加mock的引用
import Vue from 'vue' import App from './App.vue' // 因为在es6中 如果只指向了文件夹 那么他会自己去找文件夹下的index.js require("./mock") Vue.config.productionTip = false new Vue({ render: h => h(App), }).$mount('#app')
4.重启项目
params来进行数据的发送 params:{ 发送数据的key:发送数据的val}
import service from "@/util/service.js" export function getlink(url,params){ return new Promise((resolve,reject)=>{ service.request({ url, method:"GET", // 发送get数据使用params来发送 params }).then((ok)=>{ resolve(ok) }).catch((err)=>{ reject(err) }) }) }
基本的封装上与get相同
post发送数据 使用data
import service from "@/util/service.js" export function postlink(url,data){ return new Promise((resolve,reject)=>{ service.request({ url, method:"POST", // post发送数据使用data data }).then((ok)=>{ resolve(ok) }).catch((err)=>{ reject(err) }) }) }
在前端页面使用的时候需要帮助axios解析
fun(){ // 因为axios不知道怎么去解析post发送数据 所以我们需要帮助 // axios来解析post let usp = new URLSearchParams() // usp.append(后台要的key,val) usp.append("uname",this.inputa) usp.append("upwd",this.inputb) postlink("/api/user/denglu",usp).then((ok)=>{ console.log(ok); }) }
引子
组件的本质 --- 自定义标签
组件在调用的时候 可以使用单标签或者双标签 (双标签的情况我们能不能在组件调用的标签中插入内容?)
如果我们默认情况下硬要插入内容 没有用 什么都不显示
槽口是一种组件的复用技巧
props 正向传值 在复用组件的时候 复用的内容不同 但是数量相同
slot槽口 在复用组件的时候 复用的内容不同 但是数量也不相同相同
语法:在组件向现实插入内容的位置写上
首页
在组件被调用的时候在其中插入内容
我是插入的内容
我是插入的内容
我是插入的内容
我是插入的内容
我是插入的内容
我是插入的内容
带有名字的槽口
在插入的时候 给插入的内容添加一个slot=“你要插入的槽口名”
我是插入的内容1
我是插入的内容2
我是插入的内容3
我是插入的内容4
我是插入的内容5
我是插入的内容6
后面会讲
使用
1.给你要操作的dom元素起个名字(ref="名字")
2.找到他 this.$refs.xxx
ref的使用
设置我的颜色
如果我们把ref绑定到组件之上 那么就可以得到当前组件的组件实例 得到了实例就得到了组件的所有的属性和方法
其中一点就是可以得到组件的data数据从而完成逆向传值
父组件如何直接触发子组件的方法?通过ref绑定到组件之上即可
多个组件使用同一个挂载点 并且动态切换
挂载点:
fuffufufufuf
传统的html+css+js的项目中如何完成页面之间的切换呢?
1.写多个html
2.在html里面可以使用超链接标签a 来跳转或者使用 js的方式进行跳转
js方式:
window.location.href 设置当前url 可以使用浏览器的回退按钮返回回来
window.history.replace() 替换当前页面 跳转之后就回不来了
路由就是根据url的地址不同(就是根据url的锚点路径 在加载不同的组件页面) 来动态分配不同的组件页面 从而完成单页面应用(SPA)
单页面应用 在用户切换页面的时候 没有那种白屏的效果 很丝滑
vue-router库 就是在vue中实现路由的基础依赖库
在创建项目的时候 选中router选项即可
大家会发现src中多了一个router (配置路由的) 与 views(组件页面)的文件夹
1.删除views与components里面的内容
2.配置路由i router文件夹下的index.js中进行配置
import Vue from 'vue' import VueRouter from 'vue-router' // 引用你要配置的路由组件页面 import Home from '../views/home.vue' import Shop from '../views/shop.vue' import User from '../views/user.vue' Vue.use(VueRouter) const routes = [ { path: '/',//url的匹配路径 name: 'Home',//就是给当前这个规则起个名字 component: Home //引用的显示组件页面 }, { path: '/shop', name: 'Shop', component: Shop }, { path: '/user', name: 'User', component: User }, ] const router = new VueRouter({ mode: 'history', base: process.env.BASE_URL, routes }) export default router
3.来到app.vue设置初体验点击跳转
Home |shop |user |
1.创建出vue路由所需要的相关文件夹与文件 并且编写路由页面
2.下载vue-router库 来帮助我们实现路由 npm install --save vue-router
3.引用相关依赖 并且在vue使用use方法使用vuerouter
import Vue from 'vue' import VueRouter from 'vue-router' import Home from '../views/Home.vue' Vue.use(VueRouter)
4.配置路由规则
const routes = [ { path: '/', name: 'Home', component: Home } ]
5.实例化路由对象 并且在路由对象中 设置路由模式与注入路由规则
const router = new VueRouter({ mode: 'history', base: process.env.BASE_URL, routes })
6引用路由并且在vue实例中注入路由规则
import Vue from 'vue' import App from './App.vue' // 引用路由 import router from './router' Vue.config.productionTip = false new Vue({ router,//在vue实例中注入路由规则 render: h => h(App) }).$mount('#app')
7 设置router-view的路由出口
src文件夹下的router里面的index.js文件
只要新建了路由的页面 那么必须在此文件中进行配置
import Vue from 'vue' import VueRouter from 'vue-router' // 引用你要配置的路由组件页面 import Home from '../views/home.vue' import Shop from '../views/shop.vue' import User from '../views/user.vue' // 在vue中使用vue路由功能 Vue.use(VueRouter) // 数组对象 就是用来配置路由规则的 const routes = [ { path: '/',//url的匹配路径 name: 'Home',//就是给当前这个规则起个名字 component: Home //引用的显示组件页面 }, { path: '/shop', name: 'Shop', component: Shop }, { path: '/user', name: 'User', component: User }, ] // 实例化路由对象 并且传入相关依赖参数 const router = new VueRouter({ mode: 'history', base: process.env.BASE_URL, routes }) export default router
标签的方式
使用router-link 来实现路由之间的页面切换 其中有一个to属性 用来表示跳转的页面路径
页面显示的内容
注意:
打开浏览器查看源码会发现把router-link翻译成了a标签 因为浏览器不能识别router-link标签所以被编译成了a标签
虽然vue在编译的时候会把router-link解析成a标签 但是 我们不能在写跳转的时候使用a标签
动态样式类
router-link会在切换的选中时候动态的 添加一个router-link-active的类名 方便我们设置路由导航的选中效果
js的方式
this.$router.push( "/你要去那里") 跳转页面
this.$router.replace("/替换的路径") 替换页面
this.$router.go(正数前进 负数回退)
fun(){ // 编程式导航 this.$router.push("/user") }
就是用来设置 路由页面的显示位置 使用router-view来进行表示 路由出口必须有
一个路由中嵌套另外一个路由页面
使用 children 进行多级路由的配置
实现:
1.先完成二级路由的路由页面
2.在router文件夹下的index.js中配置规则
2-1先引用
2-2 配置路由规则(二级路由路由规则是配置到 他对应的一级路由规则中进行设置)
import Vue from 'vue' import VueRouter from 'vue-router' import Home from '../views/home.vue' import Phone from '../views/phone.vue' import User from '../views/user.vue' // 引用二级路由 import Era from "@/views/er/era.vue" import Erc from "@/views/er/erc.vue" import Erd from "@/views/er/erd.vue" Vue.use(VueRouter) const routes = [ { path: '/home', name: 'Home', component: Home }, { path: '/user', name: 'User', component: User, // 设置二级路由 children:[ { path: 'era',//二级路由的path可以不带/ name: 'Era', component: Era }, { path: 'erc', name: 'Erc', component: Erc }, { path: 'erd', name: 'Erd', component: Erd }, ] }, { path: '/phone', name: 'Phone', component: Phone } ] const router = new VueRouter({ mode: 'history', base: process.env.BASE_URL, routes }) export default router
3.配置二级路由的路由出口
router-view 来进行设置
二级路由的路由出口需要写在对应一级路由页面中
4.设置路由导航
4-1 如果在配置二级路由的时候path没有带/ 那么二级路由导航的路径是 /一级路由/二级路由
era erc erd
4-2 4-1 如果在配置二级路由的时候path带/ 那么二级路由导航的路径是 /二级路由
era erc erd
重定向 :重新定位方向
{ path:"/你要重定向的路径",redirect:"/定位到那个路径上" }
// 重定向 { path:"/", redirect:"/home" }
在规则的最下面设置404
// 404页面规则必须必须必须写在最下面 { path: '*',//星号匹配所有地址 name: 'No', component: No }
vue中路由模式分为两种
因为有些时候我们需要把写好的页面 嵌入到手机原生app中 但是有些app要求路径中不能带#号
url中不带#号
history模式的页面刷新会丢失 上线之后会丢失 丢失解决的方式是 让你们的后端服务器的那个人 配置下后端的页面重定向
hash是默认模式 如果你不写路由模式默认就是他
url带#号
区别 | hash | history |
---|---|---|
url显示上 | 带# | 不带# |
页面刷新 | 正常展示 | 上线后刷新丢失 |
支持版本 | 支持低版本浏览器 | HTML5新增的内容所以不支持低版本浏览器 |
传统的html+css+js项目中如何把一个页面的数据传递到另外一个页面?
url传参
vue中 如果想把数据从一个页面传递到另外一个页面的时候 需要使用路由传参
params模式
1.在你需要传递数据的路由页面规则中 设置接收参数(谁接收 在谁的规则中进行配置 在其规则的path中添加 接收参数 /:xxx)
{ // 1.在需要接收数据的路由规则中 设置接收参数 path: '/phone/:xiaoming', name: 'Phone', component: Phone }
2.发送数据
声明式
方式1(知道就好了解):
点我把数据给phone
方式2(推荐使用):
点我传递数据
编程式
就是把上面声明式的两种写法to中的参数其一 放到this.$router.push()
3.接收数据
注意单词是 $route
{{this.$route.params.你配置的参数}}
query模式
不需要在路由规则中配置接收参数
1.发送
声明式
方式1:
点我使用query发送数据
方式2:
点我使用query发送数据
方式3:
点我使用query发送数据
编程式
2.接收
{{this.$route.query.xiaoming}}
query与params方式的区别
1.用法上:
query传参的时候可以使用path也可以使用name来进行传参 params只能用name来进行使用
query方式接收和params方式在接收的时候语法有所不同
2.url展示上
query 在传递数据的时候时候url会显示传递数据的参数与参数值
http://localhost:8080/query?xiaoming=111参数
params 只会显示传递的参数值
http://localhost:8080/phone/数据
在路由切换的过程中的一些钩子函数(路由切换的时候被自动执行的函数) 可以在vue中进行一些比如登录验证 等需求
全局前置守卫-- beforeEach()
就是在路由准备切换的时候 触发的一个钩子函数
语法:
to:你即将要进入的路由
from :你从那个路由来的
next: 执行下一步
router.beforeEach((to,from,next())=>{
})
注意需要写在 路由的配置文件里面
router.beforeEach((to,from,next)=>{ if(to.path=="/denglu"||to.path=="/zhuce"){ next() }else{ alert("您没有登录请您登录后访问vip页面!!!") next("/denglu") } // console.log(to); // console.log(from); })
全局后置守卫-- afterEach()
路由切换完毕之后触发的一个钩子函数
语法:
router.afterEach((to,from)=>{
})
就是只对配置当前钩子函数的哪一个路由生效
beforeEnter((to,from,next)=>{})
写在指定路由的配置上
只会对当前组件范围生效
进入组件前调用
beforeRouteEnter()
离开组件之前调用
beforeRouteLeave()
beforeRouteLeave(to,from,next){ console.log(to); console.log(from); if(confirm("您确定离开phone吗?")){ next() }else{ // 不跳转 next(false) } }
$router vueRouter对象 他代表的就是vue路由的实例 这个对象是一个全局对象 它包含了所有路由的关键属性 $route 路由的跳转对象 他包含的是当前页面路由对象
懒加载 是为了spa单页面应用中出现的首次加载白屏问题(第一次运行的时候会把所有的页面都加载一边浪费资源)
使用路由懒加载 让我们的程序按照我们的需要按需加载页面 免去了第一次加载时候的性能损耗
import导入方式 component: () => import('你使用的路由页面路径')
es6异步组件方式 component: (resolve) => require(['你使用的路由页面路径'], resolve),
在我们路由或者动态组件中发现不停切换不同页面的时候 页面的数据会丢失
原因是因为 当我们不停切换的时候页面的显示内容也在不听的切换 每次切换的时候 vue都会把原有的那个组件或者页面实例删除 并且创建一个新的vue组件实例
那么怎么样让页面切换的时候数据不丢失呢?
使用keep-alive来实现 就是用来保存在切换或者中的组件状态 可以防止页面dom重复渲染 减少页面在切换时候对程序造成的性能损耗 减少加载时间提升用户体验
你要保存状态的那些内容
如果想保存路由的状态
使用keep-alive包裹路由出口
如果想保存动态组件的状态
在vue2.1.0版本之后 keep-alive添加了两个属性
include 你要缓存谁
exclude 你不缓存谁
问题 如果我两属性都写了呢? exclude的优先级大于include
keep-alive在管理的内容中特定阶段内 被自动调用的函数
activated keep-alive管理的组件被使用的时候触发
deactivated keep-alive管理的组件被停止使用的时候触发
在指令不够用的时候 我们可以自己定义指令方便后期使用
语法:
写在data methods等同级位置
directives:{
自定义指令的名字:{
自定义指令的钩子函数(你要操作的dom元素){ 你的逻辑
}
}
}
bind 绑定到dom之上只执行一次
inserted 是咱们百分之99使用到的钩子 指令绑定到dom之上在页面加载之后调用
update 指令绑定到元素之上 在组件更新的时候调用
componentUpdate 指令绑定到元素之上 当前指令与及他所有的子节点更新完成后调用
unbind 当前指令和页面接触绑定的时候调用
注册 我是测试自定义指令的dom
数据改变了 但是视图并没有发生改变?
总结下 :当vue的data里面声明了数组或者是对象的时候,但是在项目运行的时候向数组和对象中添加新的属性的时候 就是属性发生改变 但是对应的视图并不会发生改变
官方: 如果定义在实例创建之后 向data属性中添加新的内容的时候 他不会触发视图的更新
{{obj.name}}-----{{obj.age}}
原理:
双向绑定 数据劫持与发布者订阅者模式 数据劫持 使用的是js中Object.defineProperty()进行数据劫持 但是vue2x 由于数据劫持使用的是Object.defineProperty() 但是这个方法有一个非常大的问题 就是他只能监听初始化的数据 如果中途添加新的属性时候 那么就不会被监听到 也就没有了双向绑定
解决
使用$set()来解决上述问题
语法:
this.$set(你要处理的数据,新增的数据的key,新增数据的val)
{{obj.name}}-----{{obj.age}}
nextTick就是等到dom更新完毕之后执行的一个钩子函数
就是在想使用指定页面dom的时候 但是使用的时机是dom还没有加载的情况下
在生命周期的钩子中的初始化部分 如果我们想在这个钩子中读取dom中的值是读取不到的。
{{text}}
但是如果我就是想在其中得到怎么办?
{{text}}
响应式 数据变视图变视图变数据变
vue数据的响应式 不是数据变了 视图立即更新 是等待一系列的数据都改变了 在同一进行视图更新
1.vue首先修改数据 是一个同步任务 这个修改操作可能有跟多个 那么这些修改操作就会在进行中依次执行 知道数据全部被修改了 但是修改的时候还没有设置dom操作
2.vue开启一个异步的执行列队 并且把当前事件循环中发生的虽有数据变化缓存起来
3.开始依次更新dom
{{num}}
如果我就想在数据改变了 获取dom的信息怎么办?nexttick来解决
{{num}}
混入就是vue的一个组件复用性的功能 如果多个页面有相同的方法存在的时候 可以把这些相同的内容提取出来 从而进行封装
全局
在全局引用之后 所有的组件都可以正常使用mixins的内容 ( 容易造成污染 )
1.在main.js中引用
2.使用Vue.mixin(调用)
3.你在组件中就可以正常使用了
import Vue from 'vue' import App from './App.vue' // 全局混入 import xiaoming from "./mixins/index.js" Vue.mixin(xiaoming) Vue.config.productionTip = false new Vue({ render: h => h(App), }).$mount('#app')
局部--mixins
1.新建文件夹 在其中封装你想复用的内容
let xiaoming={ methods:{ fun(){ console.log("你好"); } } } export default xiaoming
2.组件使用
混入的使用
1.ui框架的样式有的时候不能满足我们开发的需求 因为ur库的样式都是提前定义好的就几个 所以有的时候提供的功能是我们可以用的但是样式却不能满足我们
2.ui库也会出现一些问题 某个我们使用的ui库不兼容我们其中引用的某些第三方插件 那我们提前把这些ui库封装起来就不会影响我们的项目坍塌
使用二次封装会增加我们的代码量
二次封装就是 使用props与slot等组件的复用性功能来进行的 把组件变成一个全局组件即可
就是路由中的路由记录 就是给路由规则中设置一些变量数据
{ path: '/shop', name: 'shop', component: () => import('../views/shop.vue'), // 设置一些路由规则的数据 meta:{ title:"购物" }
在页面可以展示这些信息
this.$router.meta.xxx
this.$router.options.routes
1.新建好不同用户的路由页面
2.配置不同用户的路由规则
3.在跳转的时候需要根据不同的用户权限分配不同的路由规则从而显示不同的页面
登录
管理员登录
需要在每个路由规则中设置meta信息 然后根据this.$router.options.routes获取到全部路由的信息 并且挑选出我们先要的部分路由 根据得到的规则便利生成页面路由导航 在页面跳转的时候首先根据需要设置的不同用户权限信息的路由规则进行引用在通过
1把你引用的路由插入到vue的路由实例中 this.$router.options.routes=putouter
2添加到路由实例上 this.$router.addRoutes(putouter)
1.响应式
2.0当中 数据的响应式 是居于Object.defineProperty()方法来实现的 只会监听初始化的数据 如果在初始化(数据观测)完毕之后 再向数据中添加新的属性的时候 Object.defineProperty() 就不会监听到 就数去了响应式
3.0响应式采用了 最新的proxy来替代Object.defineProperty() proxy是惰性监听(不会在初始化监听数据 而是在数据需要用到时候才回去监听数据) proxy标准太新了 所以ie不兼容 在3.0中 专门为ie进行了适配 他会判断你的浏览器是什么 如果是ie那么久继续使用Object.defineProperty() 来实现响应式 如果不是是用proxy来完成响应式
2.实例的属性改变
2.0中 组件的属性是通过声明式的方式直接写在实例中的
3.0 改变了使用方式 变成了 compositionAPI (组合式api) 就把原有的属性写法变成了一个个的方法进行剥离式编写 也免去了new一系列的流程
3.声明响应式
3.0中 data methods等属性 都需要写在一个setup的方法中 并且return出去
setup3.0中最终要的一个启动方法 setup方法是出去beforCreate 与 Created两个钩子之间调用的函数 setup是组合式api的入口 在其中可以进行变量 方法 计算属性等内容的启动 但是不要忘了return出去
ref 来进行创建 ref需要接受一个参数作为数据的值 会返回一个响应式的对象
let text=ref("变量值")
我是一个组件---{{text}}
修改
想要修改ref创建的数据 必须在修改的时候使用.value属性来修改
想要修改ref创建的数据 必须在修改的时候使用.value属性来修改
想要修改ref创建的数据 必须在修改的时候使用.value属性来修改
想要修改ref创建的数据 必须在修改的时候使用.value属性来修改
我是一个组件---{{text}}
reactive 来创建复杂数据类型变量
{{obj.age}}
创建的数据类型是不相同的
修改的时候ref必须使用.value来进行修改 reactive直接修改
ref操作dom的话 我们在使用ref的时候需要向ref(传入null)即可操纵dom
computed 实现计算属性
正常显示--{{text}}
大写显示--{{uptext}}
{{text}}
https://blog.csdn.net/weixin_43294560/article/details/107585301
是一个UI框架(就是写页面)
有的同学去公司之后可能使用的是公司内部的框架
npm 安装 npm i element-ui -S
在main.js中写入如下内容
import ElementUI from 'element-ui'; import 'element-ui/lib/theme-chalk/index.css'; Vue.use(ElementUI);
主要就是用来构建整体项目的基本框架和轮廓 方便甲方或者是项目组内部开发讨论的一个快速构建项目图片的一个东西
工具有: 蓝湖 墨刀 慕客 等工具
Vant - Mobile UI Components built on Vue
npm run build 打包 会生成一个dist文件夹 运行其中的html文件发现报了很多的错(无法找到相关的js css文件)
需要在打包之前设置打包之后的静态资源路径 vue.config.js 设置静态资源路径
// 配置静态资源路径
publicPath:"./",
还需要把路由模式设置成hash模式