1 vue安装
1.1 直接用 script标签引入
对于制作原型或学习,你可以这样使用最新版本:
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
对于生产环境,我们推荐链接到一个明确的版本号和构建文件,以避免新版本造成的不可预期的破坏:
<script src="https://cdn.jsdelivr.net/npm/vue@2.6.11"></script>
1.2 NPM创建
//安装vue
npm install vue
npm install -g @vue/cli
//创建vue项目
vue create project_name
//q
cd project_name
npm run serve
1.3 使用HbuilderX创建vue项目
1.4 快速启动vue-element-admin
# clone the project
git clone https://github.com/PanJiaChen/vue-admin-template.git
# enter the project directory
cd vue-admin-template
# install dependency
npm install
# develop
npm run dev
2 vue执行顺序
3 vue基础语法
4 vue特性
5 组件
5.1 定义组件的固定写法:
<template>
... //这里写组件中的HTML代码,可复用
</template>
<script>
... //这里写一些动态的脚本
</script>
<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped>
... //这里写一些样式,如果加上scoped则表示当前样式仅限该组件使用,一般组件中的样式都是局部样式
</style>
5.2 vue
官方的helloworld
组件写法:
<template>
<div class="hello"> //一般会在模板中定义一个大盒子,否则会报一个如图2所示的错误
<h1>{{ msg }}</h1>
<p>
For a guide and recipes on how to configure / customize this project,<br>
check out the
<a href="https://cli.vuejs.org" target="_blank" rel="noopener">vue-cli documentation</a>.
</p>
<h3>Installed CLI Plugins</h3>
<ul>
<li><a href="https://github.com/vuejs/vue-cli/tree/dev/packages/%40vue/cli-plugin-babel" target="_blank" rel="noopener">babel</a></li>
<li><a href="https://github.com/vuejs/vue-cli/tree/dev/packages/%40vue/cli-plugin-eslint" target="_blank" rel="noopener">eslint</a></li>
</ul>
<h3>Essential Links</h3>
<ul>
<li><a href="https://vuejs.org" target="_blank" rel="noopener">Core Docs</a></li>
<li><a href="https://forum.vuejs.org" target="_blank" rel="noopener">Forum</a></li>
<li><a href="https://chat.vuejs.org" target="_blank" rel="noopener">Community Chat</a></li>
<li><a href="https://twitter.com/vuejs" target="_blank" rel="noopener">Twitter</a></li>
<li><a href="https://news.vuejs.org" target="_blank" rel="noopener">News</a></li>
</ul>
<h3>Ecosystem</h3>
<ul>
<li><a href="https://router.vuejs.org" target="_blank" rel="noopener">vue-router</a></li>
<li><a href="https://vuex.vuejs.org" target="_blank" rel="noopener">vuex</a></li>
<li><a href="https://github.com/vuejs/vue-devtools#vue-devtools" target="_blank" rel="noopener">vue-devtools</a></li>
<li><a href="https://vue-loader.vuejs.org" target="_blank" rel="noopener">vue-loader</a></li>
<li><a href="https://github.com/vuejs/awesome-vue" target="_blank" rel="noopener">awesome-vue</a></li>
</ul>
</div>
</template>
<script>
export default {
name: 'HelloWorld',
props: { //从外部获取参数,组件之间传递参数
msg: String
}
}
</script>
<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped>
h3 {
margin: 40px 0 0;
}
ul {
list-style-type: none;
padding: 0;
}
li {
display: inline-block;
margin: 0 10px;
}
a {
color: #42b983;
}
</style>
5.3 使用自定义组件
<div id="app">
//写法1,其中的msg是传到到组件中的参数,msg必须与组件中定义的接收变量一致,等于号后面的部分至变量值
<HelloWorld msg="this parma is from props"/>
//写法2
<HelloWorld msg="this parma is from props"></HelloWorld>
</div>
6 组件间通信
6.1 方式1-props/$emit
- 父组件A 向 子组件B 传递数据 通过
props
的方法 - 子组件B 向 父组件A 发送数据 通过
emit
使用该方式传递参数时,官方提供了两种写法:
写法1:
为了简化代码,可以使用数组的写法
props: ['var1', 'var2', ...]
写法2:
如果你想指定每一个变量的类型,可以使用对象的写法
props: {
var1: String,
var2: Number,
var3: Boolean,
var4: Array,
var5: Object,
var6: Function
}
prop的特性(单向数据流)
所有的 prop 都使得其父子 prop 之间形成了一个单向下行绑定:父级 prop 的更新会向下流动到子组件中,但是反过来则不行。这样会防止从子组件意外变更父级组件的状态,从而导致你的应用的数据流向难以理解。
额外的,每次父级组件发生变更时,子组件中所有的 prop 都将会刷新为最新的值。这意味着你不应该在一个子组件内部改变 prop。如果你这样做了,Vue 会在浏览器的控制台中发出警告。
props 只可以从上一级组件传递到下一级组件,也就是父子组件,即这就是单向数据流
props是只读,不可以被修改,所有被修改都会失效和被警告
注意:
注意在 JavaScript 中对象和数组是通过引用传入的,所以对于一个数组或对象类型的 prop 来说,在子组件中改变变更这个对象或数组本身将会影响到父组件的状态。
示例1(父组件向子组件传递数据)
father.vue
:
<template>
<div class="father">
in father : {{msg}}
<son :msg="[1,2,3,4,5]"></son>
</div>
</template>
<script>
import son from "./son.vue"
export default {
name: 'father',
components: {
son
},
props: {
msg: String
}
}
</script>
<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped>
.father {
border: #000000 1px solid;
}
</style>
son.vue
:
<template>
<div class="son">
in son:
<h1 v-for="(item,index) in msg" :key="index">{{item}}</h1>
</div>
</template>
<script>
export default {
name: 'son',
props: {
msg: Array
}
}
</script>
<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped>
.son {
border: red 1px solid;
margin: 5px;;
}
</style>
app.vue
:
<template>
<div id="app">
<fater msg="this is father"/>
</div>
</template>
<script>
import fater from './components/fater.vue'
export default {
name: 'app',
components: {
fater
}
}
</script>
<style>
#app {
font-family: 'Avenir', Helvetica, Arial, sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
text-align: center;
color: #2c3e50;
margin-top: 60px;
}
</style>
main.js
:
import Vue from 'vue'
import App from './App.vue'
Vue.config.productionTip = false
new Vue({
el: "#app",
render: h => h(App),
});
效果:
示例2(子组件向父组件传递参数)
father.vue
:
<template>
<div class="father">
in father : {{msg}}
<son :msg="sonList" @onEmitIndex="onEmitIndex"></son>
<p>{{currentIndex}}</p>
</div>
</template>
<script>
import son from "./son.vue"
export default {
name: 'father',
components: {
son
},
props: {
msg: String
},
data() {
return {
currentIndex: -1,
sonList: ['小白', '小红', '小蓝', '小绿']
}
},
methods: {
onEmitIndex(idx) {
this.currentIndex = idx
}
}
}
</script>
<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped>
.father {
border: #000000 1px solid;
}
</style>
son.vue
:
<template>
<div class="son">
<h3 v-for="(item, index) in msg" :key="index" @click="emitIndex(index)">{{index}} {{item}}</h3>
</div>
</template>
<script>
export default {
name: 'son',
props: {
msg: Array
},
methods: {
emitIndex(index) {
this.$emit('onEmitIndex', index)
}
}
}
</script>
<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped>
.son {
border: red 1px solid;
margin: 5px;
}
</style>
其他文件与上面的例子保持一致,效果如下:
当你点击子组件中的某一行时,会子组件中的行索引打印在父组件中。
6.2 vuex
6.2.0 搭建vuex环境:
可以直接在命令行输入以下命令安装插件
$ npm i vuex
也可以在项目的package.json
文件中的dependencies
属性下添加一行记录,然后执行npm install
更新项目的依赖
{
"name": "default",
"version": "0.1.0",
"private": true,
"scripts": {
"serve": "vue-cli-service serve",
"build": "vue-cli-service build"
},
"dependencies": {
"core-js": "^2.6.5",
"vue": "^2.6.10",
"vuex": "^3.1.0" //这是添加的依赖
},
"devDependencies": {
"@vue/cli-plugin-babel": "^3.8.0",
"@vue/cli-service": "^3.8.0",
"vue-template-compiler": "^2.6.10"
}
}
6.2.1 如果不用vuex
如果不用vuex,那么多个组件之间如果需要公用某一个变量,我们称之为state
,那么使用props/emit
是如何通信的呢
-
父子组件之间通信
-
兄弟组件之间通信
-
vuex通信
6.2.2 示例
目录结构:
App.vue
:
import Vue from 'vue'
import App from './App.vue'
import store from './store'
Vue.config.productionTip = false
new Vue({
el: '#app',
store,
render: h => h(App),
})
main.js
:
import Vue from 'vue'
import App from './App.vue'
import store from './store'
Vue.config.productionTip = false
new Vue({
el: '#app',
store,
render: h => h(App),
})
Father.vue
:
<template>
<div id="app">
<Father></Father>
<Son></Son>
<h1> IN FATHER</h1>
<h1>num = {{$store.state.num}}</h1><br />
<button @click="selfadd">加1</button><br />
<button @click="selfsub">减1</button><br />
</div>
</template>
<script>
import Father from './components/Father.vue'
import Son from './components/Son.vue'
export default {
name: 'app',
components: {
Father,
Son
},
methods: {
selfadd() {
this.$store.dispatch('selfadd', 1)
},
selfsub() {
this.$store.dispatch('selfsub', 1)
}
}
}
</script>
<style>
#app {
font-family: 'Avenir', Helvetica, Arial, sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
text-align: center;
color: #2c3e50;
margin-top: 60px;
padding: 5px;
border: #002B36 1px solid;
}
</style>
Son.vue
:
<template>
<div class="son">
<h1> IN SON</h1>
<h1>num = {{$store.state.num}}</h1><br />
</div>
</template>
<script>
export default {
name: 'Son'
}
</script>
<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped>
.son {
border: #0000FF 1px solid;
margin: 5px;
}
</style>
store/index.js
:
//这里存放vuex的核心代码
import Vuex from 'vuex'
import Vue from 'vue'
Vue.use(Vuex)
const actions = {
selfadd(context, value) {
console.log("actions is run", context, value)
context.commit('SELFADD', value)
},
selfsub(context, value) {
console.log("actions is run", context, value)
context.commit('SELFSUB', value)
}
}
const mutations = {
SELFADD(state, value) {
console.log("mutaions SELFADD is run", state, value)
state.num += value
},
SELFSUB(state, value) {
console.log("mutaions SELFSUB is run", state, value)
state.num -= value
}
}
const state = {
num: 0
}
export default new Vuex.Store({
actions,
mutations,
state
})
效果:在App
组件中操作vuex管理的变量num
,则所有使用到该变量的地方都发生了变化
7 路由
通过路由请求后端接口数据,所有这里使用axios
来作为ajax
工具。
7.1 安装vue-router
-
方法1
$ npm install vue-router //安装vue路由 $ npm install axios //安装axios
-
方法2
直接在项目的
package.json
文件中添加对应的依赖以及版本号{ "name": "default", "version": "0.1.0", "private": true, "scripts": { "serve": "vue-cli-service serve", "build": "vue-cli-service build" }, "dependencies": { "axios": "^0.24.0", //用来异步请求接口 "core-js": "^2.6.5", "vue": "^2.6.10", "vue-resource": "^1.5.3", "vue-router": "^3.5.3" //添加版本号以及依赖 }, "devDependencies": { "@vue/cli-plugin-babel": "^3.8.0", "@vue/cli-service": "^3.8.0", "vue-template-compiler": "^2.6.10" } }
7.2 示例
目录结构:
About.vue
:
<template>
<div class="about">
<h1>IN About</h1><br />
</div>
</template>
<script>
export default {
name: 'About',
}
</script>
<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped>
.about {
border: #002B36 1px solid;
margin: 5PX;;
}
</style>
GetUserInfo.vue
:
<template>
<div class="userinfo">
<h1>IN GetUserInfo</h1><br />
请求参数:{{this.$route.query.name}} //vue-router插件会给所有组件身上安装一个$route属性,该属性下有一个query用来存放query型参数
<h1>
userinfo :
<p v-if="hasInfo">{{ userinfo }}</p>
<p v-else>null</p>
</h1>
{{name}}
</div>
</template>
<script>
import axios from "axios"
export default {
name: 'GetUserInfo',
data() {
return {
userinfo: {},
hasInfo: false
}
},
mounted() {
axios.get('http://www.zhgblog.com:84/getUserInfo', {
params: {name: this.$route.query.name}
})
.then(
response => {
this.hasInfo = true
this.userinfo = response.data.data
console.log(response.data)
},
error => {
this.userinfo = error.message
console.log('error :' + error.message)
}
)
}
}
</script>
<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped>
.userinfo {
border: #000000 1px solid;
margin: 5PX;
;
}
</style>
main.js
:
import Vue from 'vue'
import App from './App.vue'
import router from './router/index.js'
Vue.config.productionTip = false
new Vue({
el: "#app",
router,
render: h => h(App)
})
App.vue
:
<template>
<div id="app">
IN APP<br />
<router-link to="/about" class='btn' active-class="active">about</router-link><br />
<router-link to="/get-user-info?name=vuetest" class='btn' active-class="active">getUserInfo</router-link>
<router-view></router-view>
</div>
</template>
<script>
import GetUserInfo from './components/GetUserInfo.vue'
import About from './components/About.vue'
export default {
name: 'app',
components: {
GetUserInfo
}
}
</script>
<style>
#app {
font-family: 'Avenir', Helvetica, Arial, sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
text-align: center;
color: #2c3e50;
margin-top: 60px;
border: #0000FF 2px solid;
}
.btn {
background-color: #F06431;
display: block;
color: #ffffff;
width: 80px;
height: 20px;
padding: 5px;
margin: 10px;
border: #0000FF 2px solid;
}
.active {
background-color: #002B36;
}
</style>
router/index.js
定义路由:
import Vue from "vue"
import VueRouter from "vue-router"
import About from '../components/About.vue'
import GetUserInfo from '../components/GetUserInfo.vue'
Vue.use(VueRouter)
export default new VueRouter({
routes: [
{
path: '/about', //路由路劲
component: About //渲染的组件
},
{
path: '/get-user-info',
component: GetUserInfo
}
]
})
效果:
-
默认情况下,此时鼠标没有点任何按钮,且从地址栏可以看出,
vue-router
已经开始工作 -
此时点击
about
按钮,此组件只是做一个跳转展示 -
此时点击
getUserInfo
按钮,该组件中通过axios
调用了用php
写的接口,通过get
请求回去postman请求结果:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-yAaXOPZs-1641734879400)(https://jums.club/images/article2/Screenshot_11.png)]
Reference
写在最后
欢迎大家关注鄙人的公众号【麦田里的守望者zhg】,让我们一起成长,谢谢。