Vue
是基于MVVM
设计模式
是单页面应用
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js">script>
指定一个选择器, 代表该元素中使用vue来渲染
let app = new Vue({
el:"#app"
})//app为标签id
el支持class(以点)、标签名方式
Mustache
语法糖
<div class="#app">{{content}}div>
<script> new Vue({
el:"#app",
data:{
content:"内容"
}
})script>
双大括号里面可以写表达式
{{true?name:age}}
一般数据来源后端(通过ajax请求)
var app=new Vue({
el:"#app",
data:{
content:"内容"
}
})
data里的数据可以与标签进行绑定
<div id="app">{{content}}div>
建议写函数形式
用脚手架需要
let app = new Vue({
el:"#app",
data(){
return{
//数据
}
}
})
里面存放的都是函数事件
var app=new Vue({
el:"#app",
data:{
content:""
},
methods:{
foo:function(){//}
}
})
methods事件里面通过this可以访问到data里面的数据也可以访问到methods
let app=new Vue({
el:"#app",
data:{
content:"内容"
},
methods:{
foo:function(){
this.content = "更改后的内容"
}
}
})
差值符号里面加上竖线 就是进行数据的判断
二次渲染
<p v-for="item in arr" :key:"item.name">
{{item.name | goudan}}
p>
<script>
let app=new Vue({
el:"#app",
data:{
arr:"数据"
},
filters:{
goudan(v){//这个v就是差值符号里面的item
return "加的东西"+v //过滤后的数据
}
}
})
script>
不能先定义在data里
将数据进行一次处理
<div id="app">
<p>{{funl}}p>
div>
<script>
let app=new Vue({
el:"#app",
data:{
arr:"数据"
,o:"bb"
},
computed:{
funl(){
return this.arr+"."+this.o
}
}
})
script>
computed:{
msg:{
get(){
return 2
}
,set(){
this.lie ++
}
}
}
要先在data里面定义
监听的数据发生变化之后这个函数会触发
data:{
a:10
},
watch:{
a(newVal,oldVale){//两个参数一个新值 一个旧值
console.log(1)
}
}
<div id="app" v-text="content">div>
let app=new Vue({
el:"#app",
data:{
content:"内容"
}
})
不能解析标签名,可以用字符串拼接
无论内容是什么只会解析为文本
可以用模板字符串
<div id="app" v-text=`${name}`>div>
当浏览器加载的数据非常庞大
加载的一瞬间会出现双大括号的差值表达式
解决这种 闪现 的现象
在需要隐藏的地方添加 v-cloak
然后再css
里面先隐藏这个标签
<div id="app" v-cloak>div>
[v-cloak]{
/* css里面不进行显示 */
display:none;
}
原理就是在页面加载的时候先不进行渲染
当Vue
挂在完成之后内部进行渲染
<div id="app" v-html="content">div>
let app=new Vue({
el:"#app",
data:{
content:"">内容"
}
})
设置元素的innerHTML
内容有html结构会被解析为标签
v-on:事件名=“方法”
<input type="button" value="事件绑定" v-on:click="foo">
<input type="button" value="事件绑定" v-on:mouseenter="foo">
<input type="button" value="事件绑定" v-on:dblclick="foo">
<input type="button" value="事件绑定" v-on:click="foo">
let app=new Vue({
el:"#app",
data:{
content:"1234"
},
methods:{
foo:function(){}
}
})
methods里面写事件
v-on可以简写为@
在方法里面传入参数
v-on:click=“foo(x)”
let app=new Vue({
el:"#app",
methods:{
foo:function(x){}//这里接受参数
}
})
@keydown.enter=“方法”
enter回车键
<div @keyup.k="方法($event)">div>
可以串联修饰
<div @keyup.k.enter.space="方法">div>
<div @click="方法">
<button @click.stop="方法">button>
div>
<div @click.right.prevent="方法">div>
<a href="地址" @click.right.prevent="方法">a>
传入两个事件需要传对象
<div v-on="{click:方法,mouseenter:方法}">div>
变相取消
<div @click="ifClick && clickAdd()">div>
设置和获取表单元素的值(双向数据绑定)
在表单元素里面添加v-model指令在指令里面添加data里面的数据
<div id="app">
<input type="text" v-model="content">
div>
<script>
let app=new Vue({
el:"#app",
data:{
content:"绑定的数据"
}
})
script>
无论是修改表单元素里的值还是数据里的值都会互相更改
根据表达式的真假来显示或者隐藏
true表示显示
false表示隐藏
<img v-show="true">
<img v-show="12<11">
原理是修改元素的display实现显示隐藏
指令后面的内容最终都会解析为布尔值
数据改变之后,对应元素的显示状态会同步更新
根据表达式的真假来显示或者隐藏操作的是dom元素
直接删除dom元素
性能消耗比较大
如果频繁切换用v-show
为false时从dom树中移出
配合v-if使用
如果if是false ,else就是显示
必须要紧跟v-if使用中间不能有东西
根据上一个v-if进行再次判断
v-bind:属性名=表达式
可以用冒号简写:
<img v-bind:src="imgSrc">
<img :src="imgSrc">
<img :class="imgClass?类名:''">
<img :class="{类名:imgClass}">
<script>
var app=new Vue({
el:"#app",
data:{
imgSrc:"地址",
imgClass:false
}
})
script>
<div :class="{red:ifRed}">div>判断ifRed的值来确定class添不添加red值
ifRed是真class就有red值
<div :class="[
{'red':ifRed},
'green'
]">div>数组里面必须有引号不加引号就会去data里面找
<div :style="{font-size:12px}">div>
根据数据生成列表结构
<ul>
<li v-for="(item,index) in arr"> {{index}} {{item}}li>
ul>
<h3 v-for="item in obj"> {{item.name}} h3>
<div v-for="(value,key,index) in o">value{{value}}key{{key}}index{{index}}div>value是键key是值index是序号
<script>
var app=new Vue({
el:"#app",
data:{
arr:[1,2,3,4,5],
obj:[
{name:"张三"},
{name:"李四"},
{name:"王五"}
],
o:{user:"名字",age:18,sex:"男"}
}
})
script>
li标签里item是数组的每一项 arr是数组本身
数组的长度的更新会同步到页面上去,是响应式的
根v-for一块使用
<div v-for="item in arr" :key="item">div>生成的每个div与item绑定
数组在后期进行打乱那么div也会随着数据进行移动
如果数据是对象数组就选取对象里面独一无二的属性
Vue.directive("goudan",(node,data)=>{//节点,数据
//里面进行的操作
})
//或者
Vue.directive('dachui',{
bind(){
//指令第一次绑定时调用的函数
},
inserted(){
//当被绑定的元素插入DOM中时
},
update(){
//数据进行更改时
},
componentUpdate(){
//
},
upbind(){
//解绑
}
})
标签里面添加v-goudan
指令里面传一个名字和函数
函数里面有两个参数
绑定的节点 , 带来的数据
extend
构造器创建子类const goudan = Vue.extend({
template:'{{name}}',
data(){
return{
name:'dachui'
}
}
})
//挂载到#cuihua里
new goudan().$mount('#cuihua')
在Vue里面操作数据数组没办法改其中一个或几个值(除了更改全部或重新赋值)
只要是数组就不行对象可以
改变数组里的其中一项
methods:{
fn(){
Vue.set(this.arr,0,"goudan")//把arr的第0项改成goudan
}
}
methods:{
fn(){
this.$set(this.arr,0,"goudan")//把arr的第0项改成goudan
}
}
this.$delete(this.arr,1)//删除下标是1的值
或者用JS splice
this.arr.splice(1,1)
nextTick
DOM进行更新之后进行操作
但是你写在那个方法里面那个才触发
this.$nextTick(function(){
console.log("DOM更新了")
})
console.log(Vue.version)
放在new Vue之前定义组件
组件中间不要有任何的东西
全局组件可以被任意组件所调用的
Vue.component(
//组件名 , 在html里面就是用这个标签来渲染 标签里面不写东西
"goudan",//还必须一些选项参数
{
//对应要生成的DOM结构
template:`内容
`
,data(){//data必须是函数
return {
msg:""
,num ++
}
}
,methods:{
add(){
this.num ++
}
}
}
)
生成对应的结构
但是结构只能有一个跟标签
起的名字不能与原有的标签名重复
驼峰命名的时候在标签里面用横杠显示-
但是在组件里面不是单词第一个大写
Vue.component("goudan",{
template:`123456 `
})
<div>
<goudan>goudan>
div>
在实例里面定义
属性就是组件名
根组件可以调用全局组件
全局组件不能调用根组件
new Vue({
el:"#app",
components(){
aaa:{//首先是用什么标签包起来
template:`组件
`
}
}
})
component标签是vue自带的
<component is="aaa">component>
<component :is="x">component>
<script>
new Vue({
el:"#app",
data:{
x:"aaa"
},
components:{
aaa:{
template:`这是组件`
}
}
})
script>
不能写在绑定Vue实例的标签里面
<template id="f">template>
<script>
new Vue({
el:"#app",
components:{
aaa:{
template:"#f"//和标签进行绑定
}
}
})
script>
父组件传过去的值改变 子组件也改变
<div id="app">
<aaaa :goudan="arr">aaaa>
div>
通过绑定标签属性传值
子组件接受
componente:{
aaaa:{
template:"#aaa"
,data(){
return {}
},
props:["goudan"]//这里数组方式接受数据
}
}
componente:{
aaa:{
temolate:"#aaa"
,data(){
return {}
}
,prop:{//对象非常像mongodb里面的表
goudan:Array
,m:{
type:String
,default:"这是默认值"
}
,o:{
type:String
,required:true//这个值是必须的
}
}
}
}
$emit
事件里的自定义事件传值
设置的自定义事件写在组件的标签上面
不建议使用驼峰命名,建议短横线命名-
父组件里的子组件标签
<aaa @goudan="fun">aaa>fun在父组件里写函数 ,父组件函数接受值
<script>
methods:{
fun(data){
//data就是传来的参数
}
}
script>
/*-------------下面是子组件里进行事件发射*/
<script>
methods:{
dachui(){
this.$emit("goudan",this.msg)//自定义事件名 ,传过来的数据
}
}
script>
<h1 ref="goudan">h1>
在Vue
实例里面使用this.$refs
获取此节点
如果在组件里使用ref
那么this.$refs
返回的是这个组件的实例方法
相当于组件的子组件传值个父组件
Vue.component("goudan",{
template:"#goudan",
data(){
return{}
},
provide(){
//发送数据
return{
goudan:'11'
}
}
})
Vue.component("dachui",{//另一个组件
template:"#dachui",
data(){
return{}
},
inject:['goudan']//接受
})
耦合
改的方法更麻烦一点
数据传过来的是非响应式的
<script src="https://unpkg.com/axios/dist/axios.min.js">script>
引入axios的地址
必须先导入再使用
使用get和set方法
axios.get("地址")//如果要查询具体的数值后面加上问号在添加属性名,等号属性值
.then((response)=>{
//请求数据成功的函数
console.log(response)
//response就是后端返回的数据
})
.catch(err=>{
//请求数据失败的函数
})
不同的地址获取的数据不同查询的方法不同
如果是表单元素(post)要在地址后面加逗号,在用对象的方式输入数值
axios.post("地址",{username:"名称"})
.then((response)=>{
//请求数据成功的函数
}).catch((err)=>{
//请求数据失败的函数
})
下载axios
包
npm i axios -S
把Axios
单独放一个js
文件里
import axios from "axios";
//配置默认的参数
axios.defaults.baseURL = 'http://localhost:3000';//默认访问地址
axios.defaults.withCredentials = true;//跨域允许携带cookie
axios.defaults.headers.post["Content-Type"] = "application/x-www-from-urlencoded";//设置post请求格式
使用axios
一种是全部引用
将所有的接口都引用
export default axios
使用
import request from '../api/index'
request.post("/articleInfo").then(data=>{console.log(data);}//articleInfo是地址
//post是请求方法
另一种方法是按需引用
导出的时候导出一个对象
export default {
goudan(){//标签
return axios.post("/articleInfo")//articleInfo是地址post是请求方法
}
};
使用
不支持解构
import axios from '../../api';
let goudan = axios.goudan;
created() {
goudan()
.then(res=>{
res.data.data;//data.data就是返回的数据
})
}
支持解构
export function goudan(){
return axios.get("地址")
}
使用
import {goudan} from '../../api';
new vue返回一个实例化后的东西
let vm = new Vue({
el:"#app",
data:{
content:"123"
}
})
//
created渲染DOM之前执行函数
npm i jquery -S//安装jquery
再导入
import $ from 'jquery'
//原型里添加$方法
Vue.prototype.$ = $
css
文件@import url("地址")
js
文件import "地址"//不用命名
npm i webpack -g
npm i webpack-cli -g
npm i @vue/cli -g
检测版本
vue -V//斜杠后面是大写的v
vue create 项目名 //创建项目文件
多选 选择是空格
或者是vue ui
一个ui界面
在js里面导入
import "名字" from "地址"
导出
export default "导出的东西"
npm run sever
npm run build
如果打包后放到路由的子路径
需要注意
在根目录创建vue.config.js
文件
写上如下代码
module.exports = {
publicPath:'./'
}
如果安装了前端路由请参照
https://www.cnblogs.com/zsg88/articles/12557862.html 进行更改
在你的组件写上slot标签
他不是一个正常的html标签所以插槽本身不会渲染
<slot>slot>
使用插槽之后 组件中间可以写东西了
顺序按照设置的属性
在插槽之后用差值符号数据就是App的数据/根组件的数据
如果同个插槽显示不同内容 给插槽起名字
<slot name="defalut">slot>默认是defalut
<slot name="goudan">slot>
<slot name="dachui">slot>
显示指定插槽内容用template
标签
简写是#号
<template v-slot:goudan>
<p>我是第一段内容p>
template>
<template #dachui>
<p>我是第二段内容p>
template>
可以用于传值
<slot :goudan="msg" :dachu="gg" :name="goudan">slot>
/使用
<template v-slot:goudan="{msg,gg}">
<p>我是第一段内容p>
template>
///或者是
<template #goudan="{msg,gg}">
<p>我是第一段内容p>
template>
一个组件的生命周期里做的一些事情
在渲染和实例挂载之间 去调用子组件 完成子组件的生命周期
<keyy-alive>
将组建写在这里 保存到缓存里面
节省性能
keyy-alive>
上面两个需要keyy-alive
标签才会触发
组件消失
组件重新显示
下载
引入
//全局
impot {Button} from "Vant"
Vue.use(Button)
//局部 局部需要下载插件
impot {Button} from "Vant"
export default {
components:{
[Button.name]:Button//用它组件里面的name
}
}
Vue add element-ui
需要Router
有两种
一个是默认的hash路由
一个是history
默认的路由地址上多一个#号
目的是判断是否是前端路由
history路由
路径就没有#号
但是他的路由容易跟后端冲突
比如 前端有一个/adou路由 后端有一个/adou路由 一旦刷新页面就出错
后端需要设置get路由返回同一个HTML
文件
切换模式就是更改router
下面的index
文件
const router = new VueRouter({
mode:"history",//默认是hash路由 ,就是带#号的
routes
});
export default router
先引用
在router文件里面的index引用你写的页面
router = [
path:"/",
name:"Home",
component:import("页面文件")
]
404页面就是星号 找不到路由
path:"*",
name:"404"
然后在页面里面引入标签
to就是你跳转的链接
<router-link to="/goudan">跳转router-link>跳转的标签
<router-view/>跳转时渲染的地方
this.$router.push("/")//添加一个当前的新历史 浏览记录
this.$router.go(-1)//当前页面向前访问 正数是向后
this.$router.replace("/")//替换当前浏览的记录
push
的操作//可以传对象
this.$router.push({path:'/foo1',query:{name:'goudan'}})//query是参数
在配置路由的地方需要的地方写上属性
children
是一个数组
[
{
path:"/",
name:"Home",
component:""
},{
path:"/about",
name:"about",
component:"",
children:[//拥有子路由
{
path:"all",
name:"All",
component:"文件路径"
}
]
}
]
渲染就跟原来的一样
但是在写router-link标签的时候注意
里面的to属性浏览器里的地址怎么写你就怎么写
<router-link to="/about/all">router-link>
如果想默认就出现一个子路由
他的路由里面的path就为空path:""
在router-link标签里面的to可以进行筛选路由
router-link>
找到路由里面name是All的路由
但是路由的命名时会冲突的
路由里面path有一个别名
他既可以有这个名字又可以有另一个名字
{
path:"",//在子路由里path不写意思指默认显示这个页面
alias:"all",
name:"All",
component:()=>import("路径")
}
参数在query
里面
mounted(){
this.$route.query
}
在路由里面设置
{
path:"about/:id"
}
请求链接的时候可以带上about/2222
获取用params
mounted(){
this.$route.params
}
next括号里面可以写false
在main.js里面写
切换完成之前
监听前端所有路由的变化
触发内部的函数
只要路由切换就触发函数
router.beforeEach((to,from,next)=>{
//to从哪那个路由来
//from到那个路由去
//next放行(相当于保安放行)
router.path("/")
next()
})
切换路由后
没有next因为你己经进入了那个页面
router.afterEach((to,from)=>{
//to从哪那个路由来
//from到那个路由去
})
在路由配置里面添加在你想要添加的页面
在某个单独的页面设置守卫
beforeEnter
{
path:"/about",
beforeEnter(to,from,next){
//to从哪那个路由来
//from到那个路由去
}
}
能够监听到路由的变化
beforeRouteEnter
因为在渲染之前执行所以监听不到this
需要使用到this的话在next里写函数
但是注意每次进入到路由里会重新渲染数据
data(){
return{
msg:0
}
}
,beforeRouterEnter(to,from,next){
next(vm=>{
vm.msg++
})
}
beforeRouteUpdate
路由传入的参数变化触发函数
data(){
return{
msg:0
}
}
,beforeRouterUpdate(to,from,next){
next(vm=>{
vm.msg++
})
}
beforeRouteLeave
离开此页面触发
data(){
return{
msg:0
}
}
,beforeRouterLeave(to,from,next){
}
transition标签
<transition name="goudan">
<router-view class='dachui'/>
transition>
设定一个name在style里面写样式
<style>
.dachui{
transsition: 2s;
}
进入的状态
.goudan-enter{
进入的初始状态
opacity:0;
}
.goudan-enter-active{
进入动画过程中
}
.goudan-enter-to{
进入的结束状态
opacity:1;
}
离开的状态
.goudan-leave{
离开的初始状态
opacity:1;
}
.goudan-leave-to{
离开的结束状态
opacity:0;
}
style>
多了一个store文件
相当于一个仓库, 存储变量
方便组件之间进行通讯
组件都能使用的一些数据
使用方法:
<h2>
{{$store.state.num}}
h2>
<script>
export default {
name:"Home",
methods:{
fn(){//不要这么写 仓库只能使用不能更改
//需要更改就写 方法
this.$store.state.num ++
}
}
}
script>
但是一般这个使用方法名字太长了
可以使用computed方法
computed:{
num(){
return this.$store.state.num
}
}
这样可以直接使用{{num}}
来书写
如果还是麻烦可以用vuex里的mapState
他是一个函数需要执行
函数执行需要传入参数 ,传入你需要的变量 以数组的形式传入
import {mapState} from 'Vuex';
export default {
name:"Home",
computed:mapState(['num','goudan'])
}
mpaState执行之后返回一个对象 ,对象里面是你需要的数据 但是
每个数据是一个函数
所以要写到computed里面
computed里面的变量都是一个函数形式
但是如果你要在computed里写自己的方法就不好写了
可以使用ES6的…解构
computed:{
dachui(){
return 2+"";
},
...mapState(['num','goudan'])
}
相当于computed
getters:{
goudan(state){
return state.num +''//state是上面的vuex里的state
}
}
getters和state的关系相当于computed和data的关系
定义操作state的方法 (里面写同步方法)
mutations:{
addN(state){
state.num ++
}
}
$store.commit
<button @click='$store.commit("addN")'>按钮button>
如果觉得名字太长可以调用mapMutations
在mathods里面挂载
mathods:{
...mapMutations(['addN'])
}
使用:
<button @click='addN(2)'>button>
mutations:{
addN(state,n){
state.num += n
}
}
存放异步操作
actions:{
addAsync(context){
new Promise(req=>{
setTimeout(req,1000);
}).then(()=>{
context.commit('addN')
})
}
}
$store.dispath
方法小范围使用
...mapActions([])
进行使用
将一些状态模块化
将一些定义的变量和相关的额方法写到一个对象里面
const num = {
namespaced:true,
state:{
num:1
},
mutations:{},
actions:{}
}
namespaced创建一个命名空间
可以用一个变量名去接受他
然后添加到modules
里面
modules:{
num:num
}
在导入数据的时候加上名字
mapState('num',['num'])
watch:{
$route(){//watch监听
//监听route的变化
}
}