安装Vue Devtools
在浏览器上安装Vue Devtools工具https://github.com/vuejs/vue-devtools
啊,直接上教程,链接:https://blog.csdn.net/weixin_38654336/article/details/80790698
v-text 、v-html 、v-on
模版指令v-text与v-html
v-text会进行转义
v-html不会进行转义
Vue实例里的methods里面定义事件
v-on:click 简写@click
v-on绑定事件
vue不是面向dom编程,而是面向数据编程
Vue中的属性绑定和双向数据绑定
模版指令v-bind 简写 :
v-bind:title = “title” title属性与title数据项进行绑定,这样后面=后面就不是一个字符串而是一个表达式了
单向绑定: 数据决定页面的显示,但是页面无法决定数据内容
模版指令v-model :实现数据的双向绑定
v-model的修饰符
.lazy
在默认情况下,v-model 在每次 input 事件触发后将输入框的值与数据进行同步 (除了上述输入法组合文字时)。你可以添加 lazy 修饰符,从而转变为使用 change 事件进行同步:
<!-- 在“change”时而非“input”时更新 -->
<input v-model.lazy="msg" >
.number
如果想自动将用户的输入值转为数值类型,可以给 v-model 添加 number 修饰符:
<input v-model.number="age" type="number">
这通常很有用,因为即使在 type=“number” 时,HTML 输入元素的值也总会返回字符串。如果这个值无法被 parseFloat() 解析,则会返回原始的值。
.trim
如果要自动过滤用户输入的首尾空白字符,可以给 v-model 添加 trim 修饰符:
<input v-model.trim="msg">
一些有用的实例属性与方法
Vue 实例还暴露了一些有用的实例属性与方法。它们都有前缀 $,以便与用户定义的属性区分开来。
Vue中计算属性与监听器
计算属性computed
Vue实例里的computed ,定义在里面的属性表示是一个计算属性
好处:当计算属性里的项没有发生改变时会使用上一次计算属性的缓存结果,当里面的项发生改变时才会重新计算
监听器watch
Vue实例里的watch,一旦里面的属性发生了变化就执行定义的函数内容
watch:{
fullName: function(){
this.count ++
}
}
v-if, v-show与v-for指令
v-if 控制dom的存在与否,true存在,false不存在
v-show 控制dom的显示与否,true显示(display:block),false隐藏(display:none)
v-if与v-show的区别:
v-if当所对应的数据项为false时,会将标签直接从dom中删除
v-show当所对应的数据项为false时,将标签中的display属性设置为none
频繁隐藏显示标签时使用v-show性能更高,不经常隐藏显示标签时使用v-if性能更高
v-for来做数据的循环展示,使用时最好加:key属性,每一项的key都需不同
<ul>
<li v-for="(item,index) of list" :key="index">{{item}}</li>
</ul>
<script>
new Vue({
...
data:{
list:[1,2,3]
},
...
})
</script>
组件
定义组件后可多次使用组件,每用一次组件,就会有一个它的新实例被创建。
全局组件
Vue.component( 'todo-list' , {
template: '<li>item</item>'
})
局部组件
使用components对局部组件进行注册
var TodoList = {
template: '<li>item</item>'
}
new Vue({
el:'#root',
components:{
todo-list:TodoList
},
...
})
想要传递参数,使用属性props
<todo-list
v-for="(item,idex) of list"
:key="index"
:content="item">
<todo-list>
<script>
Vue.component( 'todo-list' , {
props:['content'],
template: '<li>{{content}}</item>'
})
new Vue({
el:'#root',
data:{
inputValue:'',
list:[]
},
...
})
</script>
注意: :key="index"后面不加 “,” 否则报错
<to-item
v-for = "(item,index) of list"
:key = "index"
:content="item"
></to-item>
methods可以拿到参数
Vue.component('to-item',{
props:['content'],
template:'<li @click="handleClick">{{content}}</li>',
methods:{
handleClick:function(){
alert(this.content)
}
}
})
使用特性$attrs
// child:并未在props中声明foo
<p>{{$attrs.foo}}</p>
// parent
<HelloWorld foo="foo"/>
引用refs
// parent
<HelloWorld ref="hw"/>
mounted() {
this.$refs.hw.xx = 'xxx'
}
组件插槽进行分发内容
<slot>
元素, 在需要的地方加入插槽就行
Vue.component('alert-box',{
template:`<div class="demo-alert-box">
<strong>警告:</strong>
<slot></slot>
</div>`
})
<alert-box>发生错误</alert-box>
动态组件
Vue 的 <component>
元素加一个特殊的 is 特性来实现
<!-- 组件会在 `currentTabComponent` 改变时改变 -->
<component v-bind:is="currentTabComponent"></component>
如下例子:
<div id="dynamic-component-demo" class="demo">
<button
v-for="tab in tabs"
v-bind:key="tab"
v-bind:class="['tab-button', { active: currentTab === tab }]"
v-on:click="currentTab = tab"
>{{ tab }}</button>
<component
v-bind:is="currentTabComponent"
class="tab"
></component>
</div>
Vue.component('tab-home', {
template: '<div>Home component</div>'
})
Vue.component('tab-posts', {
template: '<div>Posts component</div>'
})
Vue.component('tab-archive', {
template: '<div>Archive component</div>'
})
new Vue({
el: '#dynamic-component-demo',
data: {
currentTab: 'Home',
tabs: ['Home', 'Posts', 'Archive']
},
computed: {
currentTabComponent: function () {
return 'tab-' + this.currentTab.toLowerCase()
}
}
})
组件与实例的关系
Vue中的每个组件都是一个Vue的实例,都有methods等
Vue实例可以不定义template,会将挂载点下的所有dom标签作为这个实例的模版
Vue中父组件向子组件进行传值是通过属性进行传递
注意: 组件也可以有data,但data必须是一个函数,这样每个实例可以维护一份被返回对象的独立的拷贝
data: function () {
return {
count: 0
}
}
不然,改变一个实例的data将会影响到其它所有实例
表单输入绑定
复选框(单个与多个)
多个复选框,绑定到同一个数组:设置value值,v-model绑定对应的value值
<div id='example-3'>
<input type="checkbox" id="jack" value="Jack" v-model="checkedNames">
<label for="jack">Jack</label>
<input type="checkbox" id="john" value="John" v-model="checkedNames">
<label for="john">John</label>
<input type="checkbox" id="mike" value="Mike" v-model="checkedNames">
<label for="mike">Mike</label>
<br>
<span>Checked names: {{ checkedNames }}</span>
</div>
new Vue({
el: '#example-3',
data: {
checkedNames: [] //注意:是[],而不是“” 单选则“”
}
})
选择框
<div id="example-5">
<select v-model="selected">
<option disabled value="">请选择</option>
<option>A</option>
<option>B</option>
<option>C</option>
</select>
<span>Selected: {{ selected }}</span>
</div>
prop使用注意点
所有的 prop 都使得其父子 prop 之间形成了一个单向下行绑定:父级 prop 的更新会向下流动到子组件中,但是反过来则不行。
最好不要在子组件内部改变prop。因为JavaScript 中对象和数组是通过引用传入的,所以对于一个数组或对象类型的 prop 来说,在子组件中改变这个对象或数组本身将会影响到父组件的状态。
两种常见的试图改变一个 prop 的情形与解决方法:
1、这个 prop 用来传递一个初始值;这个子组件接下来希望将其作为一个本地的 prop 数据来使用。在这种情况下,最好定义一个本地的 data 属性并将这个 prop 用作其初始值:
props: ['initialCounter'],
data: function () {
return {
counter: this.initialCounter
}
}
2、这个 prop 以一种原始的值传入且需要进行转换。在这种情况下,最好使用这个 prop 的值来定义一个计算属性:
props: ['size'],
computed: {
normalizedSize: function () {
return this.size.trim().toLowerCase()
}
}
生命周期函数
生命周期函数不能使用箭头函数,因为箭头函数是没有this的。
//在实例初始化之后,数据观测 (data observer) 和 event/watcher 事件配置之前被调用。
beforeCreate:function(){
console.log('beforeCreate');
},
/* 在实例创建完成后被立即调用。
在这一步,实例已完成以下的配置:数据观测 (data observer),属性和方法的运算,watch/event 事件回调。
然而,挂载阶段还没开始,$el 属性目前不可见。 */
created :function(){
console.log('created');
},
//在挂载开始之前被调用:相关的渲染函数首次被调用
beforeMount : function(){
console.log('beforeMount');
},
//el 被新创建的 vm.$el 替换, 挂在成功
mounted : function(){
console.log('mounted');
},
//数据更新时调用
beforeUpdate : function(){
console.log('beforeUpdate');
},
//组件 DOM 已经更新, 组件更新完毕
updated : function(){
console.log('updated');
}
事件修饰符
修饰符是由点开头的指令后缀来表示的。
.stop
.prevent
.capture
.self
.once
.passive
<!-- 阻止单击事件继续传播 -->
<a v-on:click.stop="doThis"></a>
<!-- 提交事件不再重载页面 -->
<form v-on:submit.prevent="onSubmit"></form>
<!-- 修饰符可以串联 -->
<a v-on:click.stop.prevent="doThat"></a>
<!-- 只有修饰符 -->
<form v-on:submit.prevent></form>
<!-- 添加事件监听器时使用事件捕获模式 -->
<!-- 即元素自身触发的事件先在此处理,然后才交由内部元素进行处理 -->
<div v-on:click.capture="doThis">...</div>
<!-- 只当在 event.target 是当前元素自身时触发处理函数 -->
<!-- 即事件不是从内部元素触发的 -->
<div v-on:click.self="doThat">...</div>
图片路径传递
1、如果图片是在 assets 文件夹下面的话,需要在路径前面加上 require 函数才行,否则 webpack 会识别不了路径报错
"imgPath": require("../../assets/logo.png")
2、图片放到 static 文件夹下面,这样的话就不需要 require ,可以像原来传统的方式那样写
"imgPath": "../../../static/logo.png"
脚手架vue-li 的简介与使用
npm install vue-cli -g
安装完成后进行新建一个项目
vue init webpack vue-demo
出现错误vue-cli • Failed to download repo vuejs-templates/webpack: unable to verifythe first certificate
解决方法:
1、下载webpack初始化的模板文件 下载解压出来文件是webpack-develop,改名webpack。
2、将webpack文件夹放到C:\Users\Administrator.vue-templates文件夹下面
3、如果没有找到.vue-templates文件夹则新建一个
4、执行 vue init webpack [project-name] --offline
5、如果还报错:本地模板在***地址找不到,就把webpack放到那个地址下即可
新建了一个vue-demo项目后,切到该项目目录下,启动项目
npm run dev
至此能在http://localhost:8080看到新建的基本项目
第二种新建项目的方法:
在终端输入vue ui
将会启动GUI ,将下面提示的地址如http://localhost:8000
打开会进入vue项目管理界面。
在任务中可以进行编译运行项目,非常方便
目录
build目录下放置webpack的配置文件
config是针对开发环境和线上环境的一些配置文件
node_mudules放的项目的依赖
src源代码所放置的目录
static放置静态资源
index.html是整个项目最外层的网页
src目录下的main.js文件是整个项目的入口文件
在这个脚手架工具里,提供了新的编码语法——单文件组件
组件的模板<template></template>
注意:<template></template>
里只能有一个根元素
<template>
<div id="app">
<HelloWorld/>
</div>
</template>
组件逻辑<script></script>
组件逻辑
<script>
import HelloWorld from './components/HelloWorld'
export default {
name: 'App',
components: {
HelloWorld
}
}
</script>
组件样式<style></style>
<style>
#app {
color: #2c3e50;
margin-top: 60px;
}
</style>
组件逻辑中,
定义data,以往的data是一个对象data:{}
, 现在data变成了函数data(){}
(简写)
export default {
data: function(){
return {
name:'Jack'
}
}
}
全局样式与局部样式
加了scoped即变成局部样式,只在当前有效
<style scoped>
</style>
VueX
官方描述
Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式。它采用集中式存储管理应用的所有组件的状态,并以相应的规则保证状态以一种可预测的方式发生变化。
Vuex由五部分组成:State、Getter、Mutation、Action、Module。至少会由State、Mutation构成。
如果需要在Vue组件中展示状态,最好在计算属性返回从store中读取的状态,因为VueX的状态存储是响应式的。如果放在data中,状态变化不会触发页面更新;而放计算属性中,一旦状态发生改变,都会重新求取计算组件,从而刷新页面。
Getter
可以把Getter当成 store 中的计算属性(computed)。就像计算属性一样,getter 的返回值会根据它的依赖被缓存起来,且只有当它的依赖值发生了改变才会被重新计算。
const store = new Vuex.Store({
state: {
date: new Date()
},
getters: {
// Getter 接受 state 作为其第一个参数
weekDate: state => {
return moment(state.date).format('dddd');
}
}
})
可以通过属性的方式访问这些值store.getters.weekDate
如果需要传参,可以将其变成一个函数
getters: {
// 返回一个函数,就可以传参了
weekDate: (state) => (fm) => {
return moment(state.date).format(fm ? fm : 'dddd');
}
}
使用store.getters.weekDate('MM Do YY')
mutations
更改 Vuex 的 store 中的状态的唯一方法是提交 mutation。Vuex 中的 mutation 非常类似于事件:每个 mutation 都有一个字符串的 事件类型 (type) 和 一个 回调函数 (handler)。这个回调函数就是我们实际进行状态更改的地方,并且它会接受 state 作为第一个参数
const store = new Vuex.Store({
state: {
count: 1
},
mutations: {
// 事件类型 type 为 increment
increment (state) {
// 变更状态
state.count++
}
}
})
需要使用store.commit('increment')
来触发
传参方式有两种:
// 1、把载荷和type分开提交
store.commit('increment', {
amount: 10
})
// 2、整个对象都作为载荷传给 mutation 函数
store.commit({
type: 'increment',
amount: 10
})
修改注意事项:
当状态数据的类型为对象时,添加一个属性的两种方法:
const store = new Vuex.Store({
state: {
student: {
name: '小明',
sex: '女'
}
},
mutations: {
addAge (state) {
Vue.set(state.student, 'age', 18)
// 或者:
// state.student = { ...state.student, age: 18 }
}
})
Action