vue学习笔记
注释
对着文档和视频整理的笔记,都是完整示例。复制即可实现功能,配图或控制台/页面数据。
组件区有gitee 的一个项目源码 可以看着学习
vue.config.js配置
热更新 和 runtimeCompiler
module.exports = {
runtimeCompiler: true,
devServer: {
hot: true,
open: true,
port: 8080,
host: "127.0.0.1"
}
}
vscode中 npm-v 报错
npm : 无法加载文件 D:\Program Files\nodejs\node_global\npm.ps1,因为在此系统上禁止运行脚本。有关详细信息,请参阅 https:
/go.microsoft.com/fwlink/?LinkID=135170 中的 about_Execution_Policies。
输入
get-ExecutionPolicy
输出:
Restricted
受限制的,表示状态是禁止的,那就给个权限:
Set-ExecutionPolicy -Scope CurrentUser
输入:
RemoteSigned
验证一下:
get-ExecutionPolicy
原文链接:https://blog.csdn.net/weixin_43336281/article/details/107064733
对一些使用的简单记录
v-mdoel 双向绑定
<body>
<div id="app">
<input type="text" v-model="username"> {{username}}
</div>
</body>
<script src="vue.js"></script>
<script src="vue-myPlugin.js"></script>
<script>
const vm = new Vue({
el: '#app',
data: {
username: ''
}
})
</script>
指令:强制数据绑定 v-bind:src = :src 绑定事件监听 v-on:click = @click
<body>
<div id="app">
<p>{{username}}</p>
<!-- textContent -->
<p v-text="username">{{username}}</p>
<!-- textContent -->
<p v-html="username">{{username}}</p>
<!-- innerhtml -->
<h2>指令一:强制数据绑定</h2>
<img src="imgUrl">
<img v-bind:src="imgUrl">
<img :src="imgUrl">
<h2>绑定事件监听</h2>
<button v-on:click="test">test</button>
<button @click="test2(username)">test</button>
</div>
</body>
<script src="vue.js"></script>
<script src="vue-myPlugin.js"></script>
<script>
new Vue({
el: '#app',
data: {
username: '<a>www.baidu.com</a>',
imgUrl: "https://cn.vuejs.org/images/logo.png"
},
methods: {
test() {
alert("test")
},
test2(content) {
alert(content)
}
}
})
</script>
计算属性computed之基本使用
1.计算属性
在computed属性对象中定义计算属性的方法
在页面中使用{{方法名}}来显示计算的结果
2.监视属性:
通过vm对象的$watch()或watch配置来监视指定的属性
当属性变化时,回调函数自动调用,在函数内部进行计算
3.计算属性高级
通过getter / setter 实现对属性数据的显示和监视
计算属性存在缓存,多次读取只执行一次getter计算
<body>
<div id="app">
姓<input type="text" v-model="firstname"> 名
<input type="text" v-model="lastname"> 姓名
<input type="text" v-model="fullname">
</div>
</body>
<script src="vue.js"></script>
<script src="vue-myPlugin.js"></script>
<script>
new Vue({
el: '#app',
data: {
firstname: 'a',
lastname: 'b',
},
computed: {
//什么时候执行:初始化显示/相关的data属性数据发生改变
//计算属性中的一个方法,方法返回值作为属性值
fullname() {
console.log('fullname()')
return this.firstname + this.lastname
}
}
})
</script>
用watch实现一下上面的案例
<body>
<div id="app">
姓<input type="text" v-model="firstname"> 名
<input type="text" v-model="lastname"> 姓名
<input type="text" v-model="fullname">
<input type="text" v-model="fullname2">
</div>
</body>
<script src="vue.js"></script>
<script src="vue-myPlugin.js"></script>
<script>
const vm = new Vue({
el: '#app',
data: {
firstname: 'a',
lastname: 'b',
},
computed: {
//什么时候执行:初始化显示/相关的data属性数据发生改变
//计算属性中的一个方法,方法返回值作为属性值
fullname() {
console.log('fullname()')
return this.firstname + this.lastname
}
},
watch: { //配置监视
firstname: function(value) {
//firstname发生变化 修改
console.log(this) //就是vm对象
this.fullname2 = value + this.lastname
}
}
})
vm.$watch('lastname', function(value) {
this.fullname2 = this.first + value
})
1.计算属性
在computed属性对象中定义计算属性的方法
在页面中使用{{方法名}}来显示计算的结果
2.监视属性:
通过vm对象的$watch()或watch配置来监视指定的属性
当属性变化时,回调函数自动调用,在函数内部进行计算
3.计算属性高级
通过getter / setter 实现对属性数据的显示和监视
计算属性存在缓存,多次读取只执行一次getter计算
getter get() setter set()
用一个双向的 改变全名 姓和名都改变
<body>
<div id="app">
姓<input type="text" v-model="firstname"> 名
<input type="text" v-model="lastname"> 姓名
<input type="text" v-model="fullname">
<input type="text" v-model="fullname2">
</div>
</body>
<script src="vue.js"></script>
<script src="vue-myPlugin.js"></script>
<script>
const vm = new Vue({
el: '#app',
data: {
firstname: 'a',
lastname: 'b',
},
computed: {
//什么时候执行:初始化显示/相关的data属性数据发生改变
//计算属性中的一个方法,方法返回值作为属性值
fullname() {
console.log('fullname()')
return this.firstname + this.lastname
},
fullname2: {
/* 1.你定义的 2.你没有调用3.但最终它执行了
2.什么时候调用 2.用来做什么
回调函数 当需要读取当前属性值时回调,根据相关数据
计算并返回当前属性的值*/
get() {
return this.firstname + this.lastname
},
set(value) {
const names = value.split('')
this.firstname = names[0]
this.lastname = names[1]
}
}
}
})
</script>
强制绑定class和style
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<style>
.aClass {
color: red;
}
.cClass {
font-size: 10px;
}
.bClass {
color: blue;
}
</style>
</head>
<body>
<div id="demo">
<p :class="a">绑定字符串aClass</p>
<p :class="{aClass:isA,bClass:isB}">绑定对象一开始aClass updata变成bclass </p>
<p :class="['aClass','cClass']">aClass cClass 数组</p>
<p :style="{color: activeColor,fontSize:fontsize+'px'}"> this is object</p>
<button @click="update">update</button>
</div>
<script src="vue.js">
</script>
<script>
new Vue({
el: '#demo',
data: {
a: 'aClass',
activeColor: 'green',
fontsize: 50,
isA: true,
isB: false
},
methods: {
update() {
this.a = 'bClass ',
this.isA = false,
this.isB = true,
this.activeColor = 'yellow'
this.fontsize = 100
}
}
})
</script>
</body>
</html>
条件渲染 v-if v-else v-else-if
页面显示
Vue is awesome!
A
<template>
<div id="example-1">
<h1 v-if="awesome">Vue is awesome!</h1>
<h1 v-else>Oh no 😢</h1>
<div v-if="type === 'A'">
A
</div>
<div v-else-if="type === 'B'">
B
</div>
<div v-else-if="type === 'C'">
C
</div>
<div v-else>
Not A/B/C
</div>
</div>
</template>
<script>
export default {
data () {
return {
awesome:true,
type:'A'
}
}
}
</script>
<style>
</style>
列表渲染
Foo
Bar
Parent - 0 - Foo
Parent - 1 - Bar
<template>
<div>
<ul id="example-1">
<li v-for="item in items" :key="item.message">
{{ item.message }}
</li>
</ul>
<ul id="example-2">
<li v-for="(item,index) in items" :key="item.message">
{{ parentMessage }} - {{ index }} - {{ item.message }}
</li>
</ul>
</div>
</template>
<script>
export default {
data () {
return {
parentMessage: 'Parent',
items: [
{ message: 'Foo' },
{ message: 'Bar' }
]
}
}
}
</script>
<style>
</style>
- title : How to do lists in Vue
- author : Jane Doe
- publishedAt : 2016-04-10
<template>
<div>
<ul id="v-for-object" class="demo">
<li v-for="(value, key, index) in object" :key="index">
{{ index }}. {{ key }} : {{ value }}
</li>
</ul>
</div>
</template>
<script>
export default {
data () {
return {
object: {
title: 'How to do lists in Vue',
author: 'Jane Doe',
publishedAt: '2016-04-10'
}
}
}
}
</script>
<style>
</style>
2
4
<template>
<div>
<li v-for="n in evenNumbers">{{ n }}</li>
</div>
</template>
<script>
export default {
data () {
return {
numbers: [ 1, 2, 3, 4, 5 ]
}
},
computed: {
evenNumbers: function () {
return this.numbers.filter(function (number) {
return number % 2 === 0
})
}
}
}
</script>
<style>
</style>
事件处理
可以用 v-on 指令监听 DOM 事件,并在触发时运行一些 JavaScript 代码。
<template>
<div id="example-1">
<button @click="counter += 1">Add 1</button>
<p>The button above has been clicked {{ counter }} times.</p>
</div>
</template>
<script>
export default {
data () {
return {
counter: 0
}
}
}
</script>
<style>
</style>
v-on 还可以接收一个需要调用的方法名称
<template>
<div id="example-2">
<!-- `greet` 是在下面定义的方法名 -->
<button v-on:click="greet">Greet</button>
</div>
</template>
<script>
export default {
data () {
return {
name: 'Vue.js'
}
},
methods: {
greet: function (event) {
// `this` 在方法里指向当前 Vue 实例
console.log(this)
console.log(this.name)
console.log('Hello ' + this.name + '!')
// `event` 是原生 DOM 事件
if (event) {
console.log(event)
console.log(event.target.tagName)
}
}
}
}
</script>
<style>
</style>
有时也需要在内联语句处理器中访问原始的 DOM 事件。可以用特殊变量 e v e n t 把 它 传 入 方 法 : 不 用 event 把它传入方法: 不用 event把它传入方法:不用event 的事件
methods: {
say: function (message) {
alert(message)
}
event.preventDefault()方法
阻止元素发生默认的行为。调用此方法链接(a标签)不会被打开,但是会冒泡到父元素上。
例如:
(1). 当点击提交按钮时阻止对表单的提交
(2). 阻止 URL 的链接(意思是如果点击一个a标签,浏览器不会跳到新的 URL 里面去)
用event 返回原始DOM事件
<template>
<div id="example-2">
<a href="https://www.baidu.com">
<button v-on:click="warn('warn', $event)">
Submit
</button></a>
</div>
</template>
<script>
export default {
data () {
return {
}
},
methods: {
warn: function (message, event) {
// 现在我们可以访问原生事件对象
if (event) {
console.log(event)
event.preventDefault()
}
console.log(message)
}
}
}
</script>
<style>
</style>
生命周期
<template>
<div id="app">
<button @click="destoryVM()">destroy vm</button>
<p v-show="isShow">vm</p>
</div>
</template>
<script>
export default {
data(){
return{
isShow:true
}
},
//初始化
beforeCreate(){
console.log('beforeCreate')
},
created(){
console.log('created')
},
beforeMount(){
console.log('beforeMount')
},
mounted(){ //初始化显示之后立即调用
this.intervalId = setInterval(()=>{
console.log('-----mounted')
this.isShow = !this.isShow
},1000)
},
beforeUpdate(){
console.log('beforeUpdata')
},
//更新阶段
updated(){
console.log('updated')
},
beforeDestroy(){
console.log('beforeDestroy')
//死亡之前调用一次
clearInterval(this.intervalId)
},
destory(){
console.log('destory')
},
methods:{
destoryVM(){
this.$destroy()
}
}
}
</script>
<style>
</style>
slot
引用了一个github上的demo 当时为了偷懒 demo1、2、3 合在一起了 所以有点乱 可以去看原作者的分开的 但是混合之后问题不大 理解的更加明白了
https://github.com/cunzaizhuyi/vue-slot-demo/tree/master/src/components
App.vue
<template>
<div class="father">
<h3>这里是父组件</h3>
<!--demo1第一次使用-->
<child>
<div class="tmpl">
<span>菜单1</span>
<span>菜单2</span>
<span>菜单3</span>
<span>菜单4</span>
<span>菜单5</span>
<span>菜单6</span>
</div>
</child>
<h3>这里是父组件demo2</h3>
<!--demo2第一次使用-->
<child>
<div class="tmpl" slot="up">
<span>菜单1</span>
<span>菜单2</span>
<span>菜单3</span>
<span>菜单4</span>
<span>菜单5</span>
<span>菜单6</span>
</div>
<div class="tmpl" slot="down">
<span>菜单-1</span>
<span>菜单-2</span>
<span>菜单-3</span>
<span>菜单-4</span>
<span>菜单-5</span>
<span>菜单-6</span>
</div>
<div class="tmpl">
<span>菜单->1</span>
<span>菜单->2</span>
<span>菜单->3</span>
<span>菜单->4</span>
<span>菜单->5</span>
<span>菜单->6</span>
</div>
</child>
<!--demo3第一次使用:用flex展示数据-->
<child>
<template slot-scope="user">
<div class="tmpl">
<span v-for="item in user.data">{{item}}</span>
</div>
</template>
</child>
<!--第二次使用:用列表展示数据-->
<child>
<template slot-scope="user">
<ul>
<li v-for="item in user.data">{{item}}</li>
</ul>
</template>
</child>
<!--第三次使用:直接显示数据-->
<child>
<template slot-scope="user">
{{user.data}}
</template>
</child>
<!--第四次使用:不使用其提供的数据-->
<child>
我就是模板
</child>
</div>
</template>
<script>
import Child from './components/Child'
export default {
data: function () {
return {
msg: ''
}
},
methods: {
clickHandler(data){
console.log(data);
}
},
components:{
'child': Child
}
}
</script>
<style scoped>
.father{
width:100%;
background-color: #ccc;
height: 650px;
}
.tmpl{
display: flex;
justify-content: space-around;
flex-direction: row;
width: 30%;
margin: 0 auto;
}
.tmpl span{
border:1px solid red;
height:50px;
line-height: 50px;
padding: 10px;
}
</style>
Child.vue
<template>
<div class="child">
<h3>这里是子组件</h3>
<!-- demo1 -->
<slot></slot>
<!-- demo2 -->
<slot name="up"></slot>
<h3>这里是子组件</h3>
<slot name="down"></slot>
<slot></slot>
<!-- demo3 -->
<slot :data="data"></slot>
</div>
</template>
<script>
export default {
data: function(){
return {
data: ['zhangsan','lisi','wanwu','zhaoliu','tianqi','xiaoba']
}
},
computed: {
},
methods:{
},
components: {
}
}
</script>
<style scoped>
.child{
background-color: #00bbff;
width: 100%;
padding: 10px;
-webkit-box-sizing: border-box;
-moz-box-sizing: border-box;
box-sizing: border-box;
}
</style>
自定义指令 组件 props父子传参
单项的数据处理 没有很复杂 不需要用到自定义组件 用 自定义指令
App.vue
<template>
<div>
我是父组件
<hello-world :age="ages" @patch="msg">
</hello-world>
</div>
</template>
<script>
import HelloWorld from './components/HelloWorld.vue'
import './components/n'
export default {
name:'app',
components: {
HelloWorld
},
data(){
return{
ages:18
}
},
methods:{
msg:function(){
window.console.log('msg')
this.ages++
}
}
}
</script>
<style>
</style>
HelloWorld.vue
<template>
<div >
<div v-n="3"></div>
<div v-n="4"></div>
{{age}}
<button type="button" name="button" @click="$emit('patch')">send</button>
<slot></slot>
</div>
</template>
<script>
export default {
props: ['age'],
data(){
return{
name:'helloworld'
}
}
}
</script>
<style scoped>
</style>
n.js
import Vue from 'vue'
Vue.directive('n', {
bind: function(el, binding) {
el.textContent = Math.pow(binding.value, 2)
},
update: function(el, binding) {
el.textContent = Math.pow(binding.value, 2)
}
})
组件
有一个完成度还不错的网易云仿写项目可以参考,有时间就会不断的补上笔记或者是完善项目
https://gitee.com/thinkerwing/test
路由
router.js
import Vue from 'vue'
import VueRouter from 'vue-router'
import pageA from './pages/a.vue'
import pageB from './pages/b.vue'
Vue.use(VueRouter)
/*如果在一个模块化工程中使用它,必须要通过
Vue.use() 明确地安装路由功能:
配置路由的路径 path 配置了关联 并 没有生效*/
const routes = [{
path: '/pagea',
component: pageA
}, {
path: '/pageb',
component: pageB
}]
// 实例化
const router = new VueRouter({
routes
})
//导出
export default router
cli脚手架搭建的main.js
import Vue from 'vue'
import App from './App.vue'
Vue.config.productionTip = false
new Vue({
render: function (h) { return h(App) },
}).$mount('#app')
import Vue from 'vue'
import router from './router'
Vue.config.productionTip = false
new Vue({
router
}).$mount('#app')
vue.runtime.esm.js?2b0e:619 [Vue warn]: You are using the runtime-only build of Vue where the template compiler is not available. Either pre-compile the templates into render functions, or use the compiler-included build.
(found in )
解决方法:
创建vue.config.js
module.export = {
runtimeCompiler: true
}
重启cli 重新编译
挂载index.html
<div id="app">
<router-view></router-view>
</div>
路由跳转
<router-link to="/pagea">pagea</router-link>
<router-link to="/pageb">pageb</router-link>
vuex
父子之间的通信 想共享到子组件 ? props
子组件的数据想回传到父组件? 可以用事件
有几个不相关的想共享数据呢? 用vuex
state 所有公用的部分 想要共享的那个数据 不是全局的变量 用mutations 直接操作state数据
actions 触发什么时候去改变 commit 提交commit
数据在state 如何改变呢 在mutaitons 什么时候去改变在actions
state是数据虽然没有在data里面 vue模板是可以render这个数据的
完整的数据流:dispatch 通过用户的交互触发actions action做提交找到对应交互的mutations 最终让state数据改变 然后vue components更新
代码实现
vuex.js
<template>
<div>
vuex{{$store.state.count }}
<button @click="increment">增加</button>
<button @click="decrement">删减</button>
</div>
</template>
<script>
import {mapActions} from 'vuex'
export default {
//让事件的方法跟定义的关联
methods:mapActions([
'increment',
'decrement'
])
}
</script>
<style>
</style>
store.js
import Vue from 'vue';
import Vuex from 'vuex';
Vue.use(Vuex);
const state = {
count: 1
}
const mutations = {
increment(state) {
state.count++
},
decrement(state) {
state.count--
}
}
const actions = {
increment: ({ commit }) => {
commit('increment')
},
decrement: ({ commit }) => {
commit('decrement')
}
}
export default new Vuex.Store({ state, mutations, actions })
防止太多混乱,用index.js当入口文件
index.js
import Vue from 'vue';
import Vuex from 'vuex';
import money from './modules/a.js'
import count from './modules/b.js'
Vue.use(Vuex);
export default new Vuex.Store({
modules: {
money,
count
}
})
a.js
const state = {
money: 10
}
const mutations = {
add(state) {
state.money++
},
reduce(state) {
state.money--
}
}
const actions = {
add: ({ commit }) => {
commit('add')
},
reduce: ({ commit }) => {
commit('reduce')
}
}
export default {
namespaced: true,
state,
mutations,
actions
}
a.vue
<template>
<div>
a {{$store.state.money.money}}
<button @click="add">add</button>
<button @click="reduce">reduce</button>
</div>
</template>
<script>
import {mapActions}from 'vuex'
export default {
methods:mapActions('money',['add','reduce'])
}
</script>
<style>
</style>
传参
const mutations = {
add(state, param) {
window.console.log(param)
state.money += param
},
reduce(state) {
state.money--
}
}
const actions = {
add: ({ commit }, param) => {
commit('add', param)
},
reduce: ({ commit }) => {
commit('reduce')
}
}