"less": "^4.0.0",
"less-loader": "^7.0.0", (8以下均可)
1.template中的内容必须包含在一个div中。
2.组件名称渲染时不可为HTML标签,例如header、footer等等
如需使用,只要和标签名不一样就行,比如Header、Footer等等
1.vdata
data() {
return {
key: value
}
},
2.vcomputed
computed: {
name() {
return this.data;
}
},
https://blog.csdn.net/wang_xiao_ye/article/details/89385023
Vue全面知识点速查
:https://blog.csdn.net/qq_44317018/article/details/104146747
原理:
(1). 首次加载页面内容时,会用data中同名变量的初始值代替{{变量名}}位置
(2). 当data中同名变量在new Vue()中被更改时,自动更新{{变量名}}位置为新值
{{}}中可以放什么,不能放什么
(1). 可以放: 变量,表达式,有返回值的函数调用,创建对象,访问数组元素,三目运算
(2). 不能放: 程序结构(分支和循环),没有返回值的函数调用
根据表达式的值的 truthiness 来有条件地渲染元素。在切换时元素及它的数据绑定 / 组件被销毁并重建
。如果元素是 ,将提出它的内容作为条件块。
<el-form-item label="会员模型" v-if="modelForm.modelType===1">
<el-checkbox-group v-model="modelForm.modelTypes">
<el-checkbox :label="2" name="modelTypes">月会员</el-checkbox>
<el-checkbox :label="3" name="modelTypes">年会员</el-checkbox>
</el-checkbox-group>
</el-form-item>
modelForm{
modelTypes:[]
}
当元素隐藏时,modelForm.modelTypes会被重置为初始值 (没有设置初始值会被重置为null)
如果元素的属性值希望动态改变:
(1). 问题: 不能用{{}}绑定
(2). 解决: 应该用v-bind指令:
a. 标准写法: <元素 v-bind:属性名="JavaScript表达式
"> 这里常用函数、赋值操作
b. 强调: 一定不要加{{}},属性名前加v-bind:,=后的"“就扮演了{{}}的角色!{{}}中能写什么,此时" "中就能写什么!
c. 简写: 其实v-bind可省略!但是:不能省略!<元素:属性名=“js表达式”>
字符串拼接 外双内单或者发过来也可以
v-on
绑定事件 缩写@
v-bind
绑定属性 缩写:
英文冒号
属性前加一个英文冒号:src="imgURL"
会把字符串变成变量
例如:自定义属性="true"
此时true为布尔值
a. 标准写法: <元素 v-on:属性名="JavaScript表达式
"> 这里常用函数、赋值操作
b. 强调: 一定不要加{{}},属性名前加v-on:,=后的"“就扮演了{{}}的角色!{{}}中能写什么,此时" "中就能写什么!
https://www.cnblogs.com/mark5/p/11603428.html
v-model本质上是一个语法糖。如下代码 {{ test}}本质上是
,其中@input是对输入事件的一个监听,:value="test"是将监听事件中的数据放入到input,
下面代码是v-model的一个简单的例子。在这边需要强调一点,v-model不仅可以给input赋值还可以获取input中的数据,而且数据的获取是实时的,因为语法糖中是用@input对输入框进行监听的。可以在如下div中加入
获取input数据,然后去修改input中数据会发现中数据随之改变。
<div id="app">
<input v-model="test">
<input :value="test" @input="test= $event.target.value">
<p>{{ test}}p>
div>
<script src="/resources/js/vue.js">script>
<script>
new Vue({
el: '#app',
data: {
test: '这是一个测试'
}
});
script>
(5) 坑: 如果v-for遍历的是数组时,在程序中通过下标修改数组元素值,页面上的HTML元素不会自动更改!
比如: this.teachers[0]=“燕儿” 页面上是不会变的!
因为数组中的数字类型的下标012…无法添加访问器属性,也就不受监控!
解决: 今后,vue中修改数组中的元素值!必须用数组相关的函数(push,pop),才能自动更新页面。因为函数都是受监控的。
比如: this.teachers.splice(0,1,“燕儿”)
删除0位置的1个元素,再在0位置放入"燕儿"
结果: 页面会自动变化!
$event
是vue提供的特殊变量,用来表示原生的事件参数对象 event
。$event可以解决事件参数对象 event
被覆盖的问题。
// 传递参数获取到当前元素
//原生js
//this指向当前元素
在onclick = "fn(this)"
//Vue中使用方法 顺序不强制要求,但建议第一个为$event
v-on:click="fn($event,parm)"
无参数时 fn($event) 与 fn 作用一样
fn 默认会传一个 $event 参数
methods: {
fn: function (e,value) {
// 当前html元素
e.currentTarget; // 点击事件绑定在哪一个元素上,currentTarget获取到的就是哪一个元素。
e.target // 当前点击的是哪一个元素,target获取到的就是哪一个元素
// 变成DOM元素
$dom=$(e.currentTarget)
}
}
如果是表单元素
例如checkbox
<input type="checkbox" @change="onCheckBoxChange">
onCheckBoxChange(e){
e.target.checked // true / false
}
一般来讲,获取DOM元素,需document.querySelector(".input1") 获取这个dom节点,然后在获取input1的值。
但是用ref绑定之后,我们就不需要在获取dom节点了,直接在上面的input上绑定input1,然后$refs里面调用就行。
然后在javascript里面这样调用:this.$refs.input1这样就可以减少获取dom节点的消耗了
<div id="app">
<input type="text" ref="input1"/>
<button @click="add">添加</button>
</div>
<script>
new Vue({
el: "#app",
methods:{
add:function(){
this.$refs.input1.value ="22"; //this.$refs.input1 减少获取dom节点的消耗
}
}
})
</script>
更多用法
https://www.jianshu.com/p/899b684174a5
应用场景:在父组件中直接调用子组件的方法
https://www.cnblogs.com/yuzhongyu/p/10825824.html
webpack资源处理的规则,分为相对路径,没有前缀的路径,带~的路径,相对根目录的路径
1.相对路径: "./assets/logo_blue.png"
2.没有前缀的路径 "assets/logo_blue.png" 被webpack解析为相对路径
常用
3.带~的路径 "~@/assets/theme/logo_blue.png" 被webpack解析为 require(src/assets/theme/logo_blue.png) 动态引入
@在webpack 被resolve.alias配置下等价于/src
4.相对根目录的路径 "/assets/logo_blue.png" webpack不解析
vue-cli项目中使用别名:“@”和“~”的坑:https://blog.csdn.net/weixin_42060658/article/details/103654249
watch: {
$route: 'getAllGoods' // 监听路径改变 参数为字符串 写函数名即可
},
method:{
getAllGoods(){
}
}
mutation 改变 mutation 都是同步事务
Action 类似于 mutation,不同在于:
Action 提交的是 mutation,而不是直接变更状态。
Action 可以包含任意异步操作。
mapState 函数返回的是一个对象。
...
是扩展运算符
// 在单独构建的版本中辅助函数为 Vuex.mapState
import { mapState } from 'vuex'
computed:{
// 使用对象展开运算符将此对象混入到外部对象中
...mapState({
// 需要的属性
})
}
示例:
computed:{
//映射哪些字段就填入哪些字段
...mapState(['nickname','age','gender'])
}
computed:{
// 那一句代码就相当于下面这些
nickname(){return this.$store.state.nickname}
age(){return this.$store.state.age}
gender(){return this.$store.state.gender}
}
method:{
//等同于this.$store.commit('ADD')
...mapMutations(['ADD']),
addNum(){
//等同于this.$store.commit('ADD',{num:1})
this.ADD({num:1})
}
}
图文:https://junshuai.blog.csdn.net/article/details/105699705
$route
是代表处于激活状态的路由官方文档:https://router.vuejs.org/zh/api/#%E8%B7%AF%E7%94%B1%E5%AF%B9%E8%B1%A1%E5%B1%9E%E6%80%A7
$route获取的是当前url地址的信息,通过$route可以拿到的数据包括
fullPath: "/Namevue/test" // 包含查询参数和 hash 的完整路径。
router: "" //路由规则所属的路由器
name: "Namevue" //当前路径的名字,如果没有使用具名路径,则名字为空
// params传递参数需要在路由文件中进行配置,例如 path: detail/:id"
params: {id: "test"} //路由中的定义的动态片段和全匹配片段的键值对
path: "/Namevue/test" //当前路由对象的路径,会被解析为绝对路径,如 "/home/news"
query: {} //路由中查询参数的键值对。例如,对于 /home/01?favorite=yes ,会得到$route.query.favorite == ‘yes‘ 。
hash //当前路由的 hash 值 (带 #) ,如果没有 hash 值,则为空字符串。
matched 类型: Array<RouteRecord>
一个数组,包含当前路由的所有嵌套路径片段的路由记录。
路由记录就是 routes 配置数组中的对象副本 (包括 children 和 meta** )。
可以控制台输出看一下有什么参数
redirectedFrom 如果存在重定向,即为重定向来源的路由的名字
***
meta 元数据字段,我们可以在这里配置一些自定义信息,例如网页标题
一般配合路由跳转使用
https://www.cnblogs.com/yuxi2018/p/11967281.html
$router
官方文档:https://router.vuejs.org/zh/guide/advanced/navigation-guards.html
https://router.vuejs.org/zh/guide/advanced/meta.html
// router
{
path: '/user',
name: 'User',
component: () => import('../views/user/User'),
meta:{
// 自定义参数
auth:true
}
}
// main.js
// 守卫
router.beforeEach((to,from,next)=>{
// 和路由的meta自定义参数对应
// some() 方法会依次执行数组的每个元素,第一个参数为数组里面的元素
if (to.matched.some(item=> item.meta.auth)){
// 未登录
next({
path:'/login',
query:{
redirect:to.fullPath
}
})
}else{
next() // 放行
}
})
meta
在方法中使用$route
前面是需要加this
的,在元素中使用是不用加
元素中
<el-button type="primary" @click="$router.push({path: '/role'})">权限管理el-button>
方法中
<el-button type="primary" @click="skip">权限管理el-button>
method:{
skip() {
this.$router.push({path: '/role'})
},
}
(1)路由的跳转
根据路由名字跳转 this.$router.push({name:'B'})
根据路由路径跳转 this.$router.push({path:'/B'})
简写:this.$router.push('/B')
嵌套路由
{
path: '/user',
component: User,
children: [
{
path: 'profile',
component: UserProfile
},
{
path: 'posts',
component: UserPosts
}
]
}
1.user/profile内跳转到posts
this.$router.push({path:'posts'}) // 不用加父路径
(2)路由的跳转并传参
参考:https://www.cnblogs.com/fanfanZhao/p/12203152.html vue的params和query两种传参方式及URL的显示
解释:前台和后台的数据交互。前台各个组件之间的数据传递。
发送数据 this.$router.push({name:'B',params:{a:1,b:2}})
接收数据 `this.$route.params.a` `this.$route.params.b`
简写:this.$router.push('/user/' + this.userId)
实例1:参数值在url中显示
首先需要对应路由配置如下:
{
path: '/user/:id',
name: 'user', // 组件别名
component: user // 组件名
}
const userId = '123'
router.push({ name: 'user', params: { userId }}) // -> /user/123
简写 router.push({ path: `/user/${userId}` }) // -> /user/123 最常用
接收数据 `this.$route.params.userId `
实例2:参数值不在url中显示
不需要修改路由
const userId = '123'
router.push({ name: 'user', params: { userId }}) // -> /user
// 这种方式不行 router.push({ path: `/user/${userId}` })
接收数据 `this.$route.params.userId `
缺点:刷新会丢失数据
注意:如果提供了path,params 会被忽略。这个规则也适用于 router-link 组件的 to 属性。
因为params只能用name来引入路由,如果这里写成了path,接收参数页面会是undefined!!!
// 这里的 params 不生效
router.push({ path: '/user', params: { userId }})
发送数据 路径为 B?c=3&d=4
this.$router.push({
path:'/B',
query:{c:3,d:4}
})
接收数据代码如下
this.$route.query.c,
this.$route.query.d
vue实例中data使用return包裹
https://blog.csdn.net/fengjingyu168/article/details/72900624
为何在大型项目中data需要使用return返回数据呢?
:style 的对象语法十分直观——看着非常像 CSS,但其实是一个 JavaScript 对象。CSS property 名可以用驼
峰式 (camelCase) 或短横线分隔 (kebab-case,记得用引号括起来) 来命名:
class 可以与 :class 共存
:class="{'active':true}"
data(){
question: '',
answer: 'I cannot give you an answer until you ask a question!'
},
watch: {
// 如果 `question` 发生改变,这个函数就会运行
// 参数:新值,旧值(非必须)
question: function (newQuestion, oldQuestion) {
this.answer = 'Waiting for you to stop typing...'
this.debouncedGetAnswer()
}
},
默认情况下,组件在初次加载完毕后不会调用 watch 侦听器。如果想让 watch 侦听器立即被调用,则需要使用 immediate 选项。实例代码如下:
当 watch 侦听的是一个对象,如果对象中的属性值发生了变化,则无法被监听到。此时需要使用 deep 选项,代码示例如下:
(对象中的任意一个属性值发生了变化都会触发)
beforeCreate 实例创建前
created 实例创建完毕之后
beforeMount 实例渲染前(挂载)(此时无法找到任何模版DOM节点)
mounted 实例渲染完毕之后(挂载)
beforeUpdate 实例更新前
updated 实例更新完毕之后
beforeDestroy 实例销毁前
destroyed 实例销毁完毕
来源:https://segmentfault.com/a/1190000011381906
对象里面的函数
methods: {
add: function () {
console.log("add")
this.counter++
},
// ES6 语法
sub() {
console.log("sub")
this.counter--
}
}
父组件与子组件其实是一个相对的概念,你可以把它理解包含与被包含的关系,被包含的自定义标签元素称为子组件,根实例下的模板的内容是父组件,可以对比以前写html的时候,元素嵌套那种层级关系。
而通过全局注册(Vue.component(tagName, options))或者局部注册,自定义标签元素的是子组件,在根实例的作用域范围内,父实例的模块中以自定义元素 调用子组件进行使用,要注意的是确保在初始化根实例之前,注册了子组件
兄弟组件:同级关系的自定义标签元素在父模板中进行使用称为为兄弟组件
来源:https://www.jianshu.com/p/af9cb05bfbaf
简单的父子组件传值
https://www.cnblogs.com/phermis/p/10710894.html
https://www.cnblogs.com/leslie1943/p/13359456.html
https://www.cnblogs.com/lhuser/p/11269546.html
v-bind只能实现单向绑定
v-model(v-bind+触发的input事件)实现双向绑定
.sync
修饰符props中的属性都是只读
的,千万不要用v-model绑定props属性
正确的做法:将 props 的初始值转存到 data 中,因为 data 中的数据是可读可写的!用v-model绑定data属性
在 JavaScript 中对象和数组是通过引用
传入的,所以对于一个数组或对象类型的 prop 来说,在子组件中改变变更这个对象或数组本身将会影响到父组件的状态。
https://www.bilibili.com/video/BV1zq4y1p7ga?p=415
兄弟组件之间实现数据共享的方案是EventBus
。可以借助于第三方的包 mitt 来创建 eventBus 对象,从而实现兄弟组件之间的数据共享。示意图如下
下载
3.2 创建公共的 EventBus 模块
在项目中创建公共的 eventBus 模块如下:
3.3 在数据接收方自定义事件
在数据接收方,调用 bus.on(‘事件名称’, 事件处理函数) 方法注册一个自定义事件。示例代码如下:
注意
: 一定要写在created函数内
3.4 在数据接发送方触发事件
在数据发送方,调用 bus.emit(‘事件名称’, 要发送的数据) 方法触发自定义事件。示例代码如下:
注意
: 一定要写在created函数内
https://www.bilibili.com/video/BV1zq4y1p7ga?p=417
后代关系组件之间共享数据,指的是父节点的组件向其子孙组件共享数据。此时组件之间的嵌套关系比较复杂,
可以使用 provide 和 inject 实现后代关系组件之间的数据共享。
provide 提供数据
inject 接受数据
4.1 父节点通过 provide 共享数据
父节点的组件可以通过provide 方法,对其子孙组件共享数据:
4.2 子孙节点通过 inject 接收数据
子孙节点可以使用 inject 数组,接收父级节点向下共享的数据。示例代码如下:
4.3 父节点对外共享响应式的数据
父节点使用 provide 向下共享数据时,可以结合computed
函数向下共享响应式的数据。示例代码如下:
4.4 子孙节点使用响应式的数据
如果父级节点共享的是响应式的数据,则子孙节点必须以.value
的形式进行使用。示例代码如下:
:router="true"
可以简写为router
ref
相当于取别名 一般命名为:xxxRef
不建议使用.vue
文件
请求可以使用 jquery、axios(推荐)
最好自己在request.js
封装一下 请求的方法和格式
index.html
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>indextitle>
<script src="js/jquery-3.5.1.js">script>
<script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js">script>
head>
<body>
<div id="app">
<div style="background: red">{{ name }}div>
div>
body>
<script src="js/request.js">script>
<script>
var app = new Vue({
el: "#app",
data: { // 这里最好写上所有需要的参数
name: "123",
},
created() {
this.getName();
},
methods: {
getName() {
this.name = sendGet();
},
},
});
app.getName(); // 调用vue中的方法
script>
html>
request.js
/*
静态项目不能这样引入外部js插件,如jquery、axios、qs等等,因为这些插件没有导出
The requested module '../js/jquery.js' does not provide an export named 'default'
需要在每个html中使用引入
import $ from "/js/jquery.js";
*/
/*
js/my.js
let obj = {
click: function () {
console.log("click me");
},
name: "jane",
};
export { obj };
自定义js有导出的可以
import obj from 'js/my.js'
*/
// 模拟返回服务器数据
function sendGet() {
return "江帆啊";
}
不建议这样,建议直接使用vue重构
v-slot:
header , #
header默认有一个v-slot:default
/ #default
infomation对象赋值给info变量,然后scope获取到 info对象并把其作为一个值
scope:{
info:{…}
}
App.vue输出:info{…}
解构
传递多个对象
// ElementUI 的 表格经常用到
<el-table-column label="ID">
<template slot-scope="{ row }">
<span>{{ row }}</span>
</template>
</el-table-column>
// 常规
v-slot:default="scope"
{{scope.msg}}
{{scope.infomation.address}}
vue2:https://cn.vuejs.org/v2/guide/custom-directive.html
insert
update
-> mounted
updated
vue3:https://vue3js.cn/docs/zh/guide/custom-directive.html
二者钩子函数不一样
<script src="https://cdn.bootcdn.net/ajax/libs/vue/2.6.9/vue.js">script>
<div id="app">
<input type="text" v-focus />
div>
<script>
let app = new Vue({
el: "#app",
data: {},
directives: {
focus: {
inserted(el) { // vue3为 mounted
el.focus();
},
},
},
});
script>