一套构建用户界面的渐进式的自底向上开发的MVVM框架
可以在原有大系统的上面,把一两个组件改用vue实现,也可以整个用vue全家桶开发,不做职责之外的事
先写一个基础的页面,把基础的东西写好,再逐渐去添加功能和效果,有简单到繁琐的这么一个过程
先写兼容底层浏览器的内容,逐渐兼容高版本
先兼容高级版本浏览器,再逐渐向下兼容
1-解决数据绑定问题
2-开发大型单页面应用
3-组件化开发,把页面封装成组件,挺高复用性
1-数据驱动
2-组件化
封装与业务无关的重复代码,形成框架
vue的核心是一个允许采用简洁的模板语法来声明式的将数据渲染进DOM
1-声明式编程
2-命令式编程
通过控制数据的变化来显示vue的数据驱动使视图的内容随着数据的改变而改变
vue中data数据可以是js任意形式
vue中数据绑定使用{{}},里面存放的是表达式--通过计算可以返回结果的公式
写在html标签中,扩展html的功能
带有v-前缀的html特殊属性,写在html的开标签中,
扩展html标签的功能
显示隐藏
绑定事件
用在表单元素中完成双向绑定
vue数据双向绑定是通过数据劫持结合发布者--订阅者的方式来实现的
数据劫持:当我们访问或者设置对象的属性的时候,都会触发Object.defineProperty()函数来拦截(劫持),然后在返回(get)或者设置(set)对象的属性的值
发布者-订阅者模式:定义对象间一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都将得到通知。
v-model 绑定到表单元素中,那么他的值会自动被表单元素进行设置,如果是复选框,那么勾选上值为ture,不勾选就为false.
对数据进行遍历展示
v-for="(遍历的值,遍历的下标) in 要遍历的数据 "
v-for="(遍历的值,遍历的下标) in 要遍历的数据 "
绑定html元素的属性
绑定多个属性不能使用简写
判断是否加载固定的内容,对元素进行现实和隐藏。
v-if:对元素的dom进行添加和删除,高切换,安全性高
v-show:用css控制元素显示隐藏,高消耗,不安全
与v-if搭配使用
往指定区域插入文本
v-text叫做指令
{{}}叫模板插值,当网速慢的时候会把{{}}展示出来
当vue没有加载的时候先不显示,加载完毕之后再展示数据,解决屏幕闪烁的问题。不用每个都加,加在vue挂载的元素上就行。
把字符串标签解析成标签
一次性插值,只展示一次,后面数据改变页面不会跟着改变
可以监听data模型数据 当模型数据改变的时候就会触发一个异步的方法,完成指定功能
watch:{
监听的变量(新数据,旧数据){
consolo.log(新数据+"-----"旧数据)
}
}
watch:{
inputa(newval,oldval){
// 判断两个输入框是否为空
if(this.inputa==""||this.inputb==""){
this.bool=true
}else{
this.bool=false
}
}
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<script src="node_modules/vue/dist/vue.min.js"></script>
</head>
<body>
<div id="demodiv">
<!-- watch 用来监听data模型数据 当数据改变watch就会自动触发 -->
<input type="text" v-model="text">{{text}}
</div>
<script >
new Vue({
el:"#demodiv",
data:{
text:"你好"
},
methods:{
},
watch:{
text(newval,oldval){
console.log(newval+"-------"+oldval)
}
}
})
</script>
</body>
</html>
watch初始化的时候不会执行,只有数据改变的时候才会运行
概念:顾名思义,首先它是一种属性,其次它有“计算”这个特殊性质。每次取得它的值得时候,它并不像普通属性那样直接返回结果,而是经过一系列的计算之后再返回结果。同时只要在它的当中里引用了 data 中的某个属性,当这个属性发生变化时,计算属性仿佛可以嗅探到这个变化,并自动重新执行。
如果一条数据需要被处理之后再进行展示的话,可以使用计算属性
或者是一条数据在不同位置展示不同的形态的时候,可以使用计算属性
computed: {
需要返回的数据: function () {
return 处理操作
}
}
----------------------------------------
另一种写法:
computed: {
需要返回的数据() {
return 处理操作
}
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<script src="node_modules/vue/dist/vue.min.js"></script>
</head>
<body>
<div id="demodiv">
<!-- 如果在视图中有大量的业务数据处理没有问题 但是会影响我们的代码
可读性 官方不推荐我们这样子写 而且区公司也不能这样子写 -->
<!-- {{text.toUpperCase()}}
{{text}}
{{text.toUpperCase().substr(2,3)}} -->
<!-- 如果 一条数据需要被处理之后再进行展示的话 可以使用计算属性
或者是 一条数据在不同位置展示数不同的形态 可以使用计算属性 -->
<h1>{{newtext}}</h1>
<h1>{{newbtext}}</h1>
<h1>{{newtext}}</h1>
<h1>{{newbtext}}</h1>
<h1>{{newtext}}</h1>
<h1>{{newbtext}}</h1>
<h1>{{newtext}}</h1>
<h1>{{newbtext}}</h1>
<h1>{{newtext}}</h1>
<h1>{{newbtext}}</h1>
<h1>{{newtext}}</h1>
<h1>{{newbtext}}</h1>
<hr>
<h1>方法</h1>
<h2>{{fun()}}</h2>
<h2>{{funb()}}</h2>
<h2>{{fun()}}</h2>
<h2>{{funb()}}</h2>
<h2>{{fun()}}</h2>
<h2>{{funb()}}</h2>
<h2>{{fun()}}</h2>
<h2>{{funb()}}</h2>
<h2>{{fun()}}</h2>
<h2>{{funb()}}</h2>
<h2>{{fun()}}</h2>
<h2>{{funb()}}</h2>
<h2>{{fun()}}</h2>
<h2>{{funb()}}</h2>
<h2>{{fun()}}</h2>
<h2>{{funb()}}</h2>
<h2>{{fun()}}</h2>
<h2>{{funb()}}</h2>
</div>
<script >
new Vue({
el:"#demodiv",
data:{
text:"abcdefg"
},
methods:{
fun(){
console.log("我是方法")
return this.text.toUpperCase()
},
funb(){
return this.text.toUpperCase().substr(2,4)
}
},
watch:{
},
computed:{
newtext(){
console.log("我是计算属性")
return this.text.toUpperCase()
},
newbtext(){
return this.text.toUpperCase().substr(2,4)
}
}
})
</script>
</body>
</html>
1-计算属性是基于它们的依赖进行缓存的。计算属性只有在它的相关依赖发生改变时才会重新求值。计算属性有缓存,方法没有缓存,方法用一次被调用一次
2-方法绑定数据只要被调用,方法将总会再次执行函数。
3-计算属性相对于方法在处理特定场合下节省资源性能
两者都是对data模型数据进行相关的处理
计算属性是当传入的数据发生改变之后,计算属性会重新计算,返回新数据
watch是当监听的数据发生改变时会触发一个相关的函数
触发事件的对象
作用:记录事件相关的信息,
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<script src="node_modules/vue/dist/vue.min.js"></script>
</head>
<body>
<div id="demodiv">
<input type="text" @keydown.ctrl="fun($event)">
</div>
<script >
new Vue({
el:"#demodiv",
data:{
},
methods:{
fun(e){
// console.log(e)
// if(e.keyCode==17){
console.log("用户按下了ctrl")
// }
}
},
watch:{
},
computed:{
}
})
</script>
</body>
</html>
概念:v-on指令提供了事件修饰符来处理DOM事件细节
@click.修饰符='fn()'
.up, .down, .ctrl, .enter, .space等等
prevent修饰符:阻止事件的默认行为(submit提交表单)
stop修饰符:阻止事件冒泡
capture修饰符:与事件冒泡的方向相反,事件捕获由外到内
self:只会触发自己范围内的事件,不包含子元素
once:只会触发一次
注意:修饰符可以串联使用
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<script src="node_modules/vue/dist/vue.min.js"></script>
<style>
.fu{
width: 500px;
height: 500px;
background-color: pink;
}
.zi{
width: 200px;
height: 200px;
background-color: green;
}
</style>
</head>
<body>
<div id="demodiv">
<div class="fu" @click="fufun()">
<div class="zi" @click.stop.once="zifun()"></div>
</div>
</div>
<script >
new Vue({
el:"#demodiv",
data:{
},
methods:{
fufun(){
console.log("夫妇付付付付付付")
},
zifun(){
console.log("zizizzizizizizizzizi")
}
},
watch:{
},
computed:{
}
})
</script>
</body>
</html>
是一个异步的解决方案,主要是为了解决回调地狱(回调函数层层嵌套)
传统的异步代码的可读性很差,使用promise可以提高可读性
Promise对象是一个构造函数,用来生成promise实例。
const promise = new Promise(function(resolve,reject){
if(/*异步操作成功*/){
resolve(value);
}else{
reject(error);
}
})
promise构造函数接受一个函数作为参数,该函数的两个参数分别是resolve和rejected.他们是两个函数,由js引擎提供,不用自己部署
resolve函数的作用是,将Promise对象的状态从未完成变成成功,在异步操作成功时调用,并将异步操作的结果,作为参数传递出去;
rejected函数的作用是,将Promise对象的状态从未完成变为失败,在异步操作失败时调用,并将异步操作爆出的错误,作为参数传递出去。
Promise实例生成以后,可以用then方法指定resolved状态的回调函数,同时也可以用then方法指定rejected状态的回调函数,then方法执行完后返回一个新的Promise实例。
promise.then(function(value){},function(error){})
then方法可以接受两个回调函数作为参数。
第一个回调函数是Promise对象的状态变为resolved时调用。
第二个回调函数是Promise对象的状态变为rejected时调用。第二个是可选的。
这两个函数都接受Promise对象传出得值作为参数。
padding 等待
resolve 成功
reject 失败
new Promise((resolve,reject)=>{
resolve("成功信息")
reject("失败信息")
})
<script>
function linkapi(url,method){
return new Promise((resolve,reject)=>{
$.ajax({
url,
type:method,
dataType:"json",
success(ok){
resolve(ok)
},
error(err){
reject(err)
}
})
})
}
var a = "http://api.artgoer.cn:8084/artgoer/api/v1/user/324380/v3/topic/topicHomeByLabel?pageIndex=1&token=b544cd63-6d42-46fe-a96c-3cf96bae3113&topicId=62187";
linkapi(a,"get").then((data)=>{
console.log(data)
}).catch((err)=>{
console.log(err)
})
</script>
<script>
function linkapi(url,method){
return new Promise((resolve,reject)=>{
axios({
url,
method,
}).then((ok)=>{
resolve(ok)
}).catch((err)=>{
reject(err)
})
})
}
var a = "http://api.artgoer.cn:8084/artgoer/api/v1/user/324380/v3/topic/topicHomeByLabel?pageIndex=1&token=b544cd63-6d42-46fe-a96c-3cf96bae3113&topicId=62187";
linkapi(a,"get").then((data)=>{
console.log(data)
}).catch((err)=>{
})
</script>
前端:客户端,就是浏览器(pc端 手机端)
后端:服务器(性能很好的电脑)是提供计算服务的设备。
服务器的构成包括处理器、硬盘、内存、系统总线等,和通用的计算机架构类似,但是由于需要提供高可靠的服务,因此在处理能力、稳定性、可靠性、安全性、可扩展性、可管理性等方面要求较高。
vue实例从创建到销毁的过程中有很多个阶段,在每个阶段都有一些函数会被自动执行,可以方便的帮助我们完成自动被执行调用的逻辑。
<body>
<!-- 生命周期 -->
<div id="demodiv">
<h1>{{text}}</h1>
<button v-on:click="text='我改了'">点我修改</button>
</div>
<script>
new Vue({
el:"#demodiv",
data:{
text:"生命周期"
},
methods:{},
watch:{},
computed:{},
filters:{},
beforeCreate(){
console.log("实例创建之前")
},
created(){
console.log("实例创建之后")
},
beforeMount(){
console.log("开始创建模板")挂载前
},
mounted(){
console.log("创建模板ok")挂载后
},
beforeUpdate(){
console.log("开始更新")
},
updated(){
console.log("更新完成")
},
beforeDestroy(){
console.log("开始销毁")
},
destroyed(){
console.log("销毁完成")
},
})
</script>
</body>
1-beforeCreate(创建前) 在数据观测和初始化事件还未开始
2-created(创建后) 完成数据观测,属性和方法的运算,初始化事件,实例中的el属性还没有显示出来
3-beforeMount(载入前) 在挂载开始之前被调用,相关的render函数首次被调用。实例已完成以下的配置:编译模板,把data里面的数据和模板生成html。注意此时还没有挂载html到页面上。
4-mounted(载入后) 在el 被新创建的 vue.el 替换,并挂载到实例上去之后调用。实例已完成以下的配置:用上面编译好的html内容替换el属性指向的DOM对象。完成模板中的html渲染到html页面中。此过程中进行ajax交互。
5-beforeUpdate(更新前) 在数据更新之前调用,发生在虚拟DOM重新渲染和打补丁之前。可以在该钩子中进一步地更改状态,不会触发附加的重渲染过程。
6-updated(更新后) 在由于数据更改导致的虚拟DOM重新渲染和打补丁之后调用。调用时,组件DOM已经更新,所以可以执行依赖于DOM的操作。然而在大多数情况下,应该避免在此期间更改状态,因为这可能会导致更新无限循环。该钩子在服务器端渲染期间不被调用。
7-beforeDestroy(销毁前) 在实例销毁之前调用。实例仍然完全可用。
8-destroyed(销毁后) 在实例销毁之后调用。调用后,所有的事件监听器会被移除,所有的子实例也会被销毁。该钩子在服务器端渲染期间不被调用。
Vue 实例从创建到销毁的过程,就是生命周期。也就是从开始创建、初始化数据、编译模板、挂载Dom→渲染、更新→渲染、卸载等一系列过程,我们称这是 Vue 的生命周期。
生命周期中有多个事件钩子,让我们在控制整个Vue实例的过程时更容易完成指定逻辑。
它可以总共分为8个阶段:创建前/后, 载入前/后,更新前/后,销毁前/销毁后
第一次页面加载时会触发 beforeCreate, created, beforeMount, mounted 这几个钩子
DOM 渲染在 mounted 中就已经完成了。
格式化展示数据,把展示的数据快速的展示成我们想要的内容
vue2x的时候,vue取消了内置过滤器,如果想使用过滤器就必须自定义过滤器
在所有vue实例都可以使用的叫全局过滤器,必须定义在实例之前
全局过滤器的定义方法 位置:创建实例之前
Vue.filter(‘sum’, function(val){
return val + 4;
});
<body>
<!-- 全局过滤器
写在实例之前
Vue.filter("过滤器的名字随便写的",(你要过滤的数据会自动传入)=>{
return 逻辑
})
-->
<div id="demodiv">
aaaaaaaaa
<h1>{{text|xiaoming}}</h1>
</div>
<div id="demodivb">
bbbbbbbbbbb
{{text|xiaoming}}
<h1>{{num|xiaohong}}</h1>
</div>
<script>
Vue.filter("xiaoming",(val)=>{
return "《《"+val+"》》"
})
Vue.filter("xiaohong",(val)=>{
return "¥"+val
})
new Vue({
el:"#demodiv",
data:{
text:"demodiv"
}
})
new Vue({
el:"#demodivb",
data:{
text:"demodivb",
num:19.9
}
})
</script>
</body>
只能在一个指定vue实例中使用的叫局部过滤器,定义在指定vue实例中,与el同级。
只能在当前vue注册内容中使用
在vue实例中与el属性data属性同级定义
filters:{
过滤器名字:function(val){
return 输出内容
}
}
<body>
<div id="demodiv">
aaaaaaaaa
<h1>{{text|xiaoming}}</h1>
<h1>{{textb|xiaoming}}</h1>
</div>
<div id="demodivb">
bbbbbbbbbbb
{{text}}
</div>
<script>
new Vue({
el:"#demodiv",
data:{
text:"demodiv",
textb:"abcdefgbhjfhf"
},
filters:{
xiaoming:(val)=>{
return val.substr(0,4)+"..."
}
}
})
new Vue({
el:"#demodivb",
data:{
text:"demodivb"
}
})
</script>
</body>
vue请求数据有Vue-resource、Axios、fetch三种方式。
Vue-resource是Vue官方提供的插件,但是vue2.0之后停止更新了
Vue自身不带处理HTTP请求 如果想使用HTTP请求必须要引入 vue-resource.js 库它可以通过XMLHttpRequest发起请求并处理响应。也就是说,$.ajax能做的事情,vue-resource插件一样也能做到,而且vue-resource的API更为简洁。
Vue.js 交互借助于 $http 完成
get 类型
语法:this.$http.get(‘url’,
{params: {key1:val1,key2:val2…}}).
then(function(res){处理请求成功的情况},
function(res){处理请求失败的情况})
POST类型
语法:this.$http.post(‘url’,
{key1:val1,key2:val2…},
{emulateJSON:true}).
then(function(res){处理请求成功的情况},
function(res){处理请求失败的情况})
axios是第三方插件,利用promise进行了二次封装,返回的是promise对象
Axios是第三方插件,不仅能在Vue里使用,还能再其他第三方库中使用
//get类型
//语法:
axios.get('/路径?k=v&k=v}
.then((ok)=>{})
.catch((err)=>{})
axios(utl:'请求地址',method:'请求方式',params:{k:v}).then((ok)=>{})
使用get发送数据的时候 使用params:{key:val}发送数据
import service from "@/util/service.js"
export function zhucelink(url,params){
return new Promise((resolve,reject)=>{
service.request({
url,
method:"get",
params
}).then((ok)=>{
resolve(ok)
}).catch((err)=>{
reject(err)
})
})
}
<template>
<div class="about">
<h1>注册</h1>
用户名: <input type="text" v-model="inputa"/>
密码: <input type="text" v-model="inputb"/>
<hr>
<p>{{text}}</p>
<button @click="fun()">注册</button>
</div>
</template>
<script>
import {zhucelink} from "@/api/zhuceapi.js"
export default {
data(){
return {
text:"",
inputa:"",
inputb:""
}
},
methods:{
fun(){
zhucelink("/api/zhuce/zhuce/user",{uname:this.inputa,upwd:this.inputb}).then((ok)=>{
console.log(ok)
if(ok.data.data.loginid==1){
let num=4
setInterval(()=>{
num--
if(num==0){
this.$router.push("/")
}
this.text="注册ok----"+num+"秒后跳转到登录页面"
},1000)
}
})
}
}
}
</script>
//post类型
//语法
axios.post('/user', {k:v,k:v })
.then(function (ok) { })
.catch(function (error) { });
实例化对象:
let param = new URLSearchParams();
添加发送数据参数
param.append("key", "value");
axios(utl:'请求地址',method:'请求方式',data:{k:v}).then((ok)=>{})
使用post发送数据需要使用 var param=new URLSearchParams();修改传参方法
使用param.append("uname","xixi")添加数据并且使用data发送数据
import service from "@/util/service.js"
export function loginlink(url,data){
return new Promise((resolve,reject)=>{
service.request({
url,
method:"post",
data
}).then((ok)=>{
resolve(ok)
}).catch((err)=>{
reject(err)
})
})
}
<template>
<div class="home">
<h1>登录</h1>
用户名: <input type="text" v-model="inputa"/>
密码: <input type="text" v-model="inputb"/>
<hr>
<button @click="fun()">登录</button>
</div>
</template>
<script>
import {loginlink} from "@/api/loginapi.js"
export default {
name: 'Home',
components: {
},
data(){
return {
inputa:"",
inputb:""
}
},
methods:{
fun(){
let usp=new URLSearchParams()
usp.append("uname",this.inputa)
usp.append("upwd",this.inputb)
loginlink("/api/login/login/user",usp).then((ok)=>{
console.log(ok)
if(ok.data.data.usernum==1){
alert("登陆成功")
this.$router.push("/home")
}else{
alert("用户名密码失败!!!!!!")
}
})
}
}
}
</script>
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
import service from "@/util/service.js"
export function homelink(url,method){
return new Promise((resolve,reject)=>{
service.request({
url,
method
}).then((ok)=>{
resolve(ok)
}).catch((err)=>{
reject(err)
})
})
}
<form action="http://localhost:3000/home/img/upload" method="post" enctype="multipart/form-data">
<input type="file" name="logo" />
<input type="submit" value="form上传图片提交">
</form>
<input type="file" ref="demo" />
<button @click="fun()">点我上传图片</button>
methods:{
fun(){
// 需要找到图片并且转换成数据流
let imgfile=this.$refs.demo.files[0]
var formdata=new FormData()//创建出formdata对象(异步上传文件)
formdata.append("logo",imgfile)//添加上传文件的key 和后台接受的key要相同 imgfile就是当前得到的图片
imglink("/api/home/img/upload",formdata).then((ok)=>{
console.log(ok)
})
}
}
//上传图片时请求配置
import service from "@/util/service.js"
export function imglink(url,data){
return new Promise((resolve,reject)=>{
service.request({
url,
method:"post",
data,
cache: false, //不必须不从缓存中读取
processData: false,//必须处理数据 上传文件的时候,则不需要把其转换为字符串,因此要改成false
contentType: false,//必须 发送数据的格式
}).then((ok)=>{
resolve(ok)
}).catch((err)=>{
reject(err)
})
})
}
//在vue.config.js中
proxy: {
'/api': {
target: 'http://localhost:3000/', //对应自己的接口
changeOrigin: true,
ws: true,
pathRewrite: {
'^/api': ''
}} }
//请求的时候,请求地址要修改
fetch es6原生
vue脚手架---就是一个与业务无关的项目环境
vue-cli4x--2019年10月16号发布
npm install -g @vue/cli
vue --version
指定项目放在那个文件夹,cd到指定文件夹路径下
vue create 项目名
cd 项目名
npm run serve
组件就是用来封装可复用的ui代码块,组件的本质是自定义标签
父子组件的数据不能直接相互使用,父子组件是一个完整的独立作用域
props期待外部传值,就是在调用组件的时候从外部把数据传递进去
//父组件
<template>
<div class="content">
<Bi v-for="(v,i) in arr" :key="i" :title="v.title" :imgurl="v.img"/>
</div>
</template>
<script>
import Bi from "./bottomItem.vue"
export default {
components:{
Bi
},
data(){
return {
futext:"我是父的数据",
arr:[
{title:"首页1" ,img:"img/ciwei.png"},
{title:"首页2" ,img:"img/dianying.png"},
{title:"首页3" ,img:"img/recommend.png"},
{title:"首页4" ,img:"img/video.png"},
{title:"首页5" ,img:"img/yuedu.png"},
]
}
}
}
</script>
<style>
.content{
width: 100%;
height: 90px;
border-top:1px solid red;
position: fixed;
bottom: 0px;
display: flex;
flex-direction: row;
}
</style>
子组件
<template>
<div class="item">
<img :src="imgurl"/>
<br/>
<span>{{title}}</span>
</div>
</template>
<script>
export default {
data(){
return {
zitext:"我是子的数据"
}
},
props:["title","imgurl"]
}
</script>
<style scoped>
p{
color:pink;
}
.item{
flex: 1;
text-align: center;
}
img{
width: 25px;
height: 25px;
}
</style>
就是在父组件给子组件数据的时候,默认情况下任意数据类型都可以传递,但是这样会造成问题,就是子组件在使用数据的时候就没办法进行更加复杂的处理,有时必须限制数据类型,这个时候用props
props不通过的话,不会对程序的运行造成影响,但是只会在console中报一个警告
在进行props验证时,数据传递明显发生了错误,但是没有错误提示?
因为用vue包是压缩版本的,压缩版本把props验证的错误去掉了,如果要有错误提示,改用不压缩版本。
<template>
<div>
{{img}}
<button @click="fun()">点我完成逆向传值</button>
</div>
</template>
<script>
export default {
props:["img"],
methods:{
fun(){
this.$emit("rightpao","我是子组件的数据")
}
}
}
</script>
<style scoped>
</style>
<template>
<div>
<div class="content" v-for="(v,i) in arr" :key="i">
<div class="left">
<Leftzi :title="v.title"/>
</div>
<div class="right">
<Rightzi :img="v.img" @rightpao="fufun"/>
</div>
</div>
</div>
</template>
<script>
import Leftzi from "./leftzi.vue"
import Rightzi from "./rightzi.vue"
export default {
methods:{
// val形参就是子组件传递过来的数据
fufun(val){
console.log(val)
}
},
created(){
// console.log("aaaa")
// console.error("1aaaa")
// console.warn("2aaaa")
},
data(){
return {
arr:[
{title:"1111111",img:"图1片"},
{title:"恋爱的犀牛哈哈22!!!",img:"2图片"},
{title:"恋爱的犀牛哈哈33!!!",img:"图3片"},
{title:"恋爱的犀牛哈哈44!!!",img:"4图片"},
{title:"恋爱的犀牛哈哈55!!!",img:"图5片"},
{title:"恋爱的犀牛哈哈66!!!",img:"6图片"}
]
}
},
components:{
Leftzi,
Rightzi
}
}
</script>
<style scoped>
.content{
display: flex;
flex-direction: row;
font-size: 0.16rem;
}
.left{
flex: 2;
height: 1rem;
background-color: pink;
}
.right{
flex:1;
height: 1rem;
background-color: green;
}
</style>
为遍历数组或元素中的唯一标示,增加或删减元素时,通过这个喂一标示key判断是否是之前的元素,vue会直接对已有的标签进行复用,不会整个的将所有的标签全部删除和创建,只会重新渲染数据,然后再创建新的元素直到数据渲染完毕
组件中数量不同内容不同,使用的技术
具名槽口slot 就是带有名字的槽口,在定义slot的时候使用name属性来起名字,在使用的时候使用slot属性来进行插入
利用锚点完成切换
定义组件页面
定义路由,配置路由规则routes
import Vue from 'vue'
import VueRouter from 'vue-router'
import Home from '../views/homee.vue'
import Dianying from '../views/dianying.vue'
import Guangbo from '../views/guangbo.vue'
import Tushu from '../views/tushu.vue'
import Xiaozu from '../views/xiaozu.vue'
Vue.use(VueRouter)
const routes = [
{
path: '/home',
name: 'Home',
component: Home
},
{
path: '/dianying',
name: 'Dianying',
component: Dianying
},
{
path: '/guangbo',
name: 'Guangbo',
component: Guangbo
},
{
path: '/tushu',
name: 'Tushu',
component: Tushu
},
{
path: '/xiaozu',
name: 'Xiaozu',
component: Xiaozu
},
{path:"/",redirect:"/home"},
]
const router = new VueRouter({
mode: 'history',
base: process.env.BASE_URL,
routes
})
export default router
创建路由实例,传入routes
const router = new VueRouter({
mode: 'history',
base: process.env.BASE_URL,
routes
})
export default router
把路由实例挂载到vue实例中
import Vue from 'vue'
import App from './App.vue'
import router from './router'
Vue.config.productionTip = false
new Vue({
router,
render: h => h(App)
}).$mount('#app')
配置路由出口
<router-view/>
配置路由导航router-link,浏览器会把routerlink解析成a标签,写路由导航的时候不能写成a标签。
<template>
<div id="nav">
<router-link to="/home">首页</router-link>
<router-link to="/list">列表</router-link>
<router-link to="/jx">惊喜</router-link>
</div>
</template>
声明式
编程式
重新定位方向,{path:"重定向的路径",“redirect”:"把路径调到要去的地方"}
{path:"/",redirect:"/home"},
{
path: '/*',
name: 'No',
component: No
},
在路由规则的path中使用 path:"/地址/:xxx"
{
path: '/list/:id/:xiaoming',
name: 'List',
component: List
},
声明式发送参数
<h1>声明是方式进行params路由传参</h1>
<router-link to="/list/我是声明第一个参数">第一种方式 了解</router-link>
<!-- :to="{name:'你要去的路由的规则上name的值' ,parmas:{key:val}}" -->
<router-link :to="{name:'List',params:{xiaoming:'我是声明第2个参数'}}">第2种方式</router-link>
methods:{
fun(){
this.$router.push({name:'List',params:{xiaoming:'我是编程式传参'}})
}
}
<div>我是详情页面----{{this.$route.params.xiaoming}}</div>
使用1.发送
<router-link :to="{name:'Querylist',query:{xiaohong:'我是声明式方式进行的query传参'}}">使用声明式的方式进行query传参</router-link>
<router-link :to="{path:'Querylist',query:{xiaohong:'我是声明式方式进行的query传参'}}">使用声明式的方式进行query传参</router-link>
<router-link :to="/Querylist/?id=参数1&name=参数2">使用声明式的方式进行query传参</router-link>
js发送
this.$router.push({name:'Querylist',query:{xiaohong:'我是声明式方式进行的query传参'})
this.$router.push({path:'Querylist',query:{xiaohong:'我是声明式方式进行的query传参'})
this.$router.push("/Querylist/?id=参数1&name=参数2")
2.接收 this.$route.query.xxxx
<h1>{{this.$route.query.xiaohong}}</h1>
用法上的:query要用path来引入,params要用name来引入,接收参数都是类似的,分别是this.$route.query.name和this.$route.params.name。
url展示上的
params类似于post,query更加类似于我们ajax中get传参,说的再简单一点,前者在浏览器地址栏中不显示参数,后者显示,所以params传值相对安全一些。
$router是VueRouter的一个对象,router的实例对象,这个对象中是一个全局的对象,他包含了所有的路由包含了许多关键的对象和属性。举例:history对象
$route是一个跳转的路由对象,每一个路由都会有一个$route对象,是一个局部的对象,可以获取对应的name,path,params,query等
默认的url中带#号。
url中没有没有没有没有没有没有#号 有的app里面url是不允许带有#号的,所以要将#号去除那么就要使用history模式,history模式还有一个问题就是,做刷新操作,会出现404错误,那么就需要和后端人配合让他配置一下apache或是nginx的url重定向,重定向到你的首页路由上。
路由导航中这样设置
to="/一级路由/二级路由"
路由导航中这样设置
to="二级路由"
vue的路由技术是为了完成spa单页面应用,在第一次页面初始化的时候,路由会把所有的路由页面都渲染好--可能会造成用户的页面白屏,可以使用路由懒加载。
{
path: '/phone',
name: 'phone',
component: () => import('../views/phone.vue')
}
当一个导航触发时,全局前置守卫(在进入组件之前)按照创建顺序调用。
vue-router 提供的 router.beforeEach((to,from,next)=>{})可以方便地实现全局前置导航守卫
to:即将要进入的目标 路由对象
from: 当前导航正要离开的路由
next: 下一步执行
import Vue from 'vue'
import VueRouter from 'vue-router'
import Home from '../views/Home.vue'
Vue.use(VueRouter)
const routes = [
{
path: '/',
name: 'Home',
component: Home
},
{
path: '/about',
name: 'About',
component: () => import('../views/About.vue')
},
{
path: '/login',
name: 'Login',
component: () => import('../views/login.vue'),
// 路由独享
beforeEnter(to,from,next){
alert('登录后才能访问')
next("/zhuce")
}
},
{
path: '/zhuce',
name: 'Zhuce',
component: () => import('../views/zhuce.vue')
}
]
const router = new VueRouter({
base: process.env.BASE_URL,
routes
})
// 全局前置
router.beforeEach((to,from,next)=>{
if(to.path=="/"||to.path=="/about"){
alert("您没有登录请您登录后访问");
// 去登录
next("/login")
}else{
// 下一步
next()
}
})
export default router
当一个导航触发时,全局后置钩子(在进入组件之后)调用。
vue-router 提供的 router.afterEach((to, from) => {})实现全局后置守卫
to:即将要进入的目标 路由对象
from: 当前导航正要离开的路由
import Vue from 'vue'
import VueRouter from 'vue-router'
import Home from '../views/Home.vue'
Vue.use(VueRouter)
const routes = [
{
path: '/',
name: 'Home',
component: Home
},
{
path: '/about',
name: 'About',
component: () => import('../views/About.vue')
},
{
path: '/login',
name: 'Login',
component: () => import('../views/login.vue'),
// 路由独享
beforeEnter(to,from,next){
alert('登录后才能访问')
next("/zhuce")
}
},
{
path: '/zhuce',
name: 'Zhuce',
component: () => import('../views/zhuce.vue')
}
]
const router = new VueRouter({
base: process.env.BASE_URL,
routes
})
//全局后置
router.afterEach((to,from)=>{
alert("欢迎您")
})
export default router
与全局前置守卫相比路由独享守卫只是对当前路由进行单一控制参数和全局前置守卫相同
在路由配置上直接定义 beforeEnter 进行路由独享守卫定义
import Vue from 'vue'
import VueRouter from 'vue-router'
import Home from '../views/Home.vue'
Vue.use(VueRouter)
const routes = [
{
path: '/',
name: 'Home',
component: Home
},
{
path: '/about',
name: 'About',
component: () => import('../views/About.vue')
},
{
path: '/login',
name: 'Login',
component: () => import('../views/login.vue'),
// 路由独享
beforeEnter(to,from,next){
alert('登录后才能访问')
next("/zhuce")
}
},
{
path: '/zhuce',
name: 'Zhuce',
component: () => import('../views/zhuce.vue')
}
]
const router = new VueRouter({
base: process.env.BASE_URL,
routes
})
export default router
组件内守卫只会对当前组件生效。
beforeRouteEnter在进入组件前调用
beforeRouteLeave离开路由之前
<template>
<div>
注册
</div>
</template>
<script>
export default {
beforeRouteLeave(to,from,next){
if(confirm("是否离开")){
next()
}else{
// flase就是什么都不执行
next(false)
}
}
}
</script>
<style>
</style>
路由meta路由记录/路由元信息。给每个路由添加一个自定义的meta对象,在meta对象中可以设置一些状态,来进行一些操作,供页面组件或者路由钩子函数中使用。
{
path: 'demoa',
name: 'demoa',
meta:{
arr:["首页","用户信息展示"],
linktext:"用户信息展示4",
linkicon:"el-icon-delete-solid",
linkto:"/home/demoa"
},
component: () => import( '../views/er/demoa.vue')
},
页面中使用:this.$route.meta.xxx
<el-breadcrumb separator="/">
<el-breadcrumb-item v-for="(v,i) in this.$route.meta.arr" :key="i">{{v}}</el-breadcrumb-item>
</el-breadcrumb>
页面中得到路由信息:$router.options.routes
<router-link
:to="v.meta.linkto"
v-for="(v, i) in this.$router.options.routes[2].children"
:key="i"
>
<el-menu-item :index="i">
<i :class="v.meta.linkicon"></i>
<span slot="title">{{ v.meta.linktext }}</span>
</el-menu-item>
</router-link>
创建mock文件夹,在mock中创建index.js和data文件夹
下载mockjs模块
在data中创建相关模拟数据的json文件,不能带注释
{
"arr":[
{"name":"1xixi","age":181},
{"name":"2xixi","age":182},
{"name":"3xixi","age":183},
{"name":"4xixi","age":184},
{"name":"5xixi","age":185},
{"name":"6xixi","age":186},
{"name":"7xixi","age":187}
]
}
编写index.js的mock代码
let Mock=require("mockjs")
Mock.mock("/home/listjson","get",require("./data/home.json"))
在main中引用mock
- import Vue from 'vue'
import App from './App.vue'
import router from './router'
Vue.config.productionTip = false
require("./mock")
new Vue({
router,
render: h => h(App)
}).$mount('#app')
在组件中使用
- <template>
<div>
home
<hr>
<!-- <router-link to="/home/era">era</router-link> -->
<!-- <router-link to="/home/erc">erc</router-link> -->
<router-link to="/era">era</router-link>
<router-link to="/erc">erc</router-link>
<router-view/>
</div>
</template>
<script>
import {homelink} from "api/homeapi.js"
export default {
mounted(){
homelink("/home/listjson","get").then((ok)=>{
console.log(ok)
})
}
}
</script>
跨域违背了同源策略
开发中,基本都是前端解决跨域
上线后,后端解决跨域
devServer: {
open: true,
port: 8088,
proxy: {
'/api': {
target: 'http://localhost:8888/', //对应自己的接口
changeOrigin: true,
ws: true,
pathRewrite: {
'^/api': ''
}
}
}
}
在请求的时候修改请求路径
mounted(){
homelink("/api/ceshi","get").then((ok)=>{
console.log(ok)
})
}
修改完重启服务
configureWebpack: {
resolve: {
alias: {
// "别名":"对应的文件夹"
"com": "@/components",
"api": "@/api"
}
}
}
module.exports = {
}
在日常开发中或者是面试中 会遇见一个问题:为什么修改了data中的数据,但是视图没有更新?
总结这个问题就是:
当vue的data里边声明或者已经赋值过的对象或者数组(数组里边的值是对象)时,
向对象中添加新的属性,如果更新此属性的值,是不会更新视图的。
根据官方文档:定义如果在实例创建之后添加新的属性到实例上,它不会触发视图更新。当你把一个普通的 JavaScript 对象传入 Vue 实例作为 data 选项,Vue 将遍历此对象所有的属性,并使用 Object.defineProperty 把这些属性全部转为 getter/setter。
受现代 JavaScript 的限制 (以及废弃 Object.observe),Vue 不能检测到对象属性的添加或删除。
由于 Vue 会在初始化实例时对属性执行 getter/setter 转化过程,
所以属性必须在 data 对象上存在才能让 Vue 转换它,这样才能让它是响应的。
this.$set(要操作的数据,新增的内容,值)
<template>
<div>
shop
<h1>{{ obj.name }}</h1>
<h1>年龄----{{ obj.age }}</h1>
<button @click="fun()">点我添加一个age</button>
</div>
</template>
<script>
export default {
data() {
return {
obj: {
name: "xixi",
},
};
},
methods: {
fun() {
// this.obj.age=19
this.$set(this.obj, "age", "29");
console.log(this.obj.age);
},
},
};
</script>
<style>
</style>
就是一个组件的数据仓库 把数据全部存到这个仓库中 那个组件想用 那个组件就自己去这个仓库取数据
组件之间的传值,一旦传值完毕,接受数据的这个组件无论怎么修改,传递数据的那个组件的数据不会改变
npm install vuex --save
配置vuex文件创建在src中创建store文件夹-->与store.js
Vuex 使用单一状态——用一个对象就包含了全部的应用层级状态。至此它便作为一个“唯一数据源 ”而存在。这也意味着,每个应用将仅仅包含一个 store 实例。
创建store实例
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
export default new Vuex.Store({
state: {
},
mutations: {
},
actions: {
},
modules: {
}
})
import Vue from 'vue'
import App from './App.vue'
import router from './router'
import store from './store'
Vue.config.productionTip = false
new Vue({
router,
store,
render: h => h(App)
}).$mount('#app')
通过父子组件传递来传值
就是在需要传值的兄弟组件上,创建一个新的vue实例,这个实例就叫做中央事件总线
在src下创建eventBus文件夹,在里面创建js文件,存放中央事件总线的vue实例
import Vue from "vue"
export default new Vue
创建vue实例并且暴露
在a组件中抛出需要传出的数据
创建一个A组件,引入事件总线的js文件,接着添加一个按钮并绑定一个点击事件,进行自定义事件抛出
<template>
<div>
我是demoa--<button @click="fun()">点我吧数据给我兄弟b</button>
</div>
</template>
<script>
import eventBus from "@/eventBus"
export default {
methods:{
fun(){
// 通过事件调用一个中央事件中线的自定义事件抛出
eventBus.$emit("pao","我是demoa的数据")
}
}
}
</script>
<style>
</style>
在b组件的生命周期中接收来自a组件的数据
再创建一个B组件,引入eventBus事件总线,在mounted钩子,监听了自定义事件,并把传递过来的字符串参数传递给了on监听器的回调函数
```html
```
1、创建一个事件总线,例如demo中的eventBus,用它作为通信桥梁
2、在需要传值的组件中用bus.emit触发一个自定义事件,并传递参数(emit前加美元符)
3、在需要接收数据的组件中用bus.$on监听自定义事件,并在回调函数中处理传递过来的参数
$on:监听当前实例上的自定义事件
state------数据源 相当于vue中的data 吧所有的数据保存在这里
读取数据: 在想使用的组件之上使用 this.$store.state.xxxx
也可以使用计算属性的方式进行state数据获取state里面存放的数据是响应式的
Vue组件从store中读取数据,若是store中的数据发生改变,依赖这个数据的组件也会发生更新
保存数据源,相当于vue中的data,保存数据的地方
读取数据,在想使用的组件上使用,this.$store.state.xxx
state里面的数据是响应式的,
state: {//数据源 相当于vue中的data 吧所有的数据保存在这里
text:1,
age:18,
bool:true,
arr:[11111,222222,3333333,4444444],
obj:{
name:"xixi",
age:19
},
axiosarr:[]
},
//要使用首先在main.js引入vuex。
import Vue from 'vue'
import App from './App.vue'
import router from './router'
import store from './store'
Vue.config.productionTip = false
new Vue({
router,
store,
render: h => h(App)
}).$mount('#app')
1 可以使用$store.state.xx
{{$store.state.text}}
{{this.$store.state.text}}
2 也可以在方法中调用
mounted(){
console.log(this.$store.state.text)
}
3 也可以在计算属性中调用
computed:{
obj(){
return this.$store.state.text
}
}
在组件中,通过this.$store.commit("需要调用的方法"),来调用mutation里面的方法
<button @click="add()">+{{num}}</button>
<button @click="del()">-{{num}}</button>
data(){
return {
num:""
}
},
methods:{
add(){
this.$store.commit("xadd",this.num)
},
del(){
this.$store.commit("xdel",this.num)
}
}
mutations: {//修改
//第一个参数代表state数据源
xadd(state,payload){
state.text+=payload
},
xdel(state,payload){
state.text-=payload
},
},
载荷:就是相当于从vue的组件中吧数据传递给mutations的一个过程传递的方式就是在 this.$store.commit("mustations的名字", 你要传递的数据)
如果载荷要传递多个数据 那么传递一个对象即可
this.$store.commit("mutations的名字",传递的值),传递的值也可以是对象
data(){
return {
num:""
}
},
methods:{
add(){
this.$store.commit("xadd",this.num)
},
del(){
this.$store.commit("xdel",this.num)
}
}
第二个参数基本上使用payload
mutations: {//修改
xadd(state,payload){
state.text+=payload
},
xdel(state,payload){
state.text-=payload
},
},
mutations ---- 在vuex中如果想修改数据 那么就是用mustations在组件中 通过this.$store.commit("mutations的名字")
问题 vuex数据刷新丢失vuex中页面刷新数据丢失问题
使用vue进行开发的过程中,状态管理工具一般使用vuex进行管理。
但是修改后的vuex数据存储在内存中,所以当前页面刷新数据会产生丢失现象使用H5特性本地存储流程
监听页面刷新
如果刷新了 就把state的数据存到本地存储中
在实例创建完毕之后取出来替换state以保证vuex数据刷新不丢失
//解决vuex数据刷新丢失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进行异步操作(异步请求)
Actions可以理解为通过将mutations里面处里数据的方法变成可异步的处理数据的方法,简单的说就是异步操作数据(但是还是通过mutation来操作,因为只有它能操作)
mounted(){
// 触发vuex的action
// this.$store.dispatch("actions的名字")
this.$store.dispatch("xlink")
}
actions: {//处理异步
xlink(context){
}
}
import {apilink} from "@/api/api.js"
actions: {//处理异步
//context形参代表Store对象
xlink(context){
apilink("http://api.artgoer.cn:8084/artgoer/api/v1/user/324380/v3/topic/topicHomeByLabel?pageIndex=1&token=b544cd63-6d42-46fe-a96c-3cf96bae3113&topicId=62187","get").then((ok)=>{
console.log(ok.data.data.commentList)
// 传递给mutations
//通过.commit来调用mutations对应的方法
context.commit("axiosm",ok.data.data.commentList)
}).catch((err)=>{
console.log(err)
})
}
},
mutations: {//修改
//调用那个方法,对应的就写那个方法的名字
axiosm(state,payload){
state.axiosarr=payload
}
},
Actions可以理解为通过将mutations里面处里数据的方法变成可异步的处理数据的方法,简单的说就是异步操作数据(但是还是通过mutation来操作,因为只有它能操作)
一条数据在不同位置展示出不同形态的时候用计算属性
使用场景:在项目开发中,有时候希望对state中的某个属性在多个组件中展示出不同状态
getters: { //vuex中的计算属性
newtext(state) {
return state.text.toUpperCase()
}
},
{{this.$store.getters.newtext}}
mounted() {
console.log(this.$store.getters.newtext);
},
__mindmap__topic可以让每一个模块拥有自己的state、mutation、action、getters,使得结构非常清晰,方便管理。
__mindmap__topic使用的时候 需要创建对应存放模块的文件夹 然后在其中创建相关js文件
之后就可以吧原本的state,mutations actions getters等这些内容都放置到 该文件夹中
在读取数据的时候 是this.$store.state.模块名.xxxx 剩下的操作 和没有使用modules的时候相同
export let aboutx={
state:{
atext:"我是about的数据"
}
}
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
import {aboutx} from "./modules/aboutx.js"
export default new Vuex.Store(
{
modules:{
aboutx,homex,shopx
}
}
)
使用数据:$store.state.模块名.xxx
{{ this.$store.state.aboutx.text }}
ref 被用来给元素或子组件注册引用信息, 引用信息将会注册在父组件的 $refs 对象上,如果是在普通的DOM元素上使用,引用指向的就是 DOM 元素,如果是在子组件上,引用就指向组件的实例。
$refs 是一个对象,持有已注册过 ref 的所有的子组件。
<button @click="fun()">点我修改颜色</button>
<h1 ref="demoh">我的颜色要被修改</h1>
methods:{
fun(){
this.$refs.demoh.style.color="red";
}
}
<Zi ref="democom"/>
<button @click="funb()">点我获取到子组件的数据</button>
methods:{
funb(){
console.log(this.$refs.democom.zitext)
}
}
<component is="变量"></component>
<template>
<div class="home">
<img alt="Vue logo" src="../assets/logo.png">
<div>
home <input type="text">
</div>
<h1>动态组件</h1>
<button @click="fun('Demoa')">点我去demoa</button>
<button @click="fun('Demob')">点我去demob</button>
<button @click="fun('Democ')">点我去democ</button>
<keep-alive >
<component :is="com" ></component>
</keep-alive>
</div>
</template>
<script>
import Demoa from "@/components/demoa.vue"
import Demob from "@/components/demob.vue"
import Democ from "@/components/democ.vue"
export default {
name: 'Home',
components: {
Demoa,Demob,Democ
},
data(){
return {
com:"Democ"
}
},
methods:{
fun(text){
switch (text) {
case "Demoa":
this.com=text
break;
case "Demob":
this.com=text
break;
case "Democ":
this.com=text
break;
}
}
}
}
</script>
包含的组件缓存
排除的组件不缓存,优先级大于include
<template>
<div class="home">
<img alt="Vue logo" src="../assets/logo.png">
<div>
home <input type="text">
</div>
<h1>动态组件</h1>
<button @click="fun('Demoa')">点我去demoa</button>
<button @click="fun('Demob')">点我去demob</button>
<button @click="fun('Democ')">点我去democ</button>
<!--Demoa被缓存-->
<!--除了Democ,其他的被缓存-->
<keep-alive include="Demoa" exclude="Democ">
<component :is="com" ></component>
</keep-alive>
</div>
</template>
<script>
import Demoa from "@/components/demoa.vue"
import Demob from "@/components/demob.vue"
import Democ from "@/components/democ.vue"
export default {
name: 'Home',
components: {
Demoa,Demob,Democ
},
data(){
return {
com:"Democ"
}
},
methods:{
fun(text){
switch (text) {
case "Demoa":
this.com=text
break;
case "Demob":
this.com=text
break;
case "Democ":
this.com=text
break;
}
}
}
}
</script>
在需要被激活的组件内写入,keep-alive激活时调用(进入的时候)
在需要被激活的组件内写入,keep-alive组件停用时调用(离开的时候)
<template>
<div>
<h1>用户信息录入</h1>
<div>
<input type="text">
</div>
<div>
<input type="text">
</div>
<div>
<input type="text" v-xiaoming>
</div>
<div>
<input type="text">
</div>
<div>
<input type="text">
</div>
</div>
</template>
<script>
export default {
activated() {
console.log("1激活activated钩子函数");
},
deactivated(){
console.log("bbbbb")
},
directives:{
"xiaoming":{
inserted(el){
el.focus()
}
}
}
}
</script>
<style>
</style>
在vue内置指令不够的情况下,使用自定义指令来完成具体的功能
<script>
export default {
directives:{
"xiaoming":{
inserted(el){
el.focus()
}
}
},
}
</script>
bind:绑定指令到元素上,只执行一次
inserted:绑定了指令的元素插入到页面中展示时调用,基本上都是操作这个钩子函数
update:所有组件节点更新时调用
componentUpdated:指令所在组件的节点及其子节点全部更新完成后调用
unbind:解除指令和元素的绑定,只执行一次
npm run build
在项目下面会生成一个dist文件夹就是打包好的内容 运行其中的html文件即可
module.exports = {
// 基本路径
publicPath: './', //部署应用包时的基本 URL
outputDir: 'dist', // 输出文件目录
assetsDir: '',//放置生成的静态资源 (js、css、img、fonts) 的 (相对于 outputDir 的) 目录
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: {
open: process.platform === 'darwin',
host: '0.0.0.0',
port: 8888,
https: false,
hotOnly: false,
// 设置代理
proxy: {
'/api': {
target: 'http://localhost:3000/', //对应自己的接口
changeOrigin: true,
ws: true,
pathRewrite: {
'^/api': ''
}
}
},
},
// 第三方插件配置
pluginOptions: {
// ...
}
}
router-view中的内容显示不出来
需要关闭路由的history模式,因为当前模式需要后台配合。
nginx服务器配置try_files重定向
api--->api.js--->封装请求
util--->service.js--->封装拦截器
mock --->{
data-->存放json数据,
index.js--->配置
}
store--->index.js--->vuex状态管理
此处可能存在不合适展示的内容,页面不予展示。您可通过相关编辑功能自查并修改。
如您确认内容无涉及 不当用语 / 纯广告导流 / 暴力 / 低俗色情 / 侵权 / 盗版 / 虚假 / 无价值内容或违法国家有关法律法规的内容,可点击提交进行申诉,我们将尽快为您处理。