方法一:使用 localStorage 存储数据
window.localStorage.setItem(key,value)
方法二:使用 vuex-persistedstate插件
vuex 存在一个痛点,就是刷新以后vuex里面存储的state就会被浏览器释放掉(state都是存储在内存中的)。
办法:
通过vuex-persistedstate插件,实现将数据存储到本地。
1.实现
import createPersistedState from 'vuex-persistedstate'
export default new Vuex.Store({
state:{},
getters:{},
actions:{},
mutations:{},
modules:{},
plugins: [createPersistedState()] //加上这个就可以了 //里面设置需要缓存的内容
})
API: https://www.npmjs.com/package/vuex-persistedstate
方法三: 使用vue-cookie插件
cookie 可以设置过期时间
import Vue from 'vue';在vue项目中,和后台交互获取数据这块,我们通常使用的是axios库,它是基于promise的http库,可运行在浏览器端和node.js中。他有很多优秀的特性,例如拦截请求和响应、取消请求、转换json、客户端防御cSRF等。
一 . 安装
npm install axios;
1
二 . 引入
在项目的src目录中,新建一个request文件夹,然后在里面新建一个http.js和一个api.js文件。http.js文件用来封装我们的axios,api.js用来统一管理我们的接口。
三 . 开始封装
在http.js中引入axios . vue及其他
import Axios from 'axios'; // 引入axios
import { Message, Loading, Notification } from 'element-ui'
import vue from 'vue';
1
2
3
http.js文件全部代码如下:
import Axios from 'axios';
import store from '../store';
import { Message, Loading, Notification } from 'element-ui'
import vue from 'vue';
// 环境的切换
if (process.env.NODE_ENV == 'development') {
Axios.defaults.baseURL = "http://10.230.39.58:33390/devops";
}
else if (process.env.NODE_ENV == 'production') {
Axios.defaults.baseURL = "http://10.230.39.58:33390/devops";
}
// request请求拦截器
Axios.defaults.withCredentials = true
vue.prototype.$axios = Axios
//请求超时时间
// Axios.defaults.timeout = 100000;
Axios.defaults.headers.get['Content-Type'] = "application/json"
Axios.interceptors.request.use(config => {
const Basic = sessionStorage.getItem("basicParam")
if (Basic) {
config.headers.Authorization = Basic ${Basic}
;
} else {
console.log("无校验值");
}
return config;
}, error => {
Promise.reject(error);
})
// respone返回拦截器
Axios.interceptors.response.use(
response => {
if (response.data.code !== 200) {
Notification.error({
title: '错误',
message: response.data.message
});
}
return response.data;
}, error => {
// Notification.error({
// title: '错误',
// message: '系统异常'
// });
console.log('err' + error);// for debug
return Promise.reject(error);
}
)
export default Axios;
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
api.js文件全部代码如下:
import axios from 'axios';
/
封装get方法
@param url
@param data
@returns {Promise}
*/
export function fetch(url, params = {}) {
return new Promise((resolve, reject) => {
axios.get(url, {
params: params
})
.then(response => {
resolve(response.data);
})
.catch(err => {
reject(err)
})
})
}
/*
封装post请求
@param url
@param data
@returns {Promise}
/
export function _post(url, data = {}) {
return new Promise((resolve, reject) => {
axios.post(url, data)
.then(response => {
console.log(response,
"response");
resolve(response);
}, err => {
reject(err)
})
})
}
/
vue 1.0.3 中 $set 函数是动态改变或添加一个 data 中的属性值时 属性 key 不可以使用纯数字。
例如:
var app = new Vue({
el:"#app",
data:{
test:{
k1:'v1',
k2:'v2'
}
},
methods:{
changeTestValue:function{
// 动态改变 test 中某一属性的值
var key = 'test.k1'; // 改变 test 属性中的 k1 的值
this.$set(key,'changev1'); // 此处执行没有问题
// 改变 整个 test 的值可以使用
this.$set('test',{k1:'change-demo-v1',k2:'change-demo-v2'}); // 此处执行没有问题
// 动态给 test 增加一个属性 k3
this.$set('test.k3','test-add-value3'); // 此处执行没有问题
// 此处有坑 当你的 属性为全数字的时候,则 函数无效,不报错,但是也添加不上值。
// 例如
this.$set('test.123','test-add-123'); // 此处执行不报错,但是也没有效果。
// 所以在使用老版本vue的时候尽量避免 属性 key 未纯数字,或其他特殊字符。
}
}
});
除了这个坑以外还有另外一个坑,不过没有具体试验,
watch 监听某一值得变化,好像有点问题, 实际结果是只要 data 中的任意一个值发生变化都会被捕捉到。
最后还是使用 vue 2.x 以上版本吧,bug 少很多。
另外 $set 函数在2.x 中使用方式有所变化。
this.$set(target,key,obj);
target 对象类型,是需要赋值或修改的对象,
key 是字符串类型, 是 target 对象的属性
obj 可以是字符串,可以是对象类型,是 你要修改的或增加的值
蓝蓝设计( www.lanlanwork.com )是一家专注而深入的界面设计公司,为期望卓越的国内外企业提供卓越的UI界面设计、BS界面设计 、 cs界面设计 、 ipad界面设计 、 包装设计 、 图标定制 、 用户体验 、交互设计、 网站建设 、平面设计服务。
概述
Vue 2.x 及以前的高阶组件的组织形式或多或少都会面临一些问题,特别是在需要处理重复逻辑的项目中,一旦开发者组织项目结构组织得不好,组件代码极有可能被人诟病为“胶水代码”。而在 Vue 2.x 及之前的版本,解决此类问题的办法大致是下面的方案:
mixin
函数式组件
slots
笔者维护的项目也需要处理大量复用逻辑,在这之前,笔者一直尝试使用mixin的方式来实现组件的复用。有些问题也一直会对开发者和维护者造成困惑,如一个组件同时mixin多个组件,很难分清对应的属性或方法写在哪个mixin里。其次,mixin的命名空间冲突也可能造成问题。难以保证不同的mixin不用到同一个属性名。为此,官方团队提出函数式写法的意见征求稿,也就是RFC:Function-based component API。使用函数式的写法,可以做到更灵活地复用组件,开发者在组织高阶组件时,不必在组件组织上考虑复用,可以更好地把精力集中在功能本身的开发上。
注:本文只是笔者使用vue-function-api提前体验 Vue Function API ,而这个 API 只是 Vue 3.0 的 RFC,而并非与最终 Vue 3.x API 一致。发布后可能有不一致的地方。
在 Vue 2.x 中使用
要想提前在Vue 2.x中体验 Vue Function API ,需要引入vue-function-api,基本引入方式如下:
import Vue from 'vue';
import { plugin as VueFunctionApiPlugin } from 'vue-function-api';
Vue.use(VueFunctionApiPlugin);
基本组件示例
先来看一个基本的例子:
<template>
<div>
<span>count is {{ count }}</span>
<span>plusOne is {{ plusOne }}</span>
<button @click="increment">count++</button>
</div>
</template>
<script>
import Vue from 'vue';
import { value, computed, watch, onMounted } from 'vue-function-api';
export default {
setup(props, context) {
// reactive state
const count = value(0);
// computed state
const plusOne = computed(() => count.value + 1);
// method
const increment = () => {
count.value++;
};
// watch
watch(
() => count.value 2,
val => {
console.log(`count 2 is ${val});<br /> }<br /> );<br /> // lifecycle<br /> onMounted(() => {<br /> console.log(
mounted);<br /> });<br /> // expose bindings on render context<br /> return {<br /> count,<br /> plusOne,<br /> increment,<br /> };<br /> },<br /> };<br /> </script><br /> 详解<br /> setup<br /> setup函数是Vue Function API 构建的函数式写法的主逻辑,当组件被创建时,就会被调用,函数接受两个参数,分别是父级组件传入的props和当前组件的上下文context。看下面这个例子,可以知道在context中可以获取到下列属性值<br /> <br /> const MyComponent = {<br /> props: {<br /> name: String<br /> },<br /> setup(props, context) {<br /> console.log(props.name);<br /> // context.attrs<br /> // context.slots<br /> // context.refs<br /> // context.emit<br /> // context.parent<br /> // context.root<br /> }<br /> }<br /> value & state<br /> value函数创建一个包装对象,它包含一个响应式属性value:<br /> <br /> <br /> <br /> 那么为何要使用value呢,因为在JavaScript中,基本类型并没有引用,为了保证属性是响应式的,只能借助包装对象来实现,这样做的好处是组件状态会以引用的方式保存下来,从而可以被在setup中调用的不同的模块的函数以参数的形式传递,既能复用逻辑,又能方便地实现响应式。<br /> <br /> 直接获取包装对象的值必须使用.value,但是,如果包装对象作为另一个响应式对象的属性,Vue内部会通过proxy来自动展开包装对象。同时,在模板渲染的上下文中,也会被自动展开。<br /> <br /> import { state, value } from 'vue-function-api';<br /> const MyComponent = {<br /> setup() {<br /> const count = value(0);<br /> const obj = state({<br /> count,<br /> });<br /> console.log(obj.count) // 作为另一个响应式对象的属性,会被自动展开<br /> <br /> obj.count++ // 作为另一个响应式对象的属性,会被自动展开<br /> count.value++ // 直接获取响应式对象,必须使用.value<br /> <br /> return {<br /> count,<br /> };<br /> },<br /> template:
<button @click="count++">{{ count }}</button>,<br /> };<br /> 如果某一个状态不需要在不同函数中被响应式修改,可以通过state创建响应式对象,这个state创建的响应式对象并不是包装对象,不需要使用.value来取值。<br /> <br /> watch & computed<br /> watch和computed的基本概念与 Vue 2.x 的watch和computed一致,watch可以用于追踪状态变化来执行一些后续操作,computed用于计算属性,用于依赖属性发生变化进行重新计算。<br /> <br /> computed返回一个只读的包装对象,和普通包装对象一样可以被setup函数返回,这样就可以在模板上下文中使用computed属性。可以接受两个参数,第一个参数返回当前的计算属性值,当传递第二个参数时,computed是可写的。<br /> <br /> import { value, computed } from 'vue-function-api';<br /> <br /> const count = value(0);<br /> const countPlusOne = computed(() => count.value + 1);<br /> <br /> console.log(countPlusOne.value); // 1<br /> <br /> count.value++;<br /> console.log(countPlusOne.value); // 2<br /> <br /> // 可写的计算属性值<br /> const writableComputed = computed(<br /> // read<br /> () => count.value + 1,<br /> // write<br /> val => {<br /> count.value = val - 1;<br /> },<br /> );<br /> watch第一个参数和computed类似,返回被监听的包装对象属性值,不过另外需要传递两个参数:第二个参数是回调函数,当数据源发生变化时触发回调函数,第三个参数是options。其默认行为与 Vue 2.x 有所不同:<br /> <br /> lazy:是否会在组件创建时就调用一次回调函数,与 Vue 2.x 相反,lazy默认是false,默认会在组件创建时调用一次。<br /> deep:与 Vue 2.x 的 deep 一致<br /> flush:有三个可选值,分别为 'post'(在渲染后,即nextTick后才调用回调函数),'pre'(在渲染前,即nextTick前调用回调函数),'sync'(同步触发)。默认值为'post'。<br /> // double 是一个计算包装对象<br /> const double = computed(() => count.value * 2);<br /> <br /> watch(double, value => {<br /> console.log('double the count is: ', value);<br /> }); // -> double the count is: 0<br /> <br /> count.value++; // -> double the count is: 2<br /> 当watch多个被包装对象属性时,参数均可以通过数组的方式进行传递,同时,与 Vue 2.x 的vm.$watch一样,watch返回取消监听的函数:<br /> <br /> const stop = watch(<br /> [valueA, () => valueB.value],<br /> ([a, b], [prevA, prevB]) => {<br /> console.log(
a is: ${a});<br /> console.log(
b is: ${b});<br /> }<br /> );<br /> <br /> stop();<br /> 注意:在RFC:Function-based component API初稿中,有提到effect-cleanup,是用于清理一些特殊情况的副作用的,目前已经在提案中被取消了。<br /> <br /> 生命周期<br /> 所有现有的生命周期都有对应的钩子函数,通过onXXX的形式创建,但有一点不同的是,destoryed钩子函数需要使用unmounted代替:<br /> <br /> import { onMounted, onUpdated, onUnmounted } from 'vue-function-api';<br /> <br /> const MyComponent = {<br /> setup() {<br /> onMounted(() => {<br /> console.log('mounted!');<br /> });<br /> onUpdated(() => {<br /> console.log('updated!');<br /> });<br /> // destroyed 调整为 unmounted<br /> onUnmounted(() => {<br /> console.log('unmounted!');<br /> });<br /> },<br /> };<br /> 一些思考<br /> 上面的详解部分,主要抽取的是 Vue Function API 的常见部分,并非RFC:Function-based component API的全部,例如其中的依赖注入,TypeScript类型推导等优势,在这里,由于篇幅有限,想要了解更多的朋友,可以点开RFC:Function-based component API查看。个人也在Function-based component API讨论区看到了更多地一些意见:<br /> <br /> 由于底层设计,在setup取不到组件实例this的问题,这个问题在笔者尝试体验时也遇到了,期待正式发布的 Vue 3.x 能够改进这个问题。<br /> <br /> 对于基本类型的值必须使用包装对象的问题:在 RFC 讨论区,为了同时保证TypeScript类型推导、复用性和保留Vue的数据监听,包装属性必须使用.value来取值是讨论最激烈的<br /> <br /> 关于包装对象value和state方法命名不清晰可能导致开发者误导等问题,已经在Amendment proposal to Function-based Component API这个提议中展开了讨论:<br /> <br /> setup() {<br /> const state = reactive({<br /> count: 0,<br /> });<br /> <br /> const double = computed(() => state.count * 2);<br /> <br /> function increment() {<br /> state.count++;<br /> }<br /> <br /> return {<br /> ...toBindings(state), // retains reactivity on mutations made to
state`
double,
increment,
};
}
引入reactive API 和 binding API,其中reactive API 类似于 state API , binding API 类似于 value API。
之前使用的方法名state在 Vue 2.x 中可能被用作组件状态对象,导致变量命名空间的冲突问题,团队认为将state API 更名为 reactive 更为优雅。开发者能够写出const state = ... ,然后通过state.xxxx这种方式来获取组件状态,这样也相对而言自然一些。
value方法用于封装基本类型时,确实会出现不够优雅的.value的情况,开发者可能会在直接对包装对象取值时忘记使用.value,修正方案提出的 reactive API,其含义是创建响应式对象,初始化状态state就使用reactive创建,可保留每项属性的getter和setter,这么做既满足类型推导,也可以保留响应式引用,从而可在不同模块中共享状态值的引用。
但reactive可能导致下面的问题,需要引入binding API。 解决,如使用reactive创建的响应式对象,对其使用拓展运算符...时,则会丢失对象的getter和setter,提供toBindings方法能够保留状态的响应式。
当然,目前 Vue Function API 还处在讨论阶段,Vue 3.0 还处在开发阶段,还是期待下半年 Vue 3.0 的初版问世吧,希望能给我们带来更多的惊喜。
一、搭建cli
1.事先安装好cnpm(淘宝镜像)
npm install -g cnpm --registry=https://registry.npm.taobao.org
1
2.cnpm install -g vue-cli
全局安装vue脚手架工具。(下载一次就好)
3.vue init webpack your_project_name
创建一个脚手架项目(每次创建需要)
eg:这时在命令行中有需要你填的信息{
你的项目名;
你的项目描述;
还有你想是否下载的插件(y/n);
}
4.使用 npm run dev来运行项目
就这样,一个简单的vue开发项目模板就这样下载完成了。
eg:
i 是install 的简写。
全局安装依赖:
cnpm i 依赖名
1
局部安装依赖:
cnpm i -D 依赖名
1
二、vue-router
一般事先安装模板时,已经安装上了。
可以查看package.json中。
如果没有安装
cnpm i -D vue-router
1
安装好之后,在src目录中会生成一个router目录,里面放着index.js,
一般有两种配置
第一种:
import Vue from 'vue';
import Router from 'vue-router';
Vue.use(Router);
export default new Router({
routes: [
// 一进入就显示页面
{
path: '/',
redirect: '/index'
},
{
path: '/',
component: pather => require(['../components/common/bodys.vue'], pather),
meta: { title: '主体' },
children:[
{
path: '/index',
component: pather => require(['../components/page/index.vue'], pather),
meta: { title: '系统首页' }
},
{
path: '/biaoge',
component: pather => require(['../components/page/biaoge.vue'], pather),
meta: { title: '基础表格' }
},
{
path: '/Tab',
component: pather => require(['../components/page/Tab.vue'], pather),
meta: { title: 'tab选项卡' }
},
{
path: '/jibenbiaodan',
component: pather => require(['../components/page/jibenbiaodan.vue'], pather),
meta: { title: '基本表单' }
},
{
path: '/fuwenben',
component: pather => require(['../components/page/fuwenben.vue'], pather),
meta: { title: '富文本编辑器' }
},
{
path: '/bianjiqi',
component: pather => require(['../components/page/bianjiqi.vue'], pather),
meta: { title: 'markdown编辑器' }
},
{
path: '/shangchuan',
component: pather => require(['../components/page/shangchuan.vue'], pather),
meta: { title: '文件上传' }
},
{
path: '/scharts',
component: pather => require(['../components/page/scharts.vue'], pather),
meta: { title: 'schart图表' }
},
{
path: '/tuozhuai',
component: pather => require(['../components/page/tuozhuai.vue'], pather),
meta: { title: '拖拽列表' }
},
{
path: '/quanxianceshi',
component: pather => require(['../components/page/quanxianceshi.vue'], pather),
meta: { title: '权限测试', permission: true }
}
]
},
{
path: '/login',
component: pather => require(['../components/page/login.vue'], pather)
},
{
path: '/cuowu404',
component: pather => require(['../components/page/cuowu404.vue'], pather)
},
{
path: '/cuowu403',
component: pather => require(['../components/page/cuowu403.vue'], pather)
},
{
path: '*',
redirect: '/404'
}
],
// 去掉#号
mode:"history"
})
第二种:
import Vue from 'vue'
import Router from 'vue-router'
import HelloWorld from '@/components/HelloWorld'
Vue.use(Router)
export default new Router({
routes: [
{
path: '/',
name: 'HelloWorld',
component: HelloWorld
}
]
})
三、axios
先安装
cnpm i -D axios
1
然后在main.js写入
import axios from 'axios'
Vue.prototype.$axios = axios
1
2
3
这样就可以在组件中使用axios 获取数据了
loadData(){
this.$axios.get(['https://free-api.heweather.com/v5/weather?city=qingdao&key=1b47b16e4aa545eaa55a66f859ac0089'])
.then((response) => {
// success
console.log(response.data);
})
.catch((error) => {
//error
console.log(error);
})
},
四、vuex
1、安装
cnpm i -D vuex
1
2、然后需要手动创建一个文件夹store在src目录当中,
接着在store文件夹中创建store.js
例:
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
export default new Vuex.Store({
state: {
count: 0
},
mutations: {
increment: state => state.count++,
decrement: state => state.count--,
}
})
1
2
3
4
5
6
7
8
9
10
11
12
13
3、然后在main.js引入注册
import Vuex from 'vuex'
import store from './store/store'
Vue.use(Vuex)
new Vue({
el: '#app',
router,
store,
components: { App },
template: '<App/>'
})
比如在headers.vue使用vuex
<template>
<div class="headers">
<p>{{count}}</p>
<button @click="increment">+</button>
<button @click="decrement">-</button>
</div>
</template>
<script>
import { mapState } from 'vuex'
export default {
name: 'headers',
data () {
return {
msg: 'Welcome to Your Vue.js App'
}
},
methods: {
increment(){
this.$store.commit('increment')
},
decrement(){
this.$store.commit('decrement')
}
},
computed:{
count(){
return this.$store.state.count
},
}
}
</script>
<style scoped lang="scss" >
</style>
五、sass
1、需要安装sass
(1)安装node-sass
(2)安装sass-loader
(3)安装style-loader 有些人安装的是 vue-style-loader 其实是一样的!
cnpm install node-sass --save-dev
cnpm install sass-loader --save-dev
cnpm install style-loader --save-dev
1
2
3
2、接着需要更改build文件夹下面的webpack.base.config.js
'use strict'
const path = require('path')
const utils = require('./utils')
const config = require('../config')
const vueLoaderConfig = require('./vue-loader.conf')
function resolve (dir) {
return path.join(dirname, '..', dir)
}
module.exports = {
context: path.resolve(dirname, '../'),
entry: {
app: './src/main.js'
},
output: {
path: config.build.assetsRoot,
filename: '[name].js',
publicPath: process.env.NODE_ENV === 'production'
? config.build.assetsPublicPath
: config.dev.assetsPublicPath
},
resolve: {
extensions: ['.js', '.vue', '.json'],
alias: {
'vue$': 'vue/dist/vue.esm.js',
'@': resolve('src'),
}
},
module: {
rules: [
{
test: /.vue$/,
loader: 'vue-loader',
options: vueLoaderConfig
},
{
test: /.js$/,
loader: 'babel-loader',
include: [resolve('src'), resolve('test'), resolve('node_modules/webpack-dev-server/client')]
},
{
test: /.(png|jpe?g|gif|svg)(\?.)?$/,
loader: 'url-loader',
options: {
limit: 10000,
name: utils.assetsPath('img/[name].[hash:7].[ext]')
}
},
{
test: /.(mp4|webm|ogg|mp3|wav|flac|aac)(\?.)?$/,
loader: 'url-loader',
options: {
limit: 10000,
name: utils.assetsPath('media/[name].[hash:7].[ext]')
}
},
{
test: /.(woff2?|eot|ttf|otf)(\?.*)?$/,
loader: 'url-loader',
options: {
limit: 10000,
name: utils.assetsPath('fonts/[name].[hash:7].[ext]')
}
},
{ //从这一段上面是默认的!不用改!下面是没有的需要你手动添加,相当于是编译识别sass!
test: /.scss$/,
loaders: ["style", "css", "sass"]
}
]
},
node: {
// prevent webpack from injecting useless setImmediate polyfill because Vue
// source contains it (although only uses it if it's native).
setImmediate: false,
// prevent webpack from injecting mocks to Node native modules
// that does not make sense for the client
dgram: 'empty',
fs: 'empty',
net: 'empty',
tls: 'empty',
child_process: 'empty'
}
}
3、在你需要使用sass的地方写入即可
<style lang="scss" scoped="" type="text/css">
$primary-color: #333;
body {
color: $primary-color;
}
</style>
六、vue UI库
这里已著名的Element组件库为例
https://element.eleme.cn/#/zh-CN/component/carousel
1、安装
npm i element-ui -S
1
2、使用
在main.js写入
import ElementUI from 'element-ui'
import 'element-ui/lib/theme-chalk/index.css'
Vue.use(ElementUI)
1
2
3
4
3、然后在组件使用就可以了
例:轮播图
<template>
<el-carousel indicator-position="outside">
<el-carousel-item v-for="item in 4" :key="item">
<h3>{{ item }}</h3>
</el-carousel-item>
</el-carousel>
</template>
<style>
.el-carouselitem h3 {
color: #475669;
font-size: 18px;
opacity: 0.75;
line-height: 300px;
margin: 0;
}
.el-carouselitem:nth-child(2n) {
background-color: #99a9bf;
}
.el-carousel__item:nth-child(2n+1) {
background-color: #d3dce6;
}
</style>
蓝蓝设计( www.lanlanwork.com )是一家专注而深入的界面设计公司,为期望卓越的国内外企业提供卓越的UI界面设计、BS界面设计 、 cs界面设计 、 ipad界面设计 、 包装设计 、 图标定制 、 用户体验 、交互设计、 网站建设 、平面设计服务。
如果您想订阅本博客内容,每天自动发到您的邮箱中, 请点这里
话不多说,直接上问题图片
这里确认按钮是fixed布局 bottom:0 弹出键盘之后按钮被顶到了键盘上面
网上搜到的解决方案有两种,
一种是监听页面高度(我采用的这种)
一种是监听软键盘事件(ios和安卓实现方式不同,未采用)
下面是实现代码
data() {
return {
docmHeight: document.documentElement.clientHeight ||document.body.clientHeight,
showHeight: document.documentElement.clientHeight ||document.body.clientHeight,
hideshow:true //显示或者隐藏footer
}
},
watch: {
//监听显示高度
showHeight:function() {
if(this.docmHeight > this.showHeight){
//隐藏
this.hideshow=false
}else{
//显示
this.hideshow=true
}
}
},
mounted() {
//监听事件
window.onresize = ()=>{
return(()=>{
this.showHeight = document.documentElement.clientHeight || document.body.clientHeight;
})()
}
},
<div class="bottom" v-show="hideshow">
<div class="btn">
确认操作
</div>
</div>
我这里使用的是方法是:当键盘弹出时,将按钮隐藏。如果必须出现按钮的话,可以修改按钮回归到正常的流中。
蓝蓝设计( www.lanlanwork.com )是一家专注而深入的界面设计公司,为期望卓越的国内外企业提供卓越的UI界面设计、BS界面设计 、 cs界面设计 、 ipad界面设计 、 包装设计 、 图标定制 、 用户体验 、交互设计、网站建设 、平面设计服务。
如果您想订阅本博客内容,每天自动发到您的邮箱中, 请点这里
现在我有如下需求,子组件 <user /> 中此时有一条用户的信息(userInfo);我要在父组件通过插槽展示这个用户的姓名(userInfo.name);
注意:这里的父组件并没有这个用户的信息,子组件中有,如果直接在父组件{{userInfo.name}} 获取这条信息是获取不到的;因为,只有 <user /> 组件可以访问到 userInfo,而我们提供的内容是在父组件渲染的;
模板在哪写,就是用哪里的变量,跟插槽用在哪无关
模板是在父组件中写好,被编译过后,传到子组件的插槽中的
为了让父组件的插槽内容可以读取到子组件的数据,我们可以将userInfo 作为一个 <slot> 元素的特性绑定上去;
// 子组件
const card = {
data() {
return {
userInfo: {name: '宫鑫'}
}
},
template: `
<div class='card'>
<!-- 在插槽上绑定子组件的数据 -->
<slot :userInfo="userInfo"/>
</div>
`
};
绑定在 元素上的特性被称为插槽 prop。现在在父级作用域中,我们可以给v-slot带一个值来定义我们提供的插槽 prop 的名字:
// 父组件
template: `
<div>
<card>
<template v-slot:default="userInfo">
用户姓名: {{userInfo}}
</template>
</card>
</div>
`
// 输出:
// 用户姓名: { "userInfo": { "name": "宫鑫" } }
蓝蓝设计( www.lanlanwork.com )是一家专注而深入的界面设计公司,为期望卓越的国内外企业提供卓越的UI界面设计、BS界面设计 、 cs界面设计 、 ipad界面设计 、 包装设计 、 图标定制 、 用户体验 、交互设计、 网站建设 、平面设计服务。
如果您想订阅本博客内容,每天自动发到您的邮箱中, 请点这里
全局组件和局部组件
* 1.先定义组件 Vue.component('组件名', { 组件模板对象 })
* 注意: 组件名不要使用原生的标签名, 若组件名定义时用的是驼峰命名法, 则调用时用中划线分割后小写
* 例如: 组件-->mtText 使用时--> <my-text></my-text>
* 2.配置组件的模板 注意: 组件的模板内容有且只有一个根元素
* 3.在视图层里调用 ,用双标签
* 4.组件是一个独立的作用域, 也可以看成一个特殊的vue实例, 可以有data, methods,computed等等
* 注意: 组件的data是函数, 函数中需要返回一个对象作为组件的data
全局组件案例
<body>
<div id="app">
<my-component></my-component>
</div>
<script src="lib/vue-2.4.0.js"></script>
<script>
//全局组件
Vue.component('myComponent',{
//1.组件的内容/模板
template: '<div><div>头部组件</div><h1 @click="fn">呵呵{{msg}}</h1></div>',
data(){
return {
msg:'hello,组件'
}
},
methods:{
fn(){
console.log(this.msg);
}
}
})
let vm = new Vue({
el:"#app",
data:{
},
methods:{
},
})
</script>
</body>
局部组件案例
<body>
<div id="app">
<my-component></my-component>
<my-test></my-test>
</div>
<template id="box1">
<h1>haha</h1>
</template>
<template id="box2">
<div>
<ul>
<li v-for="item in arr">
{{ item }}
</li>
</ul>
</div>
</template>
<script src="lib/vue-2.4.0.js"></script>
<script>
let vm = new Vue({
el:"#app",
data:{
},
methods:{
},
//局部子组件
components:{
// 组件名: {配置项}
"myComponent":{
template:'#box1',
data(){
return {
msg:"哈哈"
}
}
},
"myTest":{
template:"#box2",
data(){
return {
arr:[1,2,3,4]
}
}
}
}
})
</script>
</body>
组件切换:法一
<body>
<div id="app">
<a href="" @click.prevent="flag=true">登录</a>
<a href="" @click.prevent="flag=false">注册</a>
<login v-if="flag"></login>
<register v-else="flag"></register>
</div>
<script src="lib/vue-2.4.0.js"></script>
<script>
Vue.component("login",{
template:"<h1>登录组件</h1>"
})
Vue.component("register",{
template:"<h1>注册组件</h1>"
})
let vm = new Vue({
el:"#app",
data:{
flag: false
},
methods:{
},
})
</script>
</body>
组件切换:法二
<style>
.red{
color:red;
}
.v-enter{
opacity:0;
transform: translateX(150px);
}
.v-leave-to{
opacity:0;
transform: translateX(-150px);
}
.v-enter-active,
.v-leave-active{
transition: all 0.5s;
position: absolute;
}
</style>
</head>
<body>
<div id="app">
<a href="" :class="{red: flag=='login'}" @click.prevent="flag='login'">登录</a>
<a href="" :class="{red: flag=='register'}" @click.prevent="flag='register'">注册</a>
<!-- vue提供了一个标签 component标签(理解为一个占位符), 用来展示对应名称的组件 :is属性设置指定的组件名 -->
<transition>
<component :is="flag"></component>
</transition>
</div>
<script src="lib/vue-2.4.0.js"></script>
<script>
Vue.component("login",{
template:"<h1>登录组件</h1>"
})
Vue.component("register",{
template:"<h1>注册组件</h1>"
})
let vm = new Vue({
el:"#app",
data:{
flag: "login"
},
methods:{
},
})
</script>
</body>
父组件向子组件传值
<body>
<div id="app">
<my-component :fromfather="father"></my-component>
</div>
<template id="box1">
<h1 @click="change">
{{ fromfather }}
子组件的数据
</h1>
</template>
<template id="grandSon">
<h1>孙子组件的数据</h1>
</template>
<!--1.子组件不能访问父组件的数据
2. 解决办法: ①在引用子组件时, 通过属性绑定 v-bind方法, 把需要传递给子组件的数据以绑定的形式传过来
② 在子组件配置项里添加 props: ['传递过来的数据']-->
<script src="lib/vue-2.4.0.js"></script>
<script>
let vm = new Vue({
el:"#app",
data:{
father:'啊~~这是父组件的数据'
},
methods:{
},
//局部子组件
components:{
// 组件名: {配置项}
"myComponent":{
template:'#box1',
data(){
return {
msg:"哈哈"
}
},
//在子组件配置项里添加 props: ['传递过来的数据']
//注意: 组件中所有的props中的数据, 都是通过父组件传递给子组件的, props中的数据是只读, 无法修改
props:['fromfather'],
methods:{
change(){
// this.fromfather = "被修改了"
}
},
//局部子子组件
components:{
'grandSon':{
template:'#grandSon'
}
}
}
}
})
</script>
</body>
蓝蓝设计( www.lanlanwork.com )是一家专注而深入的界面设计公司,为期望卓越的国内外企业提供卓越的UI界面设计、BS界面设计 、 cs界面设计 、 ipad界面设计 、 包装设计 、 图标定制 、 用户体验 、交互设计、 网站建设 、平面设计服务。
如果您想订阅本博客内容,每天自动发到您的邮箱中, 请点这里
方式一
<!--1.1使用Vue.extend来创建全局的Vue组件--> var tem1 = Vue.extend({
template:'<h3>这是使用 Vue.extend 创建的组件</h3>' //指定组件要展示的HTML结构
}); <!--1.2使用Vue.component('组件名称',创建出来的组件模板对象)--> Vue.component('myTem1',tem1);
/* <!--注意--> 使用 Vue.component() 定义全局组件的时候,
组件名称使用 驼峰命名,则在引用组件的时候,需要把大写改为小写,并且用 '-'将单词连接
组件名称不适用驼峰命名,则直接拿名称来使用即可
*/ <!--组合方式--> Vue.component('myTem1',Vue.extend({
template : '<h3>这是使用 Vue.extend 创建的组件</h3>'
})) <div id="app"> <!-- 如果要使用组件,直接把组件的名称以 HTML 标签的形式,引入到页面中--> <my-tem1> </my-tem1> </div>
方式二
直接使用Vue.component()
Vue.component('mycom2',{
template : '<h3>这是使用 Vue.component 创建的组件</h3>' })
但是这样写会有一个问题:
<!--在h3标签后紧接一个span标签的话就会出问题了--> <h3>这是使用 Vue.component 创建的组件</h3> <span>123</span>
这个问题是在 组件template属性指向的模板内容,必须有且只能有唯一的一个根元素
所以修改代码如下:
Vue.component('mycom2',{
template :
'<div> <h3>这是使用 Vue.component 创建的组件</h3> <span>123</span> </div>'
})
运行结果如下:
不过这种方式也有一个瑕疵,就是template
属性的值是HTML标签,而在软件中,并没有智能提示
,容易出错,若使用这种方式,需要仔细,避免出错
方式三
<!--1.定义组件:--> Vue.component('mycom3',{
template : '#tem1'
}); <!--2.在被控制的 #app 外面使用 template 元素,定义组建的HTML模板结构--> <div id="app"> <!--3. 引用组件 --> <mycom3></mycom3> </div> <template id="tem1"> <div> <h1>这是 template 元素</h1> <span>这种方式好用</span> </div> </template>
运行结果如下:
这是Vue创建组件(全局)的3种方式,其实相差不多,希望对大家有所帮助
如果您想订阅本博客内容,每天自动发到您的邮箱中, 请点这里
本组件基于element-ui 的图标库(星星图标)
第一步:
vue + webpack + element-ui 框架
第二步:
创建Rate.vue文件,实现双向绑定分数
第三部:
使用组件
在app.vue中引入组件
组件
说明
代码
import Rate from './components/Rate'
demo演示
蓝蓝 http://www.lanlanwork.com