用来封装可以重复使用的js代码块
es模块化
comment 模块化
进入项目的package.json中修改 scripts项即可
npm的服务器在国外 我们国内连接可能会很慢
淘宝在这个时候他有一个服务器在国内 这个服务器会每隔10分钟自动从npm的服务器上拉取最新的所有内容
我们可以直接访淘宝在国内的这个服务器 这样一来下载的速度就会很快
使用:
打开cmd npm install -g cnpm
–registry=https://registry.npm.taobao.org
let demo=[1,2,3,4]
let [a,b,c,d]=demo
let arr=[1,[2,3,[4,[5,[6,],7]]],8,[9]] 使用解构把这些数据分别赋值给a-i 这9个变量怎么办?
let [a,[b,c,[d,[e,[f,],g]]],h,[i]] =arr
可以在本地浏览器中存储5mb的数据
分类:
1.locationStorage:永久存储 浏览器关闭不丢失 存储得数据只要是一个项目的内容都可以用
2.sessionStoreage:临时存储(会话存储)浏览器关闭数据丢失 存储的数据谁存的只能谁用
方法:
取数据使用getItem
存数据使用setitem
墨刀 墨客 。。。。n个
Vue.js是目前最流行的前端MVVM框架
是一套构建用户界面的渐进式的自底向上增量开发MVVM框架
渐进式:可以在原有大系统的上面,把一两个组件改用vue实现,也可以整个用vue全家桶开发不会做职责之外的事
自底向上增量开发:先写一个基础的页面,把基础的东西写好,再逐一去添加功能和效果,由简单到繁琐的这么一个过程。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-w4GY2s3E-1621169757677)(.\img\图片1.png)]
Vue.js的产生核心是为了解决如下三个问题
1.解决数据绑定问题。
2.Vue.js主要的目的是为了开发大型单页面应用。
3.支持组件化,也就是可以把页面封装成为若干个组件,把组件进行拼装,这样是让页面的复用性达到最高。
M: model 模型等同于数据 m层的作用就是用来管理数据
V: view 视图层 就等同于用户可以看见的内容区域
VM:viewModel 视图模型层 相当于 用户看见的视图层与模型层之间的数据通信桥梁
1.下包vue 所有的依赖全部要交由npm管理
(1)npm init -y
{2) npm install --save vue
DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Documenttitle>
<script src="node_modules/vue/dist/vue.js">script>
head>
<body>
<div id="demodiv">
<h1>{{num}}h1>
<h1>{{text}}h1>
<h1>{{arr[2]}}h1>
div>
<script>
// 3.新建vm层 视图模型层 他就是vue实例
new Vue({
el:"#demodiv",//关联视图层
data:{ //m层 模型层
text:"我是一个字符串",
num:18,
bool:true,
arr:[1111,2222,3333,4444],
obj:{
name:"xixi",
age:18
}
}
})
script>
body>
html>
命令式渲染 : 命令我们的程序去做什么,程序就会跟着你的命令去一步一步执行
声明式渲染 : 我们只需要告诉程序我们想要什么效果,其他的交给程序来做。
通过控制数据的变化来显示vue的数据驱动是视图的内容随着数据的改变而改变
{{}}中方的是表达式
什么是表达式?
通过计算可以返回结果的内容
DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Documenttitle>
<script src="node_modules/vue/dist/vue.js">script>
head>
<body>
<div id="dmeodiv">
<h1>{{}}中方的都是表达式h1>
<h1>{{text}}h1>
<h1>{{text.toUpperCase()}}h1>
<h1>{{bool}}h1>
<h1>{{bool?'你好':"你坏"}}h1>
div>
<script>
new Vue({
el:"#dmeodiv",
data:{
text:"abcdefg",
bool:false
}
})
script>
body>
html>
避免在双括号中使用复杂表达式
如何区分插值中的内容是表达式还是普通文本?
Vue.js 会通过是否带引号区分两者
就是用来扩展html标签的功能
写在html的开标签中 并且属性=“属性值” 多个属性用空格隔开
就是在vue中使用v-开头的htmnl特殊属性 作用就是扩展html的功能
写在html的开标签中 并且v-指令=“指令值” 多个指令用空格隔开
DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Documenttitle>
<script src="node_modules/vue/dist/vue.js">script>
head>
<body>
<div id="dmeodiv">
<h1>v-mode主要是用于表单上数据的双向绑定h1>
<h1>
v-model可以完成双向绑定
模型和视图
模型变了---》视图就会自动发生改变
视图变了---》模型也会自动改变
h1>
<input type="text" v-model="text"/>
<h1>{{text}}h1>
div>
<script>
new Vue({
el:"#dmeodiv",
data:{
text:"你好么么哒"
}
})
script>
body>
html>
数据劫持:当我们访问或设置对象的属性的时候,都会触发**Object.defineProperty()**函数来拦截(劫持),然后在 返回(get)或设置(set)对象的属性的值。并且当数据发生改变的时候做出反应。
发布者-订阅者模式:其定义对象间一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都将得到通知。
作用:控制切换一个元素的显示和隐藏;
v-show=表达式
根据表达式的真假,确定是否显示当前元素;
true表示显示该元素;false表示隐藏;
元素一直存在只是被动态设置了display:none;
<a v-bind:href="aherf">{{atext}}</a>
<a :href="aherf">{{atext}}</a>
作用:判断你是否加载固定的内容;
v-if=表达式;
作用:操作网页元素的纯文本内容;{{}}是他的另外一种写法;
v-text:指令;{{}}——模板插值;
区别:渲染数据比较多的时候,可能会把{{}}显示出来,俗称屏幕闪动;{{text}
屏幕闪动:
解决:
①使用v-text渲染数据;
②使用{{}}语法渲染数据,但是同时使用v-cloak指令,
1.位置
<div id="demodiv" v-cloak>
</div>
2.CSS
[v-cloak]{
display:none;
}
为了输出真正的HTML
{{}}只会输出纯文本
数据发送改变的时候,插值出内容不会更新
watch:监听data里面的数据,如果data数据改变,watch就会触发;
computed:{
需要返回的数据:function(){
return 处理操作
}
}
区别 | |
---|---|
方法 | 只要调用就会执行,浪费性能 |
计算属性 | 有缓存;使用计算属性的时候会执行一次,只要数据没有改变,多次调用的时候就会从缓存中读取;所依赖的值发生改变才触发调用函数; |
watch | 初始化的时候不会运行,只有数据被改变之后才会运行;监听的值发送该斌就会调用这个函数; |
按键修饰符:.up、.down、.enter、.space、.ctrl——语法:@click.修饰符=‘fn()’
2.0中已经废弃了内置过滤器,
Vue.filter("过滤器的名字",(要过滤的数据)=>{
return 你的逻辑
})
// 全局过滤器
Vue.filter("filt", (val) => {
return "¥" + val
})
局部过滤器:只在当前的vue实例区域中可以使用;
位置;写在当前vue的el data 的同级位置;
filters:{
过滤器的名字(要过滤的数据){
return 你的逻辑
}
}
生命周期:实例在创建到销毁的全过程。
生命周期钩子:在生命周期中被自动调用的函数。
钩子函数
页面已进入就触发beforeCreated、created、beforeMount、mounted;
下载4.0
vue-cli@4————开发环境
在cmd中
(1)全局安装脚手架:cnpm install -g @vue/cli——(只需要执行一次)
(2)查看版本:vue --version
(3)cd 到你要创建的项目文件夹下(/在vscode集成终端打开)
(4)vue create 你的项目名(不要有大写)
————(选择第三个features之后,一路回车)
(5)下载好后,cd到项目名
(6)npm run serve ——启动项目
就是以.vue结尾的文件;
template是写html的;script是写js的;style是写样式的;
删除默认项目
怎么写?——组件写在componts下,以.vue结尾;
怎么使用?——1.引用;2.调用;3.使用;
1.引用——import 起名字(Com) from 你引用文件的地址(components/com.vue);
2.调用——components:{引用组件的名字(Com),Com1,Com2,…}
3.使用——或者
坑1——template中如果有多行标签,必须有父节点包裹
坑2——想在组件中使用data模型数据怎么办???
只有data有变化:写成函数
export default{
components:{
引用组件的名字(Com),
Com1,...
},
data(){
return{
变量名:变量值,
text:"文本",
}
}
}
在说之前我先讲讲深拷贝和浅拷贝
在 javascript 里面简单数据类型的拷贝一般使用浅拷贝,复杂类型一般使用深拷贝,请看例子
var a = 0;
var b = a;
b = 1
console.log('a···' + a,'b···' + b) //a···0 b···1
可以看到我把 a 赋值给了 b ,修改了 b 的值后 a 的值没有变
var a = {
name: '张三',
age: '18'
};
var b = a;
b.name = '李四';
console.log(a.name) //李四
而在对象中我把 a 赋值给了 b ,修改了 b 的name 值后 a 的 name 值也变了
为什么基本数据类型的值没变,引用数据类型的值变了:
如果能理解深浅拷贝就可以理解 data 为什么要用函数了???
在创建或注册模板的时候传入一个 data 属性作为用来绑定的数据。但是在组件中,data必须是一个函数,因为每一个 vue 组件都是一个 vue 实例,通过 new Vue() 实例化,引用同一个对象,如果 data 直接是一个对象的话,那么一旦修改其中一个组件的数据,其他组件相同数据就会被改变,而 data 是函数的话,每个 vue 组件的 data 都因为函数有了自己的作用域,互不干扰。
组件与组件之间调用之后呈现的嵌套关系
子组件和父组件是一个完整的独立的个体 组件与组件之间数据不能直接互通
引用组件/路径时:@代表的就是src文件夹
全局样式**需要写在app.vue中(不加scoped)
v-for key的使用
正向传值:父组件把数据给子组件
props:在子组件创建用来接受父组件传递的数据
props语法: 写在需要接受父组件数据的子组件中 与data methods等属性同级
props的本质是标签的属性
props:[接受的变量1,接受的变量2]
基本使用
子组件
<template>
<div>
<!-- 使用 -->
homezi--{{title}}---{{num}}--{{sex}}
</div>
</template>
<script>
export default {
// 子组件设置好了接受
props:["title","num",'sex']
}
</script>
<style>
</style>
父组件
<template>
<div>
home
<!-- 在子组件被调用的地方 进行传递 -->
<Homezi title="我是title" num="我是num" sex="我是sex"/>
</div>
</template>
<script>
import Homezi from "./homezi.vue"
export default {
components:{
Homezi
}
}
</script>
<style>
</style>
在传统传值上 父组件给子组件任何数据类型都可以 没有任何约束 可能在今后展示上就会出现一些不可预知的错误
所以为了稳妥起见 我们在接收父组件数据的时候 给父组件传递过来的数据可以添加一个校验
验证传递过来的数据类型是否是我们想要的----props验证props验证仅仅只会在控制台抛出一个警告 不会对我们显示造成影响 他就是给我们开发者一个提示
所以在上线的时候需要把props验证删除掉 vue的.min包 是不带props验证功能的
子组件 把数据传递给父组件 默认情况下 逆向传值是不被允许的
如果硬要使用逆向传值 必须要有事件触发才可以
流程:
事件调用一个函数
抛出一个自定事件 $emit() 就是自定义事件 $emit(“自定义事件的名字随便起”,“参数”
<template>
<div>
子组件
<!-- 1.事件触发函数 -->
<button @click="fun()">点我逆向传值</button>
</div>
</template>
<script>
export default {
data(){
return {
zitext:"我是子组件的变量"
}
},
methods:{
fun(){
// 2.抛出自定义事件
this.$emit("xiaoming",this.zitext)
}
}
}
</script>
<style>
</style>
<template>
<div>
父组件
<!-- 接收自定义事件 在子组件被调用的时候
<子组件调用的时候 v-on:子组件抛出的事件=“父组件的函数不加()不加()因为加了就默认值执行了”/> -->
<Ez @xiaoming="emitfun"/>
</div>
</template>
<script>
import Ez from "./emitzi.vue"
export default {
components:{
Ez
},
methods:{
// 形参====子组件传递的数据
emitfun(val){
console.log(val)
}
}
}
</script>
<style>
</style>
思考:组件的本质是自定义标签 标签有双标签和单标签 单标签是没有显示内容只有动作的标签 双标签则不然他是可以在开关标签中放置显示内容的
组件的调用可以是<组件名/> 也可以是 <组件名>组件名>
如果向组件中默认插入内容 h1是不会显示的
<template>
<div>
slot父
<Slotzi>
<h1>你好么么哒</h1>
</Slotzi>
</div>
</template>
我就是想让h1显示怎么办?
在这个时候就需要用slot组件来进行设置 slot是什么?slot就是组件中的一个开口 有了这个开口就可以接收外部插入的标签
在需要插入内容的组件中放置slot组件
<template>
<div>
slotzi
<!-- 设置开口 -->
<slot></slot>
</div>
</template>
带有名字的slot/槽口
使用:
在定义slot的时候 使用name属性起个名字
在调用的时候使用slot属性插入对应内容
之前我们学到的所有页面在vue的项目中只能显示一个 如何让vue显示多个页面 在这个时候我们就要使用路由技术
使用标签的方式—》声明式 使用a标签 超连接标签
使用js的方式-------》编程式
window.location.href=“xxxx地址” 修改当前url为你设置的参数
window.history.replace() 替换当前的浏览器地址
go()
路由:所有的路径都经由这个模块进行重新分配(改变URL,在不重新请求页面的情况下,更新页面视图。)
根据url的不同来渲染不同的组件页面 完成 SPA(单页面应用) 的开发
小概念:
页面组件 :就是项目中的一个个页面整体 写在views文件夹下
组件: 就是页面中一个个的ui部件 写在components文件夹下
1.vue-cli的方式:
只需要在创建的时候选择 Router这一项 即可
在路由配置文件中配置路由规则
{
path: '/',//路径 和url上面的路径进行匹配
name: 'Home', //命名空间 给这个规则起个名字
component: Home //调用的组件页面
},
下载vue-router库 : npm install --save vue
新建路由页面组件
配置路由规则
//别忘了引用
const routes = [
{
path: '/',
name: 'Home',
component: Home
}
]
创建路由实例 并且把路由规则注入到路由实例中
把路由实例注入到vue实例中
设置路由出口
通过点击导航可以进行页面的跳转
1.声明式:(a标签)router-link to=“路径”;//写在展示的页面
<router-link to="/home">home</router-link>
<router-link to="/phone">phone</router-link>
如何知道当前是哪个页面??
2.编程式:
this.$router.push("/路径")
this.$router.replace() 替换
this.$router.go() 正数前进 负数回退
给用户一个错误的提示页面,用通配符*, 但是要放在路由规则的最下面,因为路由规则的优先级是谁先定义谁的优先级高
但是有了404页面之后首次进入会先进入到404
因为:默认的路径式/,
但是刚进去的时候没有/,所以匹配不到任何路径,就会进入404页面
// 404页面
{
path: '*',
name: 'No404',
component: No404
}
重新定位方向
{
path:"/",
redirect("/去哪里")
}
路由与路由之间有嵌套 通常多级路由是指 2级及以上的路由统称为多级路由
1.创建二级路由页面组件 views
2.配置二级路由的路由规则
(1)你要确定是那个一级路由的子路由 就在这个一路由的规则中进行创建
(2)创建children 并且进行引用
(3-1)路径中不加/
{
path: '/user',
name: 'User',
component: User,
// 二级路由
children:[
// 配置二级路由的规则(同一级路由)
{
// path不加/path不加/path不加/path不加/path不加/
// path不加/path不加/path不加/path不加/path不加/
// path不加/path不加/path不加/path不加/path不加/
// path不加/path不加/path不加/path不加/path不加/
path: 'era',
name: 'Era',
component: Era
},
{
path: 'erc',
name: 'Erc',
component: Erc
},
{
path: 'erd',
name: 'Erd',
component: Erd
},
]
(3-2)path路径加/
children:[
// 配置二级路由的规则(同一级路由)
{
// path加/path加/path加/path加/
// path加/path加/path加/path加/
// path加/path加/path加/path加/
// path加/path加/path加/path加/
path: '/era',
name: 'Era',
component: Era
},
{
path: '/erc',
name: 'Erc',
component: Erc
},
{
path: '/erd',
name: 'Erd',
component: Erd
},
]
(4) 设置二级路由的路由出口(1极路由在创建的时候vue脚手架会默认给我们添加 但是二级路由必须手工添加 二级路由的路由出口必须添加在它的一级路由之上)
(5)设置路由导航
(5-1)(路径不加/,那么它的路径是/一级/二级)
<router-link to="/wode/er1">我的er1</router-link>
<router-link to="/wode/er2">我的er2</router-link>
<router-link to="/wode/er3">我的er3</router-link>
(5-2) (路径加/,那么它的路径是/二级)
<!-- 设置导航:路径加/,那么它的路径是/二级 -->
<router-link to="/er1">我的er1</router-link>
<router-link to="/er2">我的er2</router-link>
<router-link to="/er3">我的er3</router-link>
hash模式url里面永远带着#号,我们在开发当中默认使用这个模式。
history模式没有#号,是个正常的url适合推广宣传。(上了服务器之后会出现 做刷新操作,会出现404错误 让你们的服务器开发的那个人给你设置一下服务器上的重定向即可)
把一个路由页面的数据传递到另外一个路由页面(有一个新闻列表页 点击其中的新闻标题 跳转到对应的新闻详情中)
实现:
(1)在路由规则中进行配置
/:xxx自己定义参数
{
path: '/all/:xiaoming',//路由传参的接收参数配置
name: 'All',
component: All
},
(2)传递参数
(2-1)声明式
<!-- 发送数据 -->
<!-- 声明式方式1 了解 -->
<router-link to="/all/我是传递给详情页得参数">点我用声明式方式1把数据给详情页</router-link>
<!-- 声明式方式2 掌握 -->
<!-- <router-link :to="{name:'你要跳转那个路径的名字',params:{你传递的key(要和路由配置一样):传递的值}}">点我用声明式方式2把数据给详情页</router-link> -->
<router-link :to="{name:'All',params:{xiaoming:'我是方式2发送的数据么么哒!!'}}">点我用声明式方式2把数据给详情页</router-link>
(2-2)编程式:需要函数触发。
fun(){
//了解
this.$router.push('/all/编程式方式1')
},
funb(){
//掌握
this.$router.push({name:'All',params:{xiaoming:'我是编程式方式2'}})
}
(3)接收参数
this. r o u t e . p a r a m s . x x x 注 意 单 词 是 route.params.xxx 注意单词是 route.params.xxx注意单词是route
query方式千万不要在路由规则中配置接受参数
query方式千万不要在路由规则中配置接受参数
query方式千万不要在路由规则中配置接受参数
query方式千万不要在路由规则中配置接受参数
query方式千万不要在路由规则中配置接受参数
使用:
(1)发送数据
声明式
<router-link to="/queryall?suibian='我是query声明式方式1'">query声明式方式1router-link>
<router-link :to="{name:'Queryall',query:{suibian:'我是query声明式方式2呵呵哒'}}">query声明式方式2router-link>
<router-link :to="{path:'/queryall',query:{suibian:'我是query声明式方式3么么哒'}}">query声明式方式3router-link>
编程式 课下自行根据ppt尝试
(2)接收数据
this. r o u t e . q u e r y . x x x x 注 意 单 词 是 route.query.xxxx 注意单词是 route.query.xxxx注意单词是route
$router是VueRouter的一个对象,router的实例对象,这个对象中是一个全局的对象,他包含了所有的路由包含了许多关键的对象和属性。举例:history对象
$route是一个跳转的路由对象,每一个路由都会有一个route对象,是一个局部的对象,可以获取对应的name,path,params,query等
当我们的项目体积越来越大的时候 首次页面加载可能会吧所有的路由页面渲染之后在进行显示 那么这个时候 就会造成首页渲染过慢 首页白屏 就需要使用路由懒加载技术来避免 懒加载按需加载(当你需要这个路由的时候他才会去加载这个路由页面)懒加载可以分割代码块,提高页面的初始加载效率。
常用的懒加载方式有两种:即使用vue异步组件懒加载 和 ES中的import
vue异步组件懒加载:
主要是使用了Promise.resolve()的异步机制,用require代替了import,实现按需加载
component:resolve=>(require([“引用的组件路径”],resolve))
ES中的import(推荐写法):
const HelloWorld = ()=>import(‘需要加载的模块地址’)
路由守卫:就是在路由跳转的时候被自动调用的一下函数 这些函数可以在我们进行路由跳转的时候多一些验证。
全局:
当一个导航触发时,全局前置守卫(在进入组件之前)按照创建顺序调用。
vue-router 提供的 router.beforeEach((to,from,next)=>{})可以方便地实现全局前置导航守卫
to:即将要进入的目标 路由对象
from: 当前导航正要离开的路由
next: 下一步执行
当一个导航触发时,全局后置钩子(在进入组件之后)调用。
vue-router 提供的 router.afterEach((to, from) => {})实现全局后置守卫
to:即将要进入的目标 路由对象
from: 当前导航正要离开的路由
路由独享:
与全局前置守卫相比路由独享守卫只是对当前路由进行单一控制参数和全局前置守卫相同
组件内:
在组件中使用beforeRouteEnter(to, from, next) {}来进行进入组建前的钩子
在项目的根路径下根路径下根路径下根路径下创建一个文件名为vue.config.js
module.exports={
devServer:{
open:true, //自动开启
port:8888//修改端口
}
}
写在vue.config.js中
module.exports={
//修改文件夹别名
configureWebpack:{
resolve:{
alias:{
// "别名":"对应的文件夹"
"c":"@/components"
}
},
devServer:{
open:true, //自动开启
port:8888//修改端口
}
}
}
1.新建util 并且创建js文件用来承载拦截器
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
2.新建api文件夹用来存放数据请求的封装
import Service from "u/service.js"
// export default 只能暴漏一个内容
// export 可以出现多次
export function getlink(url){
return new Promise((resolve,reject)=>{
Service.request({
url,
method:"GET"
}).then((ok)=>{
resolve(ok)
}).catch((err)=>{
reject(err)
})
})
}
3.在想使用的组件中进行调用
import {getlink} from "a/getapi.js"
mounted(){
getlink("xxx").then((ok)=>{
console.log(ok)
})
}
在项目开发之初 前台和后台开发者都是同时进行开发的 前台速度可能会快一些 那么在这个时候 后台没有办法第一时间给我们提供数据接口 这个时候就需要前台开发者自己先新建模拟数据先来开发 (后台会说你前台需要什么格式的数据?你就把你的模拟数据给他 让他安装你的模拟数据给你返回即可)
使用:
1.下载 npm install --save mockjs
2.新建容纳模拟数据的文件夹与文件 mock文件夹 index.js
3.在mock文件夹中创建模拟的j数据
4.在index.js中编写代码
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-unuCXphh-1621169757686)(.\img\4.png)]
5 在main.js中引用mock
require("./mock")
6.在请求中想怎么用就怎么用
多个组件使用一个挂载点 并且可以动态切换
在动态组件或者是在路由中如果我们切换路由页面或者动态组件的时候 由于每次切换都会新创建一个vue实例会导致数据的状态丢失
解决这个问题,我们可以用一个 元素将其路由出口包裹起来。在切换过程中将状态保留在内存中,防止重复渲染DOM,减少加载时间及性能消耗,提高用户体验性
使用:
包裹你要保存状态的内容
在vue 2.1.0 版本之后,keep-alive新加入了两个属性:
include(包含的组件缓存)
exclude(排除的组件不缓存,优先级大于include) 。
在keepalive的阶段内被自动调用的函数叫keepalive的钩子函数
activated 类型:func 触发时机:keep-alive所管理的组件进入的时候触发
deactivated 类型:func 触发时机:keep-alive所管理的组件离开的时候触发;
以上两个钩子函数需要写在被管理的组件中
aaaaaaaaaa
在vue中进行dom操作
可以获取DOM对象
绑定:
我是ref
获取: this.$refs.demo
因为组件是自定义标签
可以得到子组件的信息包含变量和方法
父组件如何触发子组件的方法? 使用ref绑顶到组件之上就可以获取组件的信息包含方法
和之前vue脚手架项目一样创建唯独就是在创建的时候 选择vuex这一项
vuex就是状态(数据)管理工具 就是把项目中的数据集中的放到一个数据仓库中 大大减少了组件与组件之间数据传递的复杂度
state: 在vuex中就是用来存放数据的
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
export default new Vuex.Store({
state: {
text:"我是vuex的数据text",
num:18,
arr:[111,2222,3333,444],
obj:{name:"xixi",age:18}
}
})
组件中使用数据
在想使用的组件中 直接使用 this.$store.state.xxx
about----{{this.$store.state.num}}
1.mutations就是vuex中修改数据的 他里面有多个方法 每个放法就是一个修改的动作
// 要修改数据就要使用mutations
mutations:{
// 今后的修改操作有很多 那么每一个修改的动作就是一个函数
add(){
console.log("+++++")
},
del(){
console.log("------")
}
}
2.在组件中调用vuex的修改mutations 要使用commit(“名字”)
about----{{this.$store.state.num}}
实战修改
mutations的每个放法中都会有一个形参这个形参代表的就是上面的数据源
修改操作:
mutations:{
// 今后的修改操作有很多 那么每一个修改的动作就是一个函数
// mutations的每个放法中都会有一个形参这个形参代表的就是上面的数据源
add(state){
state.num++
},
del(state){
state.num--
}
}
就是可以从外部往vuex的mutations的一个个方法中传递实参
组件页面在传递调用commit的时候需要在commit(“名字”,你要传递的数据)
about----{{this.$store.state.num}}
在vuex中需要接收 payload
mutations:{
// 今后的修改操作有很多 那么每一个修改的动作就是一个函数
// mutations的每个放法中都会有一个形参这个形参代表的就是上面的数据源
add(state,payload){
state.num+=payload
},
del(state,payload){
state.num-=payload
}
}
多个参数也可以传递一个对象
this.$store.commit(‘add’, { ‘num’: 20 } )
vuex数据刷新会丢失
created () {
//在页面加载时读取localStorage里的状态信息
if (localStorage.getItem("data") ) {
//replaceState替换数据 Object.assign合并对象
this.$store.replaceState(Object.assign({}, this.$store.state,JSON.parse(localStorage.getItem("data"))))
}
//在页面刷新时将vuex里的信息保存到localStorage里
window.addEventListener("beforeunload",()=>{
localStorage.setItem("data",JSON.stringify(this.$store.state))
})
},
actions 用来承载异步操作 用来操作异步的 每个异步操作就是一个方法
// 用来操作异步的 每个异步操作就是一个方法
actions:{
uplink(){
console.log("我是一个异步请求")
}
}
调用使用dispatch
this.$store.dispatch()
methods:{
fun(){
// this.$store.dispatch("actions的名字")
this.$store.dispatch("uplink")
}
},
实战使用:
在actions中添加异步请求(把原来写在组件中的内容放大actions中)
// 用来操作异步的 每个异步操作就是一个方法
actions:{
uplink(){
apilink("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)
})
}
}
1.在dispatch(“名字”,数据)
2.使用的时候需要用payload接受
是vuex的计算属性 一条数据在不同位置展示出不同的形态时候使用
// vuex的计算属性
getters:{
uptitle(state){
// 必须有return
return state.title.toUpperCase()
},
strtitle(state){
return state.title.substr(1,3)
}
}
使用
this.$store.getters.xxx
1.新建一个随便名字的文件夹(modules)用来存放一个个模块
2.在其中分别创建多个文件.js
3.在文件中写入state mutations actions getters
export let userm={
state:{
usertext:"我是user的数据"
},
mutations:{
},
actions:{
}
}
4.把这些模块文件在store文件中 先引用 在使用
import Vue from 'vue'
import Vuex from 'vuex'
import {homem} from "./modules/homem.js"
import {userm} from "./modules/userm.js"
import {aboutm} from "./modules/aboutm.js"
Vue.use(Vuex)
export default new Vuex.Store({
state: {
},
mutations: {
},
actions: {
},
modules: {
homem,userm,aboutm
}
})
5.页面调用除了获取state数据有区别 剩下的调用commit修改 dispatch异步操作和原来一样
state变成了: this.$store.state.模块名.xxx
dispatch调用actions进行异步请求 把请求来的数据通过commit调用mutations进行state的数据修改 从而在页面中展示
modules是一个模块用来拆分vuex的复杂度
getters是vuex的计算属性 一条数据在不同组件位置展示出不同的形态使用
因为浏览器的安全机制 同源策略( 同端口 同协议 同域名 )
1.jsonp 动态创建一个script标签
2.代理跨域
因为vue脚手架中集成了一个小的内置服务器叫devServer 我们代理跨域就是让这个小的内置服务器帮助我们请求数据 这样一来我们就绕开了浏览器同时也就绕开了浏览器的安全机制—同源策略
1.配置代理跨域在vue.config.js中的devServer中配置如下内容
module.exports={
devServer:{
open:true,
proxy: {
'/api': {
target: 'http://www.weather.com.cn/', //对应自己的接口
changeOrigin: true,
ws: true,
pathRewrite: {
'^/api': ''
}}
}
}
}
2,千万不要忘了去修改你的请求地址
3.cors(后端解决)
在公司跨域谁解决?
1.在开发过程中 通常前端解决(代理跨域 上线之后就废了)
2.上线之后肯定是后端解决
使用params发送数据 params需要一个对象
import service from "@/util/service.js"
export function getlink(url,params){
return new Promise((resolve)=>{
service.request({
url,
method:"GET",
// 发送数据
params
}).then((ok)=>{
resolve(ok)
})
})
}
发送的时候
getlink("地址",{数据}).then((ok)=>{
console.log(ok)
})
使用post发送数据需要使用 var param=new URLSearchParams();修改传参方法
使用param.append(“uname”,“xixi”)添加数据并且使用data发送数据
import service from "@/util/service.js"
export function postlink(url,data){
return new Promise((resolve)=>{
service.request({
url,
method:"POST",
data
}).then((ok)=>{
resolve(ok)
})
})
}
funb(){
let usp=new URLSearchParams
// usp.append("key","val")
usp.append("posttext",this.inputvalb)
postlink("/api/ceshi/post",usp).then((ok)=>{
console.log(ok)
})
}
https://vant-contrib.gitee.io/vant/#/zh-CN/
指令 就是在vue中v-前缀的html特殊属性
指令 是有限的就那几个 但是如果我想用的功能没有的怎么办?
自定义指令--------- 就是我们自己定义指令
5个钩子要记住
5个钩子要记住
5个钩子要记住
5个钩子要记住
5个钩子要记住
5个钩子要记住
自定义指令
测试自定义指令
就是在vue组件的风格不同(就是显示的内容不一样)同时在多个组件中有一些相同的属性和方法显然我们不能在每个组件里面都写一遍 我们需要那这些相同的内容提取出来 写成一个公共的 那么这个公共的文件就叫mixins
创建混入文件
let myMixins={
data(){
return {
text:"呵呵"
}
},
methods:{
fun(){
alert("你好")
}
},
directives:{
xiaoming:{
inserted(el){
el.style.backgroundColor="red"
}
}
}
}
// 不要忘了暴露
export default myMixins
使用混入 用mixins属性对应一个数组
demoa
在任何组件中都可以使用
在main中引用 并且使用
import MinXin from ‘@/components/MinXins/index.js’
Vue.mixin(MinXin);
在组件中即可随意使用混入中的数据
props
通过事件触发一个$emit()
父组件怎么直接触发子组件的方法?
使用ref绑定到子组件之上
1.愚蠢的方式
先逆向传值给父组件 父组件在正向传值给子组件
2.中央事件总线方式
创建一个新的Vue实例,以后它就承担起了组件之间通信的桥梁了,也就是中央事件总线。
1、创建一个事件总线,例如demo中的eventBus,用它作为通信桥梁
2、在需要传值的组件中用bus.emit触发一个自定义事件,并传递参数(emit前加美元符)
3、在需要接收数据的组件中用bus.$on监听自定义事件,并在回调函数中处理传递过来的参数
vuex
你在vue开发中有没有遇见过 模型数据改变了 但是视图没有发生改变的情况 是怎么解决这个问题的?
出现的场景
当vue的data里边声明或者已经赋值过的对象或者数组(数组里边的值是对象)时,向对象中添加新的属性,如果更新此属性的值,是不会更新视图的。
$set
你在vue开发中有没有遇见过 模型数据改变了 但是视图没有发生改变的情况 是怎么解决这个问题的?
{{arr.name}}-----{{arr.age}}
出现这种情况的原理
官方这样说:
当你把一个普通的 JavaScript 对象传入 Vue 实例作为 data 选项,Vue 将遍历此对象所有的属性,并使用 Object.defineProperty 把这些属性全部转为 getter/setter。
受现代 JavaScript 的限制 (以及废弃 Object.observe),Vue 不能检测到对象属性的添加或删除。由于 Vue 会在初始化实例时对属性执行 getter/setter 转化过程,所以属性必须在 data 对象上存在才能让 Vue 转换它,这样才能让它是响应的。
简单点来解释:
Object.defineProperty只会在初始化的时候监听data模型数据 如果中途加入新的对象属性 那么这个方法就不会监听到 不监听也就没有了双向绑定 没有了双向绑定就不会有模型变了视图发生改变这一说
解决问题
$set()
$set
你在vue开发中有没有遇见过 模型数据改变了 但是视图没有发生改变的情况 是怎么解决这个问题的?
{{arr.name}}-----{{arr.age}}
Vue 在修改数据后,视图不会立刻更新,而是等同一事件循环中的所有数据变化完成之后,再统一进行视图更新。
vue.nexttick 等待 Vue 完成更新 DOM 可以在数据变化之后立即调用
vue.nexttick 等待 Vue 完成更新 DOM 可以在数据变化之后立即调用
vue.nexttick 等待 Vue 完成更新 DOM 可以在数据变化之后立即调用
vue.nexttick 等待 Vue 完成更新 DOM 可以在数据变化之后立即调用
vue.nexttick 等待 Vue 完成更新 DOM 可以在数据变化之后立即调用****
nexttick
{{text}}
1.首先修改数据,这是同步任务。同一事件循环的所有的同步任务都在主线程上执行,形成一个执行栈,此时还未涉及DOM.
2.Vue开启一个异步队列,并缓冲在此事件循环中发生的所有数据变化。
3.同步任务执行完毕,开始执行异步队列的任务,更新DOM
npm run build 进行打包
在项目下面会生成一个dist文件夹就是打包好的内容 运行其中的html文件即可
运行之后会发现白屏 在控制台会发现有报错
需要修改静态资源路径
在vue.config.js中 添加publicPath:"./"设置为当前级、
module.exports={
publicPath:"./"
}
下面的是完整配置 (每个公司的需求都不同 所以这个配置不是固定的 百分之99的公司都没有这么多的需求)
module.exports = {
// 基本路径
publicPath: './', //部署应用包时的基本 URL
runtimeCompiler: false, //是否使用包含运行时编译器的 Vue 构建版本。设置为true可以使用template
productionSourceMap: false,//生产环境是否生成 sourceMap 文件
lintOnSave: true,
chainWebpack(config) {
config.resolve.alias
// .set('style', resolve('public/style'))
config.output.filename('js/[name].[hash:16].js');//hash值设置
config.output.chunkFilename('js/[id].[hash:16].js');
// config.output.filename('css/[name].[hash:16].css');//hash值设置
},
configureWebpack: () => {
},
// css相关配置
css: {
// 是否使用css分离插件 ExtractTextPlugin
extract: true,
// 开启 CSS source maps?
sourceMap: false,
// css预设器配置项
loaderOptions: {},
// 启用 CSS modules for all css / pre-processor files.
modules: false
},
parallel: require('os').cpus().length > 1,//是否为 Babel 或 TypeScript 使用 thread-loader
// PWA 插件相关配置
// see https://github.com/vuejs/vue-cli/tree/dev/packages/%40vue/cli-plugin-pwa
pwa: {},
// webpack-dev-server 相关配置
devServer: {
port: 8888,
https: false,
hotOnly: false,
// 设置代理
proxy: {
'/api': {
target: 'http://localhost:3000/', //对应自己的接口
changeOrigin: true,
ws: true,
pathRewrite: {
'^/api': ''
}
}
},
},
// 第三方插件配置
pluginOptions: {
// ...
}
}
在打包运行发现什么都没有 也没有报错
解决:把路由模式修改成hash
在打包运行即可
1ui组件的部分样式不满足当前项目的需求。
2.ui组件出现问题的时候,我们有中间键支持,不至于整个项目崩塌。
二次封装的弊端:
因为我们对element-ui进行了二次封装,当element-ui组件升级的时候,我们二次封装的组件不能直接使用element-ui的新方法,所以需要有人不断的对组件进行维护,有一定的开发成本。
创建组件并且把elementui 指定的内容放置其中 (可以吧需要的参数定义成props方便复用)
在main.js中进行引用当前封装的组件 并且使用Vue.component(“组件名”,引用的组件) 设置成全局组件
新建layout文件夹 并且 在内部新建指定存放的文件夹
如果需要组件功能复用 那么可以使用传值方式进行参数的传递
页面中使用:this.$route.meta.xxx
页面中得到路由信息
this.$router.options.routes