Title

vue

vue2

引入方式

#CDN的方式引入
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
#下载后导入
其实就是直接在浏览器中打开https://cdn.jsdelivr.net/npm/vue/dist/vue.js,然后复制下来,创建一个js文件再粘贴进去

<script src="./js/vue.js"></script>
7.补充
解释型的语言是需要解释器的
js就是一门解释型语言,只不过js解释器被集成到了浏览器中

所以,在浏览器的Console中输入命令,就和在cmd中输入python后,进入交互式环境一样

nodejs:一门后端语言
把chrome的v8引擎(解释器),安装到操作系统之上

插值语法

#语法:{{ 变量、js语法、三目表达式 }}
只能写在标签内部
<p>{{name}}</p>
#有字符串,数值,数组,对象,字符串,运算

三目运算符   条件?'':''

指令

#只能写在标签上,如<p v-文本指令:"字符串">你好</p>
v-text 纯文本
v-html #在于替换标签的内容, 如果替换字符串中含有html标签元素,会被解析
v-text 和 v-html 的区别
v-text 指令只替换文本内容,如果是HTML代码段也不会被解析;v-html指令在替换文本内容时,如果目标内容不是纯文本,是一段HTML代码段会被浏览器解析渲染。
v-show  #放1个布尔值:为真 标签就显示;为假 标签就不显示
v-if   #放1个布尔值:为真 标签就显示;为假 标签就不显示
'''
v-show 与 v-if 的区别:

v-show:标签还在,只是不显示了(display: none)
v-if:直接操作DOM,删除/插入 标签
'''
v-bind 要给标签的属性绑定动态的值,需要在属性前方加上'v-bind:',也可以简写成':
v-on 格式:v-on:事件名称="事件处理函数的名称" 简写:@事件名称="事件处理函数的名称" 绑定的事件可以用小括号进行传参,若无小括号则默认传触发的事件对象(MouseEvent{}),若在有参数的情况下,仍需获取事件对象,可使用$event符号获取事件对象。(@click="add(n,$event)")不过开发中不常用

Style 和 Class

#语法::属性名="变量/语法"
'''
    :class='js变量、字符串、js数组'
    class:三目运算符、数组、对象{red: true}

    :style='js变量、字符串、js数组'
    style:三目运算符、数组[{backgreound: 'red'},]、对象{background: 'red'}
'''

class 推荐使用数组
style 推荐使用对象

条件渲染

'''
指令	释义
    v-if	相当于: if
    v-else	相当于:else
    v-else-if	相当于:else if
'''

列表渲染

# v-for 遍历数值,对象,数字,字符串

'''
    注意!在Vue中:

    数组的index和value是反的
    对象的key和value也是反的
'''

key值
'''
    在v-for循环数组、对象时,建议在控件/组件/标签写1个key属性,属性值唯一
    页面更新之后,会加速DOM的替换(渲染)
    :key="变量"
'''
<div v-for="item in 8" :key="item">{{item}}</div>

数组的更新与检查

# 1可以检查到的数组变动
'''
    push:最后位置添加
    pop:最后位置删除
    shift:第一个位置删除
    unshift:第一个位置添加
    splice:切片
    sort:排序
    reverse:反转
'''
#2 检测不到变动的数组操作
'''
    filter():过滤
    concat():追加另一个数组
    slice():slice() 方法可从已有的数组中返回选定的元素。方法可提取字符串的某个部分,并以新的字符串返回被提取的部分。
    map():方法返回一个新数组,数组中的元素为原始数组元素调用函数处理后的值。

'''

#slice map 
#不会对空数组进行检测。
#不会改变原始数组。

// 方法1:通过 索引值 更新数组(数据会更新,但是页面不会发生改变)
    vm.arrayList[0]
    "Alan"
    vm.arrayList[0]='Darker'
    "Darker"

// 方法2:通过 Vue.set(对象, index/key, value) 更新数组(数据会更新,页面也会发生改变)
	Vue.set(vm.arrayList, 0, 'Darker')

事件处理

针对于input框
'''
    input	当输入框进行输入的时候 触发的事件
    change	当元素的值发生改变时 触发的事件
    blur	当输入框失去焦点的时候 触发的事件
'''

change 和 blur 最本质的区别:

如果输入框为空,失去焦点后,change不会触发,但是blur会触发
事件修饰符
'''
    .stop	只处理自己的事件,父控件冒泡的事件不处理(阻止事件冒泡)
    .self	只处理自己的事件,子控件冒泡的事件不处理
    .prevent	阻止a链接的跳转
    .once	事件只会触发一次(适用于抽奖页面)
'''
使用修饰符时,顺序很重要;相应的代码会以同样的顺序产生

用 v-on:click.prevent.self 会阻止所有的点击
而 v-on:click.self.prevent 只会阻止对元素自身的点击

''' 
<li v-for="data in dataList" @click.stop="handleLi">{{data}}</li>
'''

按键修饰符

'''
.enter => // enter键
.tab => // tab键
.delete (捕获“删除”和“退格”按键) => // 删除键
.esc => // 取消键
.space => // 空格键
.up => // 上
.down => // 下
.left => // 左
.right => // 右
'''
<input @keyup.enter="submit">

数据双向绑定

#v-model的使用
# input  可以输入值,输入后,就被js变量拿到,如果使用 :value='变量' 这种形式,页面中输入框变化,变量不会变,使用v-model做双向数据绑定

