vue 相关实例演示
开发环境
- nodejs
- 安装 vue-cli ( $
npm i --global vue-cli
) - 快速生成项目 $
vue init webpack appName
或vue init webpack-simple vue-demo01
- 安装 $
npm i
- 运行 $
npm run dev
vue 、vuex 、vue-router 实例演示
vue 中的相关注意事项
在vue中template 中 所有的内容要被一个根节点包含起来
data 函数中是 业务逻辑里面定义的数据
循环数据演示:
<ul>
<li v-for="item in list">{{item}}</li>
</ul>
- 绑定数据, 绑定html演示:
<div id="app">
<div v-bind:title="title"></div>
<img v-bind:src="url" />
<!-- 绑定属性还可以这样写 -->
<img :src="url" />
<div v-html="h2"></div>
<div v-text="msg"></div>
<div v-bind:class="{'red': flag, 'blue': !flag}">
我是一个div, v-bind 也可以省略 即:v-bind:class 或者 :class
</div>
<ul>
<!-- 循环, 让第一个变红 -->
<li v-for="(item, key) in list" :class="{'red':key===0, 'blue': key===1}"></li>
</ul>
<div v-bind:style="{'width': boxWidth + 'px'">
<span :style="{'color':'red'}"></span>
</div>
</div>
<script>
export default {
data() {
return {
title:"xy",
url:"xx",
msg:"I'm test";
h2:"<h2>Hello</h2>",
flag: true,
boxWidth:10
}
}
}
</script>
<style>
.red{
}
.blue{
}
</style>
vue 是一个MVVM的框架, model 改变影响视图, 视图改变影响model
vue 的双向数据绑定只能在表单元素中使用 input等, 使用 ref 来获取表单中的数据,演示:
<div id="app">
<h2>{{msg}}</h2>
<input type="text" v-model="msg" />
</div>
<button v-on:click="getMsg()">获取</button>
<button v-on:click="setMsg()">设置</button>
<!-- 另一种触发事件的方法 -->
<button @click="setMsg()">设置2</button>
<input type="text" v-model="msg" ref="userinfo" />
<script>
export default {
data() {
return {
msg: "I'm Msg"
}
},
// 自定义方法的地方
methods:{
// 获取
getMsg() {
return alert(this.msg);
},
// 设置
setMsg() {
this.msg = "I'm Msg setted!"
},
// refs方式获取input值
getInputValue() {
console.log(this.$refs.userinfo.value);
}
}
}
</script>
- 循环时的item和key
<ul>
<li v-for="(item, key) in list">
{{item}}
</li>
</ul>
- 页面上的传值处理
<!-- 直接在括号中传递 -->
<button @click="delete(1)">传值</button>
- 关于事件对象
<!-- 注意,这里可以传递事件对象和其他参数 -->
<button @click="eventFunc($event, arg1, arg2)">事件对象</button>
- 在vue中写sass,需要在脚手架生成时选择支持sass开发
<style lang="scss">
.box {
background:green;
.box-children {
color: red;
}
}
</style>
- 本地持久化存储的封装: 使用 localStorage 或 cookie
storage.js
var storage = {
set(key, value) {
localStorage.setItem(key, JSON.stringfy(value))
},
get(key) {
localStorage.getItem(key)
},
remove(key) {
localStorage.removeItem(key)
},
removeAll() {
localStorage.clear();
}
}
export default storage;
- vue的声明周期函数: 页面刷新就会触发的方法
export default {
/* 页面被加载 */
mounted() {
},
mounted() {
}
}
模块化组件: 头部,尾部,侧边栏的封装, 组件是vue最强大的功能之一,可扩展html元素, 封装可重用的代码
封装头部组件:在组件中写业务逻辑
<script>
export default {
data() {
return {
msg: 'header'
}
},
methods:{
run() {
alert(1);
}
}
}
</script>
<!-- scoped 是局部作用域 -->
<style lang="scss" scoped>
</style>
引入头部组件
<!-- 3. 使用组件 -->
<app-header></app-header>
<script>
// 1. 引入组件
import appHeader form '';
export default {
data() {
return {
msg: 'Hello'
}
},
// 2 . 挂载(或注册)组件
compontents:{
'app-header': appHeader
}
}
</script>
组件的组织
①、 通用组件: components
②、 子组件(不通用) : tpl声明周期的函数: 组件挂载, 数据监听, 更新, 和注销等事件触发的一系列过程的函数,这些方法叫做声明周期函数
<div>这里是Msg: {{msg}}</div>
<button @click="setMsg()">改变msg</button>
<script>
export default {
data() {
},
methods() {
setMsg() {
this.msg = "我是改变后的数据"
}
},
/* 实例创建之前 */
beforeCreate() {
},
/* 实例创建完成 */
created() {
}
/* 模板编译之前 */
beforeMount() {
}
/* 组件挂载,模板编译之后 */
mounted() {
},
/* 数据更新之前 */
beforeUpdated() {
},
/* 数据更新完毕 */
updated() {
},
/* 组件销毁之前 */
beforeDestroy() {
},
/* 组件销毁完成 */
destroyed() {
}
}
</script>
注意:请求数据和操作虚拟dom都会放在 mounted() 中, 注意声明周期函数和自定义methods()里面的方法是同级兄弟关系
- 注意:手工卸载组件, 会触发卸载和挂载组件
<v-header v-if="flag"></v-header>
<button @click="flag=!flag">挂载和卸载组件</button>
vue 的数据请求: vue-resource(官方提供的插件)), axios, fetch-jsonp
vue-resource: 【推荐】
①、 安装:yarn add vue-resource
②、 在main.js 中引入vueResource from ‘vue-resource’
③、 使用vue-resource : Vue.use(vueResource)
④、 在vue中请求数据
<button @click="getData">请求数据</button>
<script>
export default {
data() {
return {
list:[]
}
},
methods: {
// 请求数据
getData() {
var url = "";
this.$http.get(url)
.then((res)=>{
// 成功的回调
})
.catch((error)=>{
// 失败的回调
});
}
}
}
mounted() {
// 声明周期中调用getData方法
this.getData()
}
</script>
使用 axios来请求数据:
①、 安装: yarn add axios
②、 导入: import Axios from ‘axios’ 哪里用,哪里导入
③、 使用演示:
<script>
export default {
methods() {
getData() {
var url = "";
Axios.get(api)
.then(()=>{
})
.catch(()=>{
});
}
}
}
</script>
axios 不支持jsonp, fetch-jsonp 可支持jsonp ,详细查看 github
父子组件传值
父传子:
①、在父组件中给子组件绑定属性
<!-- 以下是传指令,方法和整个指令给子组件 -->
<v-header :title="Ftitle" :run="Frun" :home="this"></v-header>
<script>
export default {
data() {
return {
Ftitle: '标题'
}
}
methods() {
Frun() {
}
}
}
</script>
②、 在子组件中通过props接收父组件传过来的数据
<!-- 此处的 title 用的就是从props中拿到的值 -->
<h2> 我是头部组件 -- {{title}} </h2>
<button @click="run()"> 调用父组件的run方法 </button>
<button @click="getParent()">获取父组件的数据和方法</button>
<script>
export default {
data() {
return {
}
}
methods() {
/* 获取父组件的所有属性和方法 */
getParent() {
// 获取父组件的title
alert(this.title); // 此处的title是从props中拿到的,
alert(this.home.title); // 此处是从整个父组件中拿到的
this.home.run(); // 还可以直接调用父组件的方法
}
}
props:['title', 'run', 'home'] // 这里表示接受父组件传递过来的title
}
</script>
③、注意子组件和父组件定义的数据名不能冲突 不能父组件有msg,并传递给子组件, 然后子组件在data中定义相同的名称的数据
④、注意父组件不仅可以传递给子组件属性,还可传递方法
⑤、 除了直接传递,还可在子组件中验证父组件传递过来值得合法性, 基本不用
<script>
export default {
props:{
"title":String,
"run":Function, // 此处待验证
'home': Object // 此处待验证
}
}
</script>
父组件主动获取子组件的数据和方法
①、 调用子组件的时候定义ref
②、 在父组件中通过this.$refs.自定义的ref属性.数据/方法 来获取子组件的数据和方法
父组件:
<!-- 子组件 -->
<v-header ref="header"></v-header>
<button @click="getChildData()">获取子组件的数据和方法</button>
<script>
export default {
methods: {
getChildData() {
this.$refs.header.run()
console.log(this.$refs.header.msg);
}
}
}
</script>
子组件:
<script>
export default {
data() {
return {
msg: '子组件的msg';
}
}
methods: {
run() {
console.log("子组件的run");
}
}
}
</script>
子组件主动获取父组件的数据和方法
①、$
this.$parent.数据
②、 $this.$parent.方法
子组件中:
<button @click="getParentData()"></button>
<script>
export default {
methods() {
getParentData() {
alert(this.$parent.msg);
this.$parent.run(); // 调用父组件的run方法
}
}
}
</script>
非父子组件传值
方法一:借助父子关系来传递,不方便,通过爷爷等节点
方法二:通过事件广播的方式新建vue-event文件
import Vue from 'vue';
var event = new Vue();
export default event;
组件Homes中:广播数据
<button @click="emitNews()">给news组件广播数据</button>
<script>
import vueEvent from 'vue-event';
export default {
data() {
return {
msg: '我是home'
}
}
methods() {
emitNews() {
vueEvent.$emit('to-news', this.msg) // 广播数据
}
}
}
</script>
在news组件中接收数据
<script>
import vueEvent from 'vue-event';
export default {
mounted() {
vueEvent.$on('to-news', function(data) {
console.log(data);
})
}
}
</script>
方法三、通过vuex 进行数据传递,会在下面讲到
vue中的路由
①、 安装:yarn add vue-router
②、 引入main.js: import VueRouter from ‘vue-router’
③、 use 一下: Vue.use(VueRouter);
④、 配置路由: 创建组件,引入组件,定义路由,实例化路由,挂载路由,将写入App.vue中
⑤、 重定向和别名(默认跳转路由)
const routes = [
{
path:'*', redirect: '/' // 注意这里默认跳转到首页
}
]
在路由中动态传递参数
首先配置路由的时候
const routers = [
{path: '/content/:id', component: Content}
]
在router-link中
<!-- 写死的方式 -->
<router-link to="/content/123"><router-link>
<!-- 动态的方式 -->
<router-link :to="'/content/' + key" v-for="(item, key) in list"><router-link>
在content组件中获取id:
<script>
export default {
mounted() {
alert(this.$router.params.id); // 获取动态路由传值
}
}
</script>
使用get传值
在配置路由时
const routes = [
{
path:'/pcontent',
component: PContent
}
]
在router-link中
<router-link to="/pcontent?id=123"><router-link>
在pcontent模块中获取get传值
<script>
export default {
mounted() {
console.log(this.$router.query.id)
}
}
</script>
如果是循环方式,同动态传递
- 编程式导航、用javascript跳转页面
<button @click="goNews()">通过js跳转到新闻页面</button>
<script>
export default {
methods:{
goNews() {
this.$router.push({path:'news'})
// 或者
this.$router.push({path: '/content/495'})
}
}
}
</script>
关于命名路由的跳转
在配置路由时,添加name属性
const routers = [
{path:'/news',component:Content, name:'news'}
]
通过
this.$router.push({name:'news', params: {userId: 123}})
html5 模式和 hash模式的切换, 备注:这里可能需要后端来配置
在实例化vue-router的时候
const router = new VueRouter({
mode: 'history' // 这个是html5模式
})
- 路由的嵌套
/user
/user/profile
/user/login
在VueRouter中的配置
const router = new VueRouter({
routes:[
{
path: '/user',
component: User,
children: [
{
path:'profile', // 注意这里是没有斜杠的
component: UserProfile
},
{
path:'login'
component: UserLogin
}
]
}
]
})
在User组件中加上
<router-view></router-view>
一个路由里嵌入其他路由已完成
vuex 状态管理
a. 不同组件之间的数据共享问题,数据持久化
b. 页面之间传值之前用localStroage 和 sessionStorage
c. 小项目中不用vuex中,会增加复杂度安装 vuex : yarn add vuex
①、 在src目录中新建一个vuex的文件夹
②、 vuex文件夹里新建一个文件store.js
③、 在store.js中引入vuex,并且use
import Vue form 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
// state 在vuex中用于存储数据
var state = {
count:1
}
// mutations 里面放置方法, 主要用于改变state里面的数据
var mutations = {
// 增加
inCount() {
++state.count
}
}
// vuex 的核心: vuex 实例化 Vuex.store
const store = new VueX.Store({
state,
mutations,
})
export default store;
在Home首页模块改变state的值
<div>
<h3>首页</h3>
<div>{{this.$store.state.count}}</div>
</div>
<button @click="inCount()">增加数量</button>
<script>
// 引入 store
import store from 'vuex/store'
export default {
data() {
return {
}
},
// 注册store
store,
methods() {
// 改变vuex中的store中的数据
inCount() {
this.$store.commit('inCount'); // 调用store中定义的inCount方法, 改变state中的数据
}
}
}
</script>
vuex getter 正常情况下用不到
在改变数据时的操作, 计算属性: 即:改变state数据的时候会触发 getters里面的方法,获取新的值
var getters = {
computedCount: (state,getters) => {
return state.count * 2
}
}
const store = new Vuex.Store({
state,
mutations,
getters
})
在展示页面
<div>{{this.$store.state.count}}</div>
<div>{{this.$store.getters.computedCount}}</div>
只要改变store中的数据,那么就会调用getters中相关的方法,
这个基本用不到
action 类似于mutation
不同于mutation:
①、 Action 提交的是mutation, 而不是直接变更状态
②、 Action 可以包含任意异步操作
var actions = {
inMutationCount(context) {
/* 通过 context.commit 提交一个mutation */
context.commit('inCount'); // 表示执行mutations中的inCount方法,改变state中的数据
}
}
const store = new Vuex.Store({
state,
mutations,
getters,
actions
})
同样也需要将actions添加进入store
在外部通过dispatch来触发action中的方法
<script>
export default {
methods() {
inCount() {
this.$store.dispatch('inMutationCount');
}
}
}
</script>
- vuex 的模块化: https://vuex.vuejs.org/zh/guide/modules.html