this.newDataList = this.dataList.filter(
                    item => item.indexOf(this.myText) >= 0

表单控制

	text 类型
    radio:单选 #// radio单选,多个radio绑定同一个变量,选中某个,就对应value值
    checkbox:单选和多选 #// checkbox 单选是true或false,checkbox 多选是数组类型,必须一开始定义就是数组,多个checkbox绑定一个变量
    
 <p>性别:
        男:<input type="radio" v-model="gender" value="1">
        女:<input type="radio" v-model="gender" value="2">
        保密:<input type="radio" v-model="gender" value="0">
    </p>
    <p>记住密码: <input type="checkbox" v-model="remember"></p>
    <p>爱好:</p>
    <p>篮球:<input type="checkbox" v-model="hobby" value="1"></p>
    <p>足球:<input type="checkbox" v-model="hobby" value="2"></p>
    <p>乒乓球:<input type="checkbox" v-model="hobby" value="3"></p>========》[ "3", "2", "1" ]

v-model进阶

'''
lazy:等待input框的数据绑定时区焦点之后再变化
number:数字开头,只保留数字,后面的字母不保留;字母开头,都保留
trim:去除首位的空格
'''

fetch

.简介
① fetch介绍
提供了一个 JavaScript 接口,用于访问和操纵 HTTP 管道的一些具体部分,例如请求和响应

它还提供了一个全局 fetch() 方法,该方法提供了一种简单,合理的方式来跨网络异步获取资源

② fetch基本格式
fetch('http://example.com/movies.json')
  .then(function(response) {
    return response.json();
  })
  .then(function(myJson) {
    console.log(myJson);
  });

# fetch 提供了一个 JavaScript 接口,用于访问和操纵 HTTP 管道的一些具体部分,例如请求和响应
	-新的发送ajax 接口
    -用起来比较方便
    -支持promise写法[最新的异步写法]
    -解决了原生的XMLHttpRequest兼容性的问题
    -不是所有浏览器都支持
    -主流现在是用axios[第三方]发送请求
# XMLHttpRequest: 原生js提供的
	-比较老,不同浏览器需要做一些兼容性的处理,写起来比较麻烦
    -jq基于它做了封装

Axios

1.简介
① Axios 是一个基于 promise 的 HTTP 库,可以用在浏览器和 node.js 中
② axios官网:http://www.axios-js.com/
'''
axios.get("http://127.0.0.1:5000/film/").then(res => {
                    console.log(res.data.data.films) // axios 自动包装data属性 res.data
                    this.dataList = res.data.data.films
                }).catch(err => {
                    console.log(err);
                })
'''

计算属性

计算属性是基于它们的依赖进行缓存的

计算属性只有在它的相关依赖发生改变时才会重新求值

计算属性就像Python中的property,可以把方法/函数伪装成属性
'''
omputed: {
            getName() { // 依赖的状态改变了,会重新计算
                return this.myText.substring(0, 1).toUpperCase() + this.myText.substring(1)
            }
        },
'''

虚拟DOM 与diff算法 key的作用

1.Vue2.0 v-for 中 :key 有什么用呢?
'''
分层级比较:只做同层级的对比
通过key值比较:出现新的key就插入同组(循环中,尽量加key,让key值唯一)
通过组件/标签进行比较:然后进行替换
'''

2.虚拟DOM的diff算法
虚拟DOM比对中用到了diff算法,就是做对比找差异,diff算法中有一个很重要的原理就是同级比对,如两个虚拟DOM树中,div1与div1做比对,div2与div2做比对,互不干涉,这样就减少了一个循环查找对应dom节点的一个操作,非常节省性能,提高了页面渲染的效率。

值类型和引用类型

# python
	-不可变类型:数字,字符串,元组
    -可变类型:列表,字典,集合
    -python中没有值类型和引用类型的叫法----【因为python一切皆对象,对象都是地址都是引用】
    -可变类型当参数传到函数中,在函数中修改会影响原来的
    -不可变类型当参数传到函数中,在函数中修改不会影响原来的
    
# python 函数参数传递是值传递还是引用传递? 这个问题不应该有


# js 传入了item 对象,在函数中修改,影响了原来的
	-js 的对象是引用类型

生命周期

img

'''
			beforeCreate	创建Vue实例之前调用
            created	创建Vue实例成功后调用(可以在此处发送异步请求后端数据)
            beforeMount	渲染DOM之前调用
            mounted	渲染DOM之后调用
            beforeUpdate	重新渲染之前调用(数据更新等操作时,控制DOM重新渲染)
            updated	重新渲染完成之后调用
            beforeDestroy	销毁之前调用
            destroyed	销毁之后调用
'''
created ===>let vm = new Vue()
mounted===>挂载,把div挂载到组件中

# 重点:
	-1 用的最多的,created  发送ajax请求----》有的人放在mounted中加载
	-2 beforeDestroy
    	-组件一创建,created中启动一个定时器
        -组件被销毁,beforeDestroy销毁定时器
        
# 实现实时聊天效果(在线聊天室)
	-轮询:定时器+ajax   http:http版本区别
    -长轮询:定时器+ajax  http
    -websocket协议:服务端主动推送消息
    https://zhuanlan.zhihu.com/p/371500343
'''
 created: function () {
            axios.get('http://127.0.0.1:8000/getgood/').then(res => {
                this.good_list = res.data
            })
        }

'''

vue组件

组件化开发

组件就是:扩展 HTML 元素,封装可重用的代码,目的是复用
例如:有一个轮播图,可以在很多页面中使用,一个轮播有js,css,html
组件把js,css,html放到一起,有逻辑,有样式,有html

组件的分类

#全局组件:可以放在根中
#局部组件

组件的注册方式

定义全局组件,绑定事件,编写样式
Vue.component('child', {
    template:})

定义局部组件
var vm = new Vue({
   		...
        components: {
            foo

        }


    })
'''
定义的组件(body中的位置)必须要放在Vue实例(这也是一个组件 根组件)中
局部组件 必须放在 全局组件/根组件 中,无法单独使用
定义的组件必须在Vue实例的上方
'''

-全局组件
    	Vue.component('名字',{template,data(){return {}},methods,生命周期})
        
    -局部组件(只能用在当前组件中)   以后咱们用局部组件用的多
    	components: {
            foo:{}
        }

组件编写方式 与 Vue实例的区别

1 Vue实例(其实,它也是1个组件,是1个根组件)
#区别
1.自定义组件需要有1个 root element,一般包裹在 1个div中
2.父子组件的data是无法共享的
    这一点就像Docker的容器一样,是相互隔离的
    就算父子的data中数据相同,拥有相同的方法,也是互不影响的
3.组件可以有data、methods、computed....,但是 data 必须是一个函数
Vue实例:data是1个键值对,用来存放属性的
组件:data是1个函数,需要有返回值(return)

组件通信

1.父传子
    在全局组件中自定义属性:<global :myname="name" :myage="19"></global>
    在组件中获取:{{myname}}
2 子传父(通过事件)
	3.子传父(控制子组件的显示和隐藏)
	点击子组件,就会触发父组件的某个函数执行

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script src="./js/vue.js"></script>
</head>
<body>
<div class="app">
    <h1>父子通信之父传子,通过自定义属性--->不能用驼峰,不要跟子组件中变量冲突</h1>
    <!--    <h2>字符串的age&ndash;&gt;age="age"</h2>-->
    <!--    <child age="age"></child>-->
    <!--    <h2>:age="19"</h2>-->
    <!--    <child :age="19"></child>-->
    <!--    <h2>age="19"</h2>-->
    <!--    <child age="19"></child>-->
    <!--    <h2>:age="age"</h2>-->
    <child :age="age" myname="彭于晏"></child>

    <h1>属性验证---》传入的必须是xx类型</h1>
    <!--    <h2>字符串的age&ndash;&gt;age="age"</h2>-->
    <!--    <child age="age"></child>-->
    <!--    <h2>:age="19"</h2>-->
    <!--    <child :age="19"></child>-->
    <!--    <h2>age="19"</h2>-->
    <!--    <child age="19"></child>-->
    <!--    <h2>:age="age"</h2>-->
    <!--    <child :age="age"></child>-->


</div>

</body>
<script>
    // 父中有age,子child 只有name,没有age,现在把父中的age传到child中,显示
    var child = {
        template: `
          <div>
          <button>后退</button>
          首页--->名字:{{ myname }}--->年龄:{{ age }}
          <button>前进</button>
          </div>`,
        data() {
            return {
                myname: 'lqz'
            }
        },
        // props: ['age'],
        props: {age: Number, myname: String},
    }
    var vm = new Vue({
        el: '.app',
        data: {
            age: 19
        },
        components: {
            child
        }

    })
</script>
</html>
组件间通信之子传父
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script src="./js/vue.js"></script>
</head>
<body>
<div class="app">
    <p>子组件传递过来的数据: {{mytext}}</p>
    <hr>
    <child @myevent="handleEvent"></child>
    <hr>


</div>

</body>
<script>
    var child = {
        template: `
          <div>
          <input type="text" v-model="mytext">
          <button @click="handleSend">点我传递</button>
          </div>`,
        data() {
            return {
                mytext: ''
            }
        },
        methods: {
            handleSend() {
                // alert(this.mytext)
                // 子组件中,触发自定义事件的执行,会执行父组件自定义事件绑定的函数,有几个参数,就传几个参数
                this.$emit('myevent', this.mytext)
            }
        }

    }


    var vm = new Vue({
        el: '.app',
        data: {
            mytext: ''
        },
        methods: {
            handleEvent(mytext) {
                this.mytext = mytext

            }
        },
        components: {
            child
        }

    })
</script>
</html>

ref属性

-ref放在标签上,拿到的是原生的DOM节点
-ref放在组件上,拿到的是组件对象 ,对象中的数据、函数 都可以直接使用
-通过这种方式实现子传父(this.$refs.mychild.text)
-通过这种方式实现父传子(调用子组件方法传参数)

 // 1 ref 属性放在普通标签上,拿到标签的dom对象
     // 通过this.$refs可以拿到所有标签上写了ref属性的 标签 ,对象类型 key值是ref对应的value值, value值是原生dom对象
      // console.log(this.$refs)
       // 直接修改原生dom对象的value属性,input就能看到有值了
      // this.$refs.myinput.value = 'lqz is handsome'

      //2 ref  属性放在 组件上,拿到的是 组件对象 ,就可以使用组件对象的属性和方法
      // console.log(this.$refs)  // 对象中有3个值,两个普通标签,一个组件
       // this.$refs.mychild   就是组件对象,可以 .属性,  .方法
       // this.age = this.$refs.mychild.age
        // 重点:以后就不需要关注是子传父还是父传子了,直接通过对象取值赋值即可,而且可以主动调用子组件中的函数
事件总线(不同层级的不同组件通信)

img

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>子传父</title>
    <script src="https://cdn.bootcdn.net/ajax/libs/vue/2.6.12/vue.min.js"></script>
</head>
<body>

<div id="box">
    <global1></global1>
    <hr>
    <global2></global2>
</div>

</body>
<script>
    // 定义1个事件总线
    let bus = new Vue({})

    // 组件1
    Vue.component('global1', {
        template: `
            <div>
                <h3>组件1</h3>
                <input type="text" v-model="myText">
                <button @click="handleClick1">点我传递数据到另一个组件</button>
            </div>
        `,
        data() {
            return {
                myText: ''
            }
        },
        methods: {
            handleClick1() {
                console.log(this.myText)
                bus.$emit('any', this.myText)  // 通过事件总线发送
            }
        }
    })
    // 组件2
    Vue.component('global2', {
        template: `
            <div>
                <h3>组件2</h3>
                收到的消息是:{{recvText}}
            </div>
        `,
        data() {
            return {
                recvText: ''
            }
        },
        mounted() { // 组件的挂载(生命周期钩子函数中的1个),开始监听时间总线上的:any
            bus.$on('any', (item) => {
                console.log('收到了', item,)
                this.recvText = item
            })
        },
        methods: {}
    })
    // 父组件
    let vm = new Vue({
        el: '#box',
        data: {},
    })
</script>
</html>

动态组件 component

<component :is="who"></component>
components: {
            home,
            order, goods
        }

keep-alive保持组件不销毁

keep-alive可以让输入框内有的内容一致保持,不会因为切换而重置
<keep-alive>
        <component :is="who"></component>
    </keep-alive>

slot 插槽

一般情况下,编写完1个组件之后,组件的内容都是写死的,需要加数据 只能去组件中修改,扩展性很差
然后就出现了插槽这个概念,只需在组件中添加<slot></slot>,就可以在body的组件标签中添加内容
具名插槽
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>具名插槽</title>
    <script src="https://cdn.bootcdn.net/ajax/libs/vue/2.6.12/vue.min.js"></script>
</head>
<body>

<div id="box">
    <!-- 具名插槽,把p标签给a插槽,div标签给b插槽-->
    <child>
        <p slot="a">我是具名插槽a插入的内容</p>
        <div slot="b">我是具名插槽b插入的内容</div>
    </child>
</div>
</body>
<script>
    Vue.component('child', {
        template: `<div>
            <slot name="a"></slot>
            <hr>
            <span style="border-bottom: 5px solid rgba(255,104,104,0.7)">我是组件的原内容</span>
            <hr>
            <slot name="b"></slot>
        </div>`,

    })
    var vm = new Vue({
        el: '#box',
        data: {}

    })
</script>
</html>

监听属性

# 在data 中定义了一些变量,只要变量发生变化,我们就执行一个函数

watch:{
    属性名(){
        
    }
}
自定义组件   https://www.cnblogs.com/liuqingzheng/articles/17124972.html

vue_cli

环境搭建

- 安装node

官网下载安装包,傻瓜式安装:https://nodejs.org/zh-cn/

- 安装cnpm

npm install -g cnpm --registry=https://registry.npm.taobao.org

- 安装脚手架

cnpm install -g @vue/cli


- 清空缓存处理

npm cache clean --force

项目创建

vue create 项目名
// 要提前进入目标目录(项目应该创建在哪个目录下)
// 选择自定义方式创建项目,选取Router, Vuex插件
//标准eslint,自动修复(ESlint+Standard config--》lint on save+Lint and fix on commit)
vue ui 使用图形界面创建项目

# 解释型语言和编译型语言
	-js,node,php,python    解释型语言   运行解释器之上   pyinstaller
    -c,go,c++               编译型语言   直接把源代码编译成不同平台的可执行文件
    	-cpython解释器用c写的----》编译成不同平台的可执行文件---》在不同平台双击运行即可
        	-win
            -mac
            -linux
    -java:一处编码处处运行
    	-java 虚拟机 ---》虚拟机跨平台
        -java字节码文件运行在虚拟机之上
        -java写了代码----》编译成字节(区别与可执行文件  jar,war,.class)

启动/停止项目

npm run serve / ctrl+c
// 要提前进入项目根目录

打包项目

npm run build
// 要在项目根目录下进行打包操作

package.json中

"scripts": {
    "serve": "vue-cli-service serve",  # 运行项目
    "build": "vue-cli-service build",  # 编译项目成html,css,js
    "lint": "vue-cli-service lint"     # 代码格式化
},

认识项目

dist: 打包的项目目录(打包后会生成)
node_modules: 项目依赖(删掉,不上传git,使用npm install重新安装)
public: 共用资源
	--favicon.ico # 网站小图标
	--index.html:项目入口页面,单页面
src: 项目目标,书写代码的地方
	-- assets:资源
	-- components:组件
	-- views:视图组件
	-- App.vue:根组件
	-- main.js: 入口js
	-- router.js: 路由文件
	-- store.js: 状态库文件# 安装了Vuex,就会有这个文件夹
vue.config.js: 项目配置文件(没有可以自己新建)
package.json:项目配置依赖(等同于python项目的reqirement.txt)
.gitignore             # git的忽略文件,后面学了git就会了

配置文件:vue.config.js

//https://cli.vuejs.org/zh/config/ 配置参考
module.exports={
	devServer: {
		port: 8888
	}
}
// 修改端口,选做

main.js 整个项目入口文件

//es6 模块导入规范,等同于python导包
//commonJs的导入规范:var Vue=require('vue')
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')


/*
new Vue({
	el:'#app' //原来是用el:'#app',现在是new出Vue对象,挂载到#app上---》.$mount('#app')
  render: h => h(App) //原来是在页面上div中写样式,现在组件化开发 把根组件(import App from './App.vue'),通过render渲染上,渲染组件的方式
}).$mount('#app')
*/

vue文件

<template>
    <!-- 模板区域 -->
</template>
<script>
    // 逻辑代码区域
    // 该语法和script绑定出现
  	//export default-->es6的默认导出(导出一个对象),模拟commonJS的导出方式制定的
    export default {
        
    }
</script>
<style scoped>
    /* 样式区域 */
    /* scoped表示这里的样式只适用于组件内部, scoped与style绑定出现 */
</style>

定义组件

#1 新建xx.vue
components-->HelloWorld.vue
#2 引入使用
<script>
	# es6的引入import from 
  import HelloWorld from '@/components/HelloWorld.vue'
  import Vue from 'vue'
  Vue.component('HelloWorld',HelloWorld) # 全局组件
  export default {
     components: { # 局部组件
   		 HelloWorld:HelloWorld
  		},
        
}
</script>

es6导入导出语法

### 看xx.vue 组件学到的重点#########
#  记住,以后开发vue项目,都按照这个模式来
1 新建xx.vue
2 在xx.vue中就三块内容
	#1 以后组件的html内容,都写在这里
	<template>
	</template>
    
    #2 以后该组件使用的样式,都写在这
    <style>
    </style>
    
    # 3 以后js的东西,都写在这
    <script>
	</script>
    
    
    
    
#### main.js 学到的
# 找到index.html 中的id为app的div,以后都在App.vue中写
new Vue({
  render: h => h(App)
}).$mount('#app')


# 导入导出语法
# python  创建包,在其他py文件中导入

# js 从es6开始,也支持包的导入和导出
	### 默认导出语法(用的最多),只能导出一个,一般导出一个对象
	-导出语法
    	export default 一般是个对象
    -导入语法
    	import 别名  from '路径'
        以后 别名   就是 导出的对象
        
        
        
   ###  命名导出导入
	-导出语法  可以导出多个
    	export const name = '彭于晏'
        export const add = (a, b) => {
            console.log(name)
            return a + b
        }
        export const age = 19
        
    -导入语法
    	import {name, add} from './lqz/s1'
        console.log(name)
        console.log(add(33, 44))
        
        
        
        
  ### 导入的简写形式
	-包下的  index.js  导入的时候,不用写到index.js的路径  --->它等同于ptyhon的__init__.py
    -例如:
    	# 包是
    	lqz
          -index.js
        #导入的时候
        	import lqz from './lqz'
            
    	

vue项目编写步骤

# 1 以后只需要写xx.vue   
	-页面组件
    -小组件   给页面组件用的
    
# 2 组件中导出
	export default {
          name: 'HelloWorld',
          data() {
            return {
              xx: '彭于晏'
            }
          },
	}

# 3 在别的组件中要用,导入,注册
	# 导入
	import HelloWorld from '../components/HelloWorld.vue'
    # 注册
    export default {
      components: {
        HelloWorld 
      }
    }
 # 4 注册以后,在这个组件中就可以使用导入的组件 ,写在<template>
	# 自定义属性
	<HelloWorld msg="传进来的p"/>
	

ESLint

ESLint 是一个开源的 JavaScript 代码检查工具,由 Nicholas C. Zakas 于2013年6月创建。代码检查是一种静态的分析,常用于寻找有问题的模式或者代码,并且不依赖于具体的编码风格。对大多数编程语言来说都会有代码检查,一般来说编译程序会内置检查工具。

JavaScript 是一个动态的弱类型语言,在开发中比较容易出错。因为没有编译程序,为了寻找 JavaScript 代码错误通常需要在执行过程中不断调试。像 ESLint 这样的可以让程序员在编码的过程中发现问题而不是在执行的过程中。

ESLint 的初衷是为了让程序员可以创建自己的检测规则。ESLint 的所有规则都被设计成可插入的。ESLint 的默认规则与其他的插件并没有什么区别,规则本身和测试可以依赖于同样的模式。为了便于人们使用,ESLint 内置了一些规则,当然,你可以在使用过程中自定义规则。

ESLint 使用 Node.js 编写,这样既可以有一个快速的运行环境的同时也便于安装
js语法规范性检查,类似于PEP8规范
官网
https://eslint.bootcss.com/docs/about/

使用vue-cli

在vue-cli在init初始化时会询问是否需要添加ESLint,确认之后在创建的项目中就会出现.eslintignore和.eslintrc.js两个文件。

.eslintignore类似Git的.gitignore用来忽略一些文件不使用ESLint检查。
.eslintrc.js是ESLint配置文件,用来设置插件、自定义规则、解析器等配置。

执行:npm run lint 会自动修复代码

配置ESLint

Vue的项目配置eslint还是很简单的。它属于依赖插件中的一种,可以像安装其他插件一样在命令行用npm install eslint -g安装,也可以修改package.json文件去更新项目的依赖包,重新跑一遍npm install就可以了。 eslint常用的依赖有很多,我贴出我用的一些。在package.jsonde 的dependencies或者devDependencies中添加下列属性即可:

"babel-eslint": "^7.1.1",  
"eslint-config-standard": "^6.2.1",  
"eslint-friendly-formatter": "^2.0.7",  
"eslint-loader": "^1.6.1",  
"eslint-plugin-html": "^2.0.0",  
"eslint-plugin-promise": "^3.4.0",  
"eslint-plugin-standard": "^2.0.1",

vue项目中关闭ESLint

时候会被ESLint的报错阻止程序的运行,这时候我们就想关闭这个ESLint了。在vue项目中关闭ESLint方法

关闭方法
在vue.config.js的module.exports下添加如下代码:

// 关闭eslint校验.
	   devServer: {
	      overlay: {
	        warnings: false, //不显示警告
	        errors: false	//不显示错误
	      }
	    },
	    lintOnSave:false //关闭eslint检查
        
方法2 
在package.json中通过eslintConfig配置,示例:

"eslintConfig": {
    "root": true,
    "env": {
      "node": true
    },
    "extends": [
      "plugin:vue/essential",
      "@vue/standard"
    ],
    "rules": {
      "eol-last": [0],
      "semi": [2, "always"], // 强制语句分号结尾
      "indent": [2, 4], // 强制缩进4 spaces
      "no-new": [0], // 不允许new一个实例后不赋值或不比较
      "no-debugger": [0], // 不允许出现debugger语句
      "camelcase": [0, {"properties": "never"}] // 关闭驼峰命名规则
    },
    "parserOptions": {
      "parser": "babel-eslint"
    }
 },
 "eslintIgnore": [
    "dist/*",
    "node_modules/*",
    "build/*",
    "*.md"
 ],

项目功能插件

vue-router

{
    path: '/',
    name: 'home',
    // 路由的重定向
    redirect: '/home'
}

{
    // 一级路由, 在根组件中被渲染, 替换根组件的<router-view/>标签
    path: '/one-view',
    name: 'one',
    component: () => import('./views/OneView.vue')
}

{
    // 多级路由, 在根组件中被渲染, 替换根组件的<router-view/>标签
    path: '/one-view/one-detail',
    component: () => import('./views/OneDetail.vue'),
    // 子路由, 在所属路由指向的组件中被渲染, 替换该组件(OneDetail)的<router-view/>标签
    children: [{
        path: 'show',
        component: () => import('./components/OneShow.vue')
    }]
}
<!-- router-link渲染为a标签 -->
<router-link to="/">Home</router-link> |
<router-link to="/about">About</router-link> |
<router-link :to="{name: 'one'}">One</router-link> |

<!-- 为路由渲染的组件占位 -->
<router-view />
a.router-link-exact-active {
    color: #42b983;
}
// router的逻辑转跳
this.$router.push('/one-view')

// router采用history方式访问上一级
this.$router.go(-1)

vuex

// 在任何一个组件中,均可以通过this.$store.state.msg访问msg的数据
// state永远只能拥有一种状态值
state: {
    msg: "状态管理器"
},
// 让state拥有多个状态值
mutations: {
    // 在一个一个组件中,均可以通过this.$store.commit('setMsg', new_msg)来修改state中的msg
    setMsg(state, new_msg) {
        state.msg = new_msg
    }
},
// 让mutations拥有多个状态值
actions: {

}

vue-cookies

// 安装cookie的命令
// npm install vue-cookies --save
// 为项目配置全局vue-cookie
import VueCookies from 'vue-cookies'
// 将插件设置给Vue原型,作为全局的属性,在任何地方都可以通过this.$cookie进行访问
Vue.prototype.$cookies = VueCookies
// 持久化存储val的值到cookie中
this.$cookies.set('val', this.val, 300)
// 获取cookie中val字段值
this.$cookies.get('val')
// 删除cookie键值对
this.$cookies.remove('val')

axios

import axios from 'axios' # 安装的模块不用加相对路径

axios.get().then()
// 安装 axios(ajax)的命令
// npm install axios--save
// 为项目配置全局axios
import Axios from 'axios'
Vue.prototype.$ajax = Axios
let _this = this
this.$ajax({
    method: 'post',
    url: 'http://127.0.0.1:5000/loginAction',
    params: {
        usr: this.usr,
        ps: this.ps
    }
}).then(function(res) {
    // this代表的是回调then这个方法的调用者(axios插件),也就是发生了this的重指向
    // 要更新页面的title变量,title属于vue实例
    // res为回调的对象,该对象的data属性就是后台返回的数据
    _this.title = res.data
}).catch(function(err) {
    window.console.log(err)
})
# 用pycharm启动该文件模拟后台
from flask import Flask, request, render_template
from flask_cors import CORS
app = Flask(__name__)
CORS(app, supports_credentials=True)

@app.route('/')
def index():
    return "<h1>主页</h1>"

@app.route('/loginAction', methods=['GET', 'POST'])
def test_action():
    # print(request.args)
    # print(request.form)
    # print(request.values)
    usr = request.args['usr']
    ps = request.args['ps']
    if usr != 'abc' or ps != '123':
        return 'login failed'
    return 'login success'


if __name__ == '__main__':
    app.run()

跨域问题解决

1 装模块
	pip3 install django-cors-headers -i https://pypi.tuna.tsinghua.edu.cn/simple/

2 注册app
	'corsheaders'
3 中间件修改
	'corsheaders.middleware.CorsMiddleware',
4 修改配置文件
CORS_ORIGIN_ALLOW_ALL = True
CORS_ALLOW_METHODS = (
	'DELETE',
	'GET',
	'OPTIONS',
	'PATCH',
	'POST',
	'PUT',
	'VIEW',
)

CORS_ALLOW_HEADERS = (
	'XMLHttpRequest',
	'X_FILENAME',
	'accept-encoding',
	'authorization',
	'content-type',
	'dnt',
	'origin',
	'user-agent',
	'x-csrftoken',
	'x-requested-with',
	'Pragma',
	'token'
)

组件中

import axios from 'axios'
mounted () {
  axios.get('ajax/moreClassicList?sortId=1&showType=3').then(res => {
    console.log(res.data)
  })
}
```07-Vue插件

热门组件库

1 使用第三方插件
https://github.com/vuejs/awesome-vue#components--libraries

集合了来自社区贡献的数以千计的插件和库。
2 使用第三方UI框架
饿了么UED团队推出的vue 前端框架:

PC框架:
(element UI , iview)

element UI 官网:http://element.eleme.io/

element UI github:https://github.com/ElemeFE/element

移动端框架:
(mint UI)

mint UI官网:https://mint-ui.github.io/docs/

mint UI github:https://github.com/ElemeFE/mint-ui

混入mixin

# 可以把多个组件共用的配置提取成一个混入对象


# 使用步骤:
	1 定义混入对象,新建mixin包,下新建index.js
    2 在 index.js中写 代码(组件中会用到的,data,methods。。。配置项)
        export const lqz = {
            methods: {
                showName() {
                    alert(this.name);   // 没有this.name
                },
            },
            mounted() {
                console.log("你好啊!,页面挂在执行");
            },
        }
   3 局部使用(只在当前组件中使用)
	import {lqz} from '@/mixin'
    # 配置项
    mixins: [lqz]

   4 全局使用(所有组件都可以用) main.js中
	import {lqz} from '@/mixin'
    Vue.mixin(lqz)
    // Vue.mixin(lqz2)
    // Vue.mixin(lqz3)
    
    	
        
   5 在组件中,直接使用即可
	

插件

功能:用于增强Vue,
本质:包含install方法的一个对象,install的第一个参数是Vue,第二个以后的参数是插件使用者传递的数据

# 使用步骤
	1 新建包plugins,新建index.js
    import Vue from "vue";
    import axios from "axios";
    export default {
        install(vue) {
            console.log('执行了插件', vue)
            # 可以做的事
            #  1 了解,自定义指令(不了解没关系)
            #  2 定义全局变量,以后在任何组件中都可以使用到,借助于Vue.prototype往里放 ,以后所有组件只要this.$ajax  就是axios对象
            #  3 使用全局混入
            #  4 自定义全局组件
        }
    }
    
    2 在main.js 中配置
   	# 使用自定义插件
    import plugin from '@/plugins'
    Vue.use(plugin)
    

elementui使用(重点)

# 在vue上,css样式,用的最多的是elementui,但是还有其他的
	-elementui        做网页端 样式用的多  vue2的 饿了吗团队开发的
    -elementui-plus   第三方团队继续基于vue3写的
    -vant             做app的样式
    -iview            pc端用www.iviewui.com
    
    
    
# elementui的使用
	1 安装
    	cnpm i element-ui -S
    2 配置完整引入  在 main.js 中写入以下内容
        import ElementUI from 'element-ui';
        import 'element-ui/lib/theme-chalk/index.css';
        Vue.use(ElementUI)  // 以后在咱们组件中直接使用elementui提供的全局组件即可
	3 在组件中使用
    	-去官网看到好的,复制贴到你的项目中
        

vuex

# 在Vue中实现集中式状态(数据)管理的一个Vue插件,对vue应用中多个组件的共享状态进行集中式的管理(读/写),也是一种组件间通信的方式,且适用于任意组件间通信


# 使用步骤
	1 安装,新建store/index.js

    2 在index.js 中写
        export default new Vuex.Store({
            state: {
                # 放数据
            },

            mutations: {
                # 放方法,正常是让actions中来调用
                # 组件也可以直接调用

            },
            actions: {
                # 放方法,正常组件调用
            }
        })
        
     3 在组件中
    	-显示state的变量
        html中:
          {{$store.state.变量名}}
        js中:
        	this.$store.state.变量面
        改state中的值
        	-推荐按正常步骤---》this.$store.dispatch('actions中的方法',参数)---》actions中的方法调用 context.commit('mutations',参数)---》在mutations中直接修改state的值
            -可以跨过任何一步
            	this.$store.commit()
                this.$store.state.变量名

vue Router

# 第三方插件,用来实现SPA 的vue 插件,
	-单页面应用---》实现在一个index.html 中有页面跳转效果的 插件
    -路由控制
    -<router-link>   跳转用
    -<router-view/>  替换页面组件用
    
#1 基本使用
	-1 创建vue项目时加入了,直接用即可
    	-如果之前没装:先下载,在项目中创建router包,写个index.js,代码copy过来,main.js 写一下
        
    -2 配置路由的跳转(跳转页面组件),只需要在routes数组中写对象即可
    	const routes = [
            {
                path: '/',
                name: 'index',
                component: Index
            },
            {
                path: '/home',
                name: 'home',
                component: Home
            }
        ]
    -3 一定要写个视图组件 Home
   


#2 点击跳转路由两种方式
	-js控制
    	this.$router.push('路径')
    -标签控制
        <router-link to="/home">
          <button>点我跳转到home页面</button>
        </router-link>
    
#3 路由跳转,携带数据的两种方式
	-1 /course/?pk=1  带在路径中使用 ? 携带  
    -2 /course/1/     路径中分割的
    
    -1 第一种方式:/course/?pk=1
    	this.$route.query.pk
    -2 第二种方式:/course/1/ 
    	- router/index中路径得改
             {
                path: '/login/:id',
                name: 'login',
                component: Login
            },
        -this.$route.params.id
    
    
    
    
#4 区分this.$route  this.$router
    -this.$router #   new VueRouter对象,实例,可以实现路由的跳转
    -this.$route  #   是当前路由对象,内部有传入的参数
    
    
    
    
# 5 两种跳转方式,使用对象方式
	-this.$router.push({
        name: 'login',
        // query: {
        //   name: 'lqz',
        //   age: 19
        // },
        params: {
          id: 88
        }
      }) # 这里可以写个对象
    
    
    -标签形式跳转,传对象形式
    <router-link :to="{name: 'login', query: {name: 'lqz'}, params: {id: 999}}">
      <button>点我跳转到home页面</button>
    </router-link>
    
    
    
    
 # 6 路由守卫--->
	全局守卫
        -前置路由守卫:在进路由前,执行代码
        -后置路由守卫:路由跳转走,执行代码
        
        
    如何用:router/index.js 加入
    // 全局前置路由守卫--->任意路由跳转都会触发它的执行
router.beforeEach((to, from, next) => {
    // to 是去哪,哪个路由对象
    // from 是来自哪,是哪个路由对象  比如从  /--->/login
    // next 是函数,如果加括号执行,就会真正的过去
    console.log('前置路由守卫', to, from, next)
    // next() // 真正跳转到 要去的路径

    if (to.name == 'login') {
        console.log('走了')
        next()
    } else {
        var res = localStorage.getItem('userinfo')
        if (res) {
            next()
        } else {
            alert('您没有登录')
            // 跳转到login--->没有解决---》你们搜一下如何解决
            // console.log(this)
            // router.push('/login')
        }
    }
})

localStorage系列

# 都是在浏览器存储数据的--》存数据有什么用?
	-登录成功 token存在本地
    -不登录加入购物车功能,迪卡侬存在了localStorage中
    -组件间通信----》 跨组件
    
# localStorage
	-永久存储,除非清空缓存,手动删除,代码删除
    -localStorage.setItem('userinfo', JSON.stringify(this.userInfo))
    -localStorage.getItem('userinfo')
    -localStorage.clear()  // 清空全部
    -localStorage.removeItem('userinfo') 
# sessionStorage
	-关闭浏览器,自动清理
    -sessionStorage.setItem('userinfo', JSON.stringify(this.userInfo))
    -sessionStorage.getItem('userinfo')
    -sessionStorage.clear()  // 清空全部
    -sessionStorage.removeItem('userinfo') 
# cookie  
	-有过期时间,到过期时间自动清理
    -借助于第三方 vue-cookies
    -cookies.set('userinfo', JSON.stringify(this.userInfo))
    -cookies.get('userinfo')
    -cookies.delete('userinfo')
    

1 vue3 介绍

# 1 vue项目的版本,新项目使用vue3,有部分老项目使用vue2

# vue3 的变化
    1.性能的提升
    	-打包大小减少41%
    	-初次渲染快55%, 更新渲染快133%
    	-内存减少54%
    2.源码的升级
    	使用Proxy代替defineProperty实现响应式
    	重写虚拟DOM的实现和Tree-Shaking
    3.拥抱TypeScript
    	Vue3可以更好的支持TypeScript
    4.新的特性
    	Composition API(组合API)
        setup配置
        ref与reactive
        watch与watchEffect
        provide与inject
        新的内置组件
        Fragment
        Teleport
        Suspense
        其他改变

        新的生命周期钩子
        data 选项应始终被声明为一个函数
        移除keyCode支持作为 v-on 的修饰符
        
        
        
 # 组合式API和配置项API
	vue2 :配置项API
         new Vue({
             el:'#app',
             data:{}
         })
        
    vue3: 组合式API
        let name='lqz'
        let add=()=>{ 
        }

2 vue3 创建项目

2.1 使用vue-cli

# 创建跟之前vue2 一样,只是选择vue版本的时候,选择vue3

# 创建完成,使用pycharm打开,并运行

2.2 vite

# 新建的前端构建工具,最大的优势就是速度快
	https://cn.vuejs.org/guide/scaling-up/tooling.html#project-scaffolding
        
        
# 使用步骤:
	- 安装 :npm init vue@latest
    	-按需选择,vueRouter
    - cd到项目中执行cnpm install 把依赖装好
    -运行:npm run dev
    
    
    
    
    -vueRouter:跟之前一样
    -Pinia:用来替换Vuex的,新一代的状态管理器
    -链式调用(抽时间)
    
    
    
# 为什么这么快
	-创建项目快----》不安装第三方依赖
    -执行项目,热更新----》按需编译

3 setup函数

# 把项目做成最简洁的

# vue2的创建vue实例和vue3创建vue实例的区别

	-new Vew()---->是Vue的实例,里面有$store,$refs...
    -createApp(App)--->是个对象,对象里有东西,没有$store,$refs...,以后有用,都是导入使用

    
# 以后vue3 的<template>,不需要写一个标签了


# 以后都写在setup函数中,定义变量,定义函数,一定要return,在templage中才能使用
# 但是失去了响应式

4 ref和reactive

# 有响应式
	-以后定义变量,如果想有响应式就用 ref包裹起来,再修改变量,需要用 变量名.value 修改
    
# 配置项api和组合式api可以混写,不建议
	-在前在data中定义的变量
    -在setup中定义的变量
    
    -总结:
    	在setup中定义的变量和函数,在之前配置项api中可以直接使用this.变量,函数调用即可
    	但是在原来配置项中定义的变量,函数,在setup中无法使用
        
        
        
# 不同类型做响应式
	ref通常用来包裹,数字,字符串类型,以后使用  xx.value
    reactive用来包裹数组和对象类型    以后使用  直接用即可
    
# 总结  
ref定义的数据:操作数据需要.value,读取数据时模板中直接读取不需要.value。
reactive定义的数据:操作数据与读取数据:均不需要.value

5 计算属性和监听属性

5.1 计算属性

# computed 的配置项中的写法,不建议用了
	computed:{
        fullName(){
          return this.firstName+this.lastName
        }
      },
    
    
 # vue3 新写法
	let person = reactive({
      firstName: '',
      lastName: '',
    })
   let fullName = computed(() => {
    return person.firstName + person.lastName
    })


# 计算属性取值和修改值
    let fullName = computed({
      get() {
        return person.firstName + person.lastName
      },
      set(value) {
        person.firstName = value.slice(0, 1)
        person.lastName = value.slice(1)
      },
    })

5.2 监听属性

# 组合式api写法,只要name发生变化,就会触发匿名函数执行
   let name = ref('lqz')
   watch(name, (newName, oldName) => {
      console.log('name变了')
      console.log('老的', oldName)
      console.log('新的', newName)
    })

# watchEffect 用法,只要age变化,就会执行,age不变化,就不会执行
    watchEffect(() => {
      console.log(age.value)
    })

6 生命周期

# vue3的变化,不推荐了
	-vue2       和    vue3比较
    beforeCreate===>beforeCreate
    created=======>created
    beforeMount ===>beforeMount
    mounted=======>mounted
    beforeUpdate===>beforeUpdate
    updated =======>updated
    beforeDestroy ==>beforeUnmount
    destroyed =====>unmounted
    
    
    
# 不推荐用这种写法了,配置项写法,统统写在setup中
    beforeCreate===>setup()
    created=======>setup()
    beforeMount ===>onBeforeMount
    mounted=======>onMounted
    beforeUpdate===>onBeforeUpdate
    updated =======>onUpdated
    beforeUnmount ==>onBeforeUnmount
    unmounted =====>onUnmounted
    
    
    
 # 以前写在created中的代码,现在直接写在setup开始即可
 let show = ref(false)
 axios.get().then(res=>{
      show.value=res.data.show
 })

7 toRefs

# 以后setup的返回值可以直接使用
  setup() {
    let data = reactive({
      name: 'lqz',
      age: 19,
      gender: '男'
    })
    return {...toRefs(data)}
  }
# 以后在模板中直接用  {{name}}

8 script setup的作用和lang=ts

<script setup>
import {ref} from 'vue'
let name = ref('lqz')
let handleClick = () => {
  alert('美女')
}
</script>

# 以后 这个script中的代码直接放到 setup函数中,不用return了

#lang=ts
里面代码使用ts写,而ts完全兼容js,继续写js代码没问题

8 vue后台管理模板

# 公司内部项目,会写后台管理,往上有很多vue开源的后台管理的框架,咱们只需要在上面做二次开发

# django-vue-admin 前端---》D2Admin 
# 若依:vue前端  用来   vue-element-admin
# elamin前端   drf  写了基于rbac权限管理的框架

# https://gitee.com/liuqingzheng/vue_admin
posted @ 2023-09-07 18:34  哈哈哈哼  阅读(17)  评论(0编辑  收藏  举